OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/audio_output.h" | 5 #include "media/audio/audio_output.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <mmsystem.h> | 8 #include <mmsystem.h> |
9 | 9 |
10 #include "base/at_exit.h" | 10 #include "base/at_exit.h" |
11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
| 12 #include "media/audio/fake_audio_output_stream.h" |
12 #include "media/audio/win/audio_manager_win.h" | 13 #include "media/audio/win/audio_manager_win.h" |
13 #include "media/audio/win/waveout_output_win.h" | 14 #include "media/audio/win/waveout_output_win.h" |
14 | 15 |
15 // A do-nothing audio stream. It behaves like a regular audio stream but does | |
16 // not have any side effect, except possibly the creation and tear-down of | |
17 // of a thread. It is useful to test code that uses audio streams such as | |
18 // audio sources. | |
19 class AudioOutputStreamMockWin : public AudioOutputStream { | |
20 public: | |
21 explicit AudioOutputStreamMockWin(AudioManagerWin* manager) | |
22 : manager_(manager), | |
23 callback_(NULL), | |
24 buffer_(NULL), | |
25 packet_size_(0), | |
26 left_volume_(1.0), | |
27 right_volume_(1.0) { | |
28 } | |
29 | |
30 virtual ~AudioOutputStreamMockWin() { | |
31 delete[] buffer_; | |
32 packet_size_ = 0; | |
33 } | |
34 | |
35 virtual bool Open(size_t packet_size) { | |
36 if (packet_size < sizeof(int16)) | |
37 return false; | |
38 packet_size_ = packet_size; | |
39 buffer_ = new char[packet_size_]; | |
40 return true; | |
41 } | |
42 | |
43 virtual void Start(AudioSourceCallback* callback) { | |
44 callback_ = callback; | |
45 memset(buffer_, 0, packet_size_); | |
46 callback_->OnMoreData(this, buffer_, packet_size_); | |
47 } | |
48 | |
49 // TODO(cpu): flesh out Start and Stop methods. We need a thread to | |
50 // perform periodic callbacks. | |
51 virtual void Stop() { | |
52 } | |
53 | |
54 virtual void SetVolume(double left_level, double right_level) { | |
55 left_volume_ = left_level; | |
56 right_volume_ = right_level; | |
57 } | |
58 | |
59 virtual void GetVolume(double* left_level, double* right_level) { | |
60 *left_level = left_volume_; | |
61 *right_level = right_volume_; | |
62 } | |
63 | |
64 virtual size_t GetNumBuffers() { | |
65 return 1; | |
66 } | |
67 | |
68 virtual void Close() { | |
69 callback_->OnClose(this); | |
70 callback_ = NULL; | |
71 manager_->ReleaseStream(this); | |
72 } | |
73 | |
74 char* buffer() { | |
75 return buffer_; | |
76 } | |
77 | |
78 private: | |
79 AudioManagerWin* manager_; | |
80 AudioSourceCallback* callback_; | |
81 char* buffer_; | |
82 size_t packet_size_; | |
83 double left_volume_; | |
84 double right_volume_; | |
85 }; | |
86 | |
87 namespace { | 16 namespace { |
88 | 17 |
89 // The next 3 constants are some sensible limits to prevent integer overflow | 18 // The next 3 constants are some sensible limits to prevent integer overflow |
90 // at this layer. | 19 // at this layer. |
91 // TODO(cpu): Some day expand the support and API to more than stereo. | 20 // TODO(cpu): Some day expand the support and API to more than stereo. |
92 const int kMaxChannels = 2; | 21 const int kMaxChannels = 2; |
93 const int kMaxSampleRate = 192000; | 22 const int kMaxSampleRate = 192000; |
94 const int kMaxBitsPerSample = 64; | 23 const int kMaxBitsPerSample = 64; |
95 | 24 |
96 AudioOutputStreamMockWin* g_last_mock_stream = NULL; | |
97 AudioManagerWin* g_audio_manager = NULL; | 25 AudioManagerWin* g_audio_manager = NULL; |
98 | 26 |
99 void ReplaceLastMockStream(AudioOutputStreamMockWin* newer) { | |
100 if (g_last_mock_stream) | |
101 delete g_last_mock_stream; | |
102 g_last_mock_stream = newer; | |
103 } | |
104 | |
105 } // namespace. | 27 } // namespace. |
106 | 28 |
107 | |
108 bool AudioManagerWin::HasAudioDevices() { | 29 bool AudioManagerWin::HasAudioDevices() { |
109 return (::waveOutGetNumDevs() != 0); | 30 return (::waveOutGetNumDevs() != 0); |
110 } | 31 } |
111 | 32 |
112 // Factory for the implementations of AudioOutputStream. Two implementations | 33 // Factory for the implementations of AudioOutputStream. Two implementations |
113 // should suffice most windows user's needs. | 34 // should suffice most windows user's needs. |
114 // - PCMWaveOutAudioOutputStream: Based on the waveOutWrite API (in progress) | 35 // - PCMWaveOutAudioOutputStream: Based on the waveOutWrite API (in progress) |
115 // - PCMDXSoundAudioOutputStream: Based on DirectSound or XAudio (future work). | 36 // - PCMDXSoundAudioOutputStream: Based on DirectSound or XAudio (future work). |
116 | |
117 AudioOutputStream* AudioManagerWin::MakeAudioStream(Format format, int channels, | 37 AudioOutputStream* AudioManagerWin::MakeAudioStream(Format format, int channels, |
118 int sample_rate, | 38 int sample_rate, |
119 char bits_per_sample) { | 39 char bits_per_sample) { |
120 if ((channels > kMaxChannels) || (channels <= 0) || | 40 if ((channels > kMaxChannels) || (channels <= 0) || |
121 (sample_rate > kMaxSampleRate) || (sample_rate <= 0) || | 41 (sample_rate > kMaxSampleRate) || (sample_rate <= 0) || |
122 (bits_per_sample > kMaxBitsPerSample) || (bits_per_sample <= 0)) | 42 (bits_per_sample > kMaxBitsPerSample) || (bits_per_sample <= 0)) |
123 return NULL; | 43 return NULL; |
124 | 44 |
125 if (format == AUDIO_MOCK) { | 45 if (format == AUDIO_MOCK) { |
126 return new AudioOutputStreamMockWin(this); | 46 return FakeAudioOutputStream::MakeFakeStream(); |
127 } else if (format == AUDIO_PCM_LINEAR) { | 47 } else if (format == AUDIO_PCM_LINEAR) { |
128 return new PCMWaveOutAudioOutputStream(this, channels, sample_rate, | 48 return new PCMWaveOutAudioOutputStream(this, channels, sample_rate, |
129 bits_per_sample, WAVE_MAPPER); | 49 bits_per_sample, WAVE_MAPPER); |
130 } | 50 } |
131 return NULL; | 51 return NULL; |
132 } | 52 } |
133 | 53 |
134 void AudioManagerWin::ReleaseStream(PCMWaveOutAudioOutputStream* stream) { | 54 void AudioManagerWin::ReleaseStream(PCMWaveOutAudioOutputStream* stream) { |
135 if (stream) | 55 if (stream) |
136 delete stream; | 56 delete stream; |
137 } | 57 } |
138 | 58 |
139 void AudioManagerWin::ReleaseStream(AudioOutputStreamMockWin *stream) { | |
140 // Note that we keep the last mock stream so GetLastMockBuffer() works. | |
141 ReplaceLastMockStream(stream); | |
142 } | |
143 | |
144 const void* AudioManagerWin::GetLastMockBuffer() { | |
145 return (g_last_mock_stream) ? g_last_mock_stream->buffer() : NULL; | |
146 } | |
147 | |
148 void AudioManagerWin::MuteAll() { | 59 void AudioManagerWin::MuteAll() { |
149 } | 60 } |
150 | 61 |
151 void AudioManagerWin::UnMuteAll() { | 62 void AudioManagerWin::UnMuteAll() { |
152 } | 63 } |
153 | 64 |
154 AudioManagerWin::~AudioManagerWin() { | 65 AudioManagerWin::~AudioManagerWin() { |
155 ReplaceLastMockStream(NULL); | |
156 } | 66 } |
157 | 67 |
158 void DestroyAudioManagerWin(void* param) { | 68 void DestroyAudioManagerWin(void* param) { |
159 delete g_audio_manager; | 69 delete g_audio_manager; |
160 g_audio_manager = NULL; | 70 g_audio_manager = NULL; |
161 } | 71 } |
162 | 72 |
163 AudioManager* AudioManager::GetAudioManager() { | 73 AudioManager* AudioManager::GetAudioManager() { |
164 if (!g_audio_manager) { | 74 if (!g_audio_manager) { |
165 g_audio_manager = new AudioManagerWin(); | 75 g_audio_manager = new AudioManagerWin(); |
166 base::AtExitManager::RegisterCallback(&DestroyAudioManagerWin, NULL); | 76 base::AtExitManager::RegisterCallback(&DestroyAudioManagerWin, NULL); |
167 } | 77 } |
168 return g_audio_manager; | 78 return g_audio_manager; |
169 } | 79 } |
OLD | NEW |