audio_device_listener_mac.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
1// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "media/audio/mac/audio_device_listener_mac.h" 6 7#include "base/bind.h" 8#include "base/files/file_path.h" 9#include "base/logging.h" 10#include "base/mac/mac_logging.h" 11#include "base/mac/mac_util.h" 12#include "base/message_loop/message_loop.h" 13#include "base/pending_task.h" 14#include "media/audio/mac/audio_low_latency_output_mac.h" 15 16namespace media { 17 18// Property address to monitor for device changes. 19const AudioObjectPropertyAddress 20AudioDeviceListenerMac::kDeviceChangePropertyAddress = { 21 kAudioHardwarePropertyDefaultOutputDevice, 22 kAudioObjectPropertyScopeGlobal, 23 kAudioObjectPropertyElementMaster 24}; 25 26// Callback from the system when the default device changes; this must be called 27// on the MessageLoop that created the AudioManager. 28// static 29OSStatus AudioDeviceListenerMac::OnDefaultDeviceChanged( 30 AudioObjectID object, UInt32 num_addresses, 31 const AudioObjectPropertyAddress addresses[], void* context) { 32 if (object != kAudioObjectSystemObject) 33 return noErr; 34 35 for (UInt32 i = 0; i < num_addresses; ++i) { 36 if (addresses[i].mSelector == kDeviceChangePropertyAddress.mSelector && 37 addresses[i].mScope == kDeviceChangePropertyAddress.mScope && 38 addresses[i].mElement == kDeviceChangePropertyAddress.mElement && 39 context) { 40 static_cast<AudioDeviceListenerMac*>(context)->listener_cb_.Run(); 41 break; 42 } 43 } 44 45 return noErr; 46} 47 48AudioDeviceListenerMac::AudioDeviceListenerMac( 49 const base::Closure& listener_cb) { 50 OSStatus result = AudioObjectAddPropertyListener( 51 kAudioObjectSystemObject, &kDeviceChangePropertyAddress, 52 &AudioDeviceListenerMac::OnDefaultDeviceChanged, this); 53 54 if (result != noErr) { 55 OSSTATUS_DLOG(ERROR, result) 56 << "AudioObjectAddPropertyListener() failed!"; 57 return; 58 } 59 60 listener_cb_ = listener_cb; 61} 62 63AudioDeviceListenerMac::~AudioDeviceListenerMac() { 64 DCHECK(thread_checker_.CalledOnValidThread()); 65 if (listener_cb_.is_null()) 66 return; 67 68 // Since we're running on the same CFRunLoop, there can be no outstanding 69 // callbacks in flight. 70 OSStatus result = AudioObjectRemovePropertyListener( 71 kAudioObjectSystemObject, &kDeviceChangePropertyAddress, 72 &AudioDeviceListenerMac::OnDefaultDeviceChanged, this); 73 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) 74 << "AudioObjectRemovePropertyListener() failed!"; 75} 76 77} // namespace media 78