audio_device_listener_mac.h revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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
3// found in the LICENSE file.
4
5#ifndef MEDIA_AUDIO_MAC_AUDIO_DEVICE_LISTENER_MAC_H_
6#define MEDIA_AUDIO_MAC_AUDIO_DEVICE_LISTENER_MAC_H_
7
8#include <CoreAudio/AudioHardware.h>
9
10#include "base/basictypes.h"
11#include "base/callback.h"
12#include "base/scoped_native_library.h"
13#include "base/threading/thread_checker.h"
14#include "media/base/media_export.h"
15
16namespace media {
17
18class ExclusiveDispatchQueueTaskObserver;
19
20// AudioDeviceListenerMac facilitates thread safe execution of device listener
21// callbacks issued via CoreAudio.  On 10.6 this means correctly binding the
22// CFRunLoop driving callbacks to the CFRunLoop AudioDeviceListenerMac is
23// constructed on.  On 10.7 this means creating a dispatch queue to drive
24// callbacks and modifying the message loop AudioDeviceListenerMac to ensure
25// message loop tasks and dispatch queue tasks are executed in a mutually
26// exclusive manner.  See http://crbug.com/158170 for more discussion.
27class MEDIA_EXPORT AudioDeviceListenerMac {
28 public:
29  // |listener_cb| will be called when a device change occurs; it's a permanent
30  // callback and must outlive AudioDeviceListenerMac.
31  explicit AudioDeviceListenerMac(const base::Closure& listener_cb);
32  ~AudioDeviceListenerMac();
33
34 private:
35  friend class AudioDeviceListenerMacTest;
36  static const AudioObjectPropertyAddress kDeviceChangePropertyAddress;
37
38  static OSStatus OnDefaultDeviceChanged(
39      AudioObjectID object, UInt32 num_addresses,
40      const AudioObjectPropertyAddress addresses[], void* context);
41
42  // Attempts to dynamically load the property listener block functions.  Sets
43  // |core_audio_lib_|, |add_listener_block_func_|, and
44  // |remove_listener_block_func_|.  Returns false on failure.  If successful,
45  // the unload function must be called to avoid memory leaks.
46  bool LoadAudioObjectPropertyListenerBlockFunctions();
47
48  base::Closure listener_cb_;
49  scoped_ptr<ExclusiveDispatchQueueTaskObserver> task_observer_;
50  base::ScopedNativeLibrary core_audio_lib_;
51
52  // TODO(dalecurtis): Use the standard AudioObjectPropertyListenerBlock when
53  // the deployment target is > 10.6.
54  typedef void (^CrAudioObjectPropertyListenerBlock)(
55      UInt32 inNumberAddresses, const AudioObjectPropertyAddress inAddresses[]);
56  CrAudioObjectPropertyListenerBlock listener_block_;
57
58  // Variables for storing dynamically loaded block functions.
59  typedef OSStatus(*AudioObjectPropertyListenerBlockT)(
60      AudioObjectID inObjectID,
61      const AudioObjectPropertyAddress* inAddress,
62      dispatch_queue_t inDispatchQueue,
63      CrAudioObjectPropertyListenerBlock inListener);
64  AudioObjectPropertyListenerBlockT add_listener_block_func_;
65  AudioObjectPropertyListenerBlockT remove_listener_block_func_;
66
67  // AudioDeviceListenerMac must be constructed and destructed on the same
68  // thread.
69  base::ThreadChecker thread_checker_;
70
71  // If the sample rate hasn't changed, don't fire a device change.  OSX will
72  // handle the routing under the hood.
73  int current_sample_rate_;
74
75  DISALLOW_COPY_AND_ASSIGN(AudioDeviceListenerMac);
76};
77
78}  // namespace media
79
80#endif  // MEDIA_AUDIO_MAC_AUDIO_DEVICE_LISTENER_MAC_H_
81