audio_device_listener_mac.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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.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 AudioDeviceListenerMac* p_this = 41 static_cast<AudioDeviceListenerMac*>(context); 42 DCHECK(p_this->thread_checker_.CalledOnValidThread()); 43 p_this->listener_cb_.Run(); 44 break; 45 } 46 } 47 48 return noErr; 49} 50 51AudioDeviceListenerMac::AudioDeviceListenerMac( 52 const base::Closure& listener_cb) { 53 OSStatus result = AudioObjectAddPropertyListener( 54 kAudioObjectSystemObject, &kDeviceChangePropertyAddress, 55 &AudioDeviceListenerMac::OnDefaultDeviceChanged, this); 56 57 if (result != noErr) { 58 OSSTATUS_DLOG(ERROR, result) 59 << "AudioObjectAddPropertyListener() failed!"; 60 return; 61 } 62 63 listener_cb_ = listener_cb; 64} 65 66AudioDeviceListenerMac::~AudioDeviceListenerMac() { 67 DCHECK(thread_checker_.CalledOnValidThread()); 68 if (listener_cb_.is_null()) 69 return; 70 71 // Since we're running on the same CFRunLoop, there can be no outstanding 72 // callbacks in flight. 73 OSStatus result = AudioObjectRemovePropertyListener( 74 kAudioObjectSystemObject, &kDeviceChangePropertyAddress, 75 &AudioDeviceListenerMac::OnDefaultDeviceChanged, this); 76 OSSTATUS_DLOG_IF(ERROR, result != noErr, result) 77 << "AudioObjectRemovePropertyListener() failed!"; 78} 79 80} // namespace media 81