Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: media/audio/win/audio_device_listener_win.cc

Issue 1248543002: Remove device change deduplication based on device id. (Closed) Base URL: http://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix tests. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/audio/win/audio_device_listener_win.h" 5 #include "media/audio/win/audio_device_listener_win.h"
6 6
7 #include <Audioclient.h> 7 #include <Audioclient.h>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
11 #include "base/system_monitor/system_monitor.h" 11 #include "base/system_monitor/system_monitor.h"
12 #include "base/time/default_tick_clock.h"
12 #include "base/win/scoped_co_mem.h" 13 #include "base/win/scoped_co_mem.h"
13 #include "base/win/windows_version.h" 14 #include "base/win/windows_version.h"
14 #include "media/audio/win/core_audio_util_win.h" 15 #include "media/audio/win/core_audio_util_win.h"
15 16
16 using base::win::ScopedCoMem; 17 using base::win::ScopedCoMem;
17 18
18 namespace media { 19 namespace media {
19 20
20 static std::string FlowToString(EDataFlow flow) { 21 static std::string FlowToString(EDataFlow flow) {
21 return (flow == eRender) ? "eRender" : "eConsole"; 22 return (flow == eRender) ? "eRender" : "eConsole";
(...skipping 23 matching lines...) Expand all
45 HRESULT hr = CoreAudioUtil::GetDeviceName(device.get(), &device_name); 46 HRESULT hr = CoreAudioUtil::GetDeviceName(device.get(), &device_name);
46 if (FAILED(hr)) { 47 if (FAILED(hr)) {
47 DVLOG(1) << "Failed to retrieve the device id: " << std::hex << hr; 48 DVLOG(1) << "Failed to retrieve the device id: " << std::hex << hr;
48 return std::string(); 49 return std::string();
49 } 50 }
50 51
51 return device_name.unique_id; 52 return device_name.unique_id;
52 } 53 }
53 54
54 AudioDeviceListenerWin::AudioDeviceListenerWin(const base::Closure& listener_cb) 55 AudioDeviceListenerWin::AudioDeviceListenerWin(const base::Closure& listener_cb)
55 : listener_cb_(listener_cb) { 56 : listener_cb_(listener_cb), tick_clock_(new base::DefaultTickClock()) {
56 CHECK(CoreAudioUtil::IsSupported()); 57 CHECK(CoreAudioUtil::IsSupported());
57 58
58 ScopedComPtr<IMMDeviceEnumerator> device_enumerator( 59 ScopedComPtr<IMMDeviceEnumerator> device_enumerator(
59 CoreAudioUtil::CreateDeviceEnumerator()); 60 CoreAudioUtil::CreateDeviceEnumerator());
60 if (!device_enumerator.get()) 61 if (!device_enumerator.get())
61 return; 62 return;
62 63
63 HRESULT hr = device_enumerator->RegisterEndpointNotificationCallback(this); 64 HRESULT hr = device_enumerator->RegisterEndpointNotificationCallback(this);
64 if (FAILED(hr)) { 65 if (FAILED(hr)) {
65 LOG(ERROR) << "RegisterEndpointNotificationCallback failed: " 66 LOG(ERROR) << "RegisterEndpointNotificationCallback failed: "
66 << std::hex << hr; 67 << std::hex << hr;
67 return; 68 return;
68 } 69 }
69 70
70 device_enumerator_ = device_enumerator; 71 device_enumerator_ = device_enumerator;
71
72 default_render_device_id_ = GetDeviceId(eRender, eConsole);
73 default_capture_device_id_ = GetDeviceId(eCapture, eConsole);
74 default_communications_render_device_id_ =
75 GetDeviceId(eRender, eCommunications);
76 default_communications_capture_device_id_ =
77 GetDeviceId(eCapture, eCommunications);
78 } 72 }
79 73
80 AudioDeviceListenerWin::~AudioDeviceListenerWin() { 74 AudioDeviceListenerWin::~AudioDeviceListenerWin() {
81 DCHECK(thread_checker_.CalledOnValidThread()); 75 DCHECK(thread_checker_.CalledOnValidThread());
82 if (device_enumerator_.get()) { 76 if (device_enumerator_.get()) {
83 HRESULT hr = 77 HRESULT hr =
84 device_enumerator_->UnregisterEndpointNotificationCallback(this); 78 device_enumerator_->UnregisterEndpointNotificationCallback(this);
85 LOG_IF(ERROR, FAILED(hr)) << "UnregisterEndpointNotificationCallback() " 79 LOG_IF(ERROR, FAILED(hr)) << "UnregisterEndpointNotificationCallback() "
86 << "failed: " << std::hex << hr; 80 << "failed: " << std::hex << hr;
87 } 81 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 } 127 }
134 128
135 STDMETHODIMP AudioDeviceListenerWin::OnDefaultDeviceChanged( 129 STDMETHODIMP AudioDeviceListenerWin::OnDefaultDeviceChanged(
136 EDataFlow flow, ERole role, LPCWSTR new_default_device_id) { 130 EDataFlow flow, ERole role, LPCWSTR new_default_device_id) {
137 // Only listen for console and communication device changes. 131 // Only listen for console and communication device changes.
138 if ((role != eConsole && role != eCommunications) || 132 if ((role != eConsole && role != eCommunications) ||
139 (flow != eRender && flow != eCapture)) { 133 (flow != eRender && flow != eCapture)) {
140 return S_OK; 134 return S_OK;
141 } 135 }
142 136
143 // Grab a pointer to the appropriate ID member.
144 // Note that there are three "?:"'s here to select the right ID.
145 std::string* current_device_id =
146 flow == eRender ? (
147 role == eConsole ?
148 &default_render_device_id_ :
149 &default_communications_render_device_id_
150 ) : (
151 role == eConsole ?
152 &default_capture_device_id_ :
153 &default_communications_capture_device_id_
154 );
155
156 // If no device is now available, |new_default_device_id| will be NULL. 137 // If no device is now available, |new_default_device_id| will be NULL.
157 std::string new_device_id; 138 std::string new_device_id;
158 if (new_default_device_id) 139 if (new_default_device_id)
159 new_device_id = base::WideToUTF8(new_default_device_id); 140 new_device_id = base::WideToUTF8(new_default_device_id);
160 141
142 // Only output device changes should be forwarded. Do not attempt to filter
143 // changes based on device id since some devices may not change their device
144 // id and instead trigger some internal flow change: http://crbug.com/506712
145 //
146 // We rate limit device changes to avoid a single device change causing back
147 // to back changes for eCommunications and eConsole; this is worth doing as
148 // it provides a substantially faster resumption of playback.
149 bool did_run_listener_cb = false;
150 const base::TimeTicks now = tick_clock_->NowTicks();
151 if (flow == eRender &&
152 now - last_device_change_time_ >
153 base::TimeDelta::FromMilliseconds(kDeviceChangeLimitMs)) {
154 last_device_change_time_ = now;
155 listener_cb_.Run();
156 did_run_listener_cb = true;
157 }
158
161 DVLOG(1) << "OnDefaultDeviceChanged() " 159 DVLOG(1) << "OnDefaultDeviceChanged() "
162 << "new_default_device: " 160 << "new_default_device: "
163 << (new_default_device_id ? 161 << (new_default_device_id
164 CoreAudioUtil::GetFriendlyName(new_device_id) : "No device") 162 ? CoreAudioUtil::GetFriendlyName(new_device_id)
163 : "no device")
165 << ", flow: " << FlowToString(flow) 164 << ", flow: " << FlowToString(flow)
166 << ", role: " << RoleToString(role); 165 << ", role: " << RoleToString(role)
167 166 << ", notified manager: " << (did_run_listener_cb ? "Yes" : "No");
168 // Only fire a state change event if the device has actually changed.
169 // TODO(dalecurtis): This still seems to fire an extra event on my machine for
170 // an unplug event (probably others too); e.g., we get two transitions to a
171 // new default device id.
172 if (new_device_id.compare(*current_device_id) == 0)
173 return S_OK;
174
175 // Store the new id in the member variable (that current_device_id points to).
176 *current_device_id = new_device_id;
177 listener_cb_.Run();
178 167
179 return S_OK; 168 return S_OK;
180 } 169 }
181 170
182 } // namespace media 171 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698