OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "webkit/glue/plugins/pepper_audio.h" | 5 #include "webkit/glue/plugins/pepper_audio.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "ppapi/c/dev/ppb_audio_dev.h" | 8 #include "third_party/ppapi/c/pp_completion_callback.h" |
brettw
2010/11/22 18:22:09
Alphabetize the headers.
nfullagar
2010/11/23 02:48:58
Done.
| |
9 #include "ppapi/c/dev/ppb_audio_trusted_dev.h" | 9 #include "third_party/ppapi/c/dev/ppb_audio_dev.h" |
10 #include "third_party/ppapi/c/dev/ppb_audio_trusted_dev.h" | |
10 #include "webkit/glue/plugins/pepper_common.h" | 11 #include "webkit/glue/plugins/pepper_common.h" |
11 | 12 |
12 namespace pepper { | 13 namespace pepper { |
13 | 14 |
14 namespace { | 15 namespace { |
15 | 16 |
16 // PPB_AudioConfig ------------------------------------------------------------- | 17 // PPB_AudioConfig ------------------------------------------------------------- |
17 | 18 |
18 uint32_t RecommendSampleFrameCount(uint32_t requested_sample_frame_count); | 19 uint32_t RecommendSampleFrameCount(uint32_t requested_sample_frame_count); |
19 | 20 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
70 &CreateStereo16bit, | 71 &CreateStereo16bit, |
71 &RecommendSampleFrameCount, | 72 &RecommendSampleFrameCount, |
72 &IsAudioConfig, | 73 &IsAudioConfig, |
73 &GetSampleRate, | 74 &GetSampleRate, |
74 &GetSampleFrameCount | 75 &GetSampleFrameCount |
75 }; | 76 }; |
76 | 77 |
77 // PPB_Audio ------------------------------------------------------------------- | 78 // PPB_Audio ------------------------------------------------------------------- |
78 | 79 |
79 PP_Resource Create(PP_Instance instance_id, PP_Resource config_id, | 80 PP_Resource Create(PP_Instance instance_id, PP_Resource config_id, |
80 PPB_Audio_Callback callback, void* user_data) { | 81 PPB_Audio_Callback user_callback, void* user_data) { |
81 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); | 82 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); |
82 if (!instance) | 83 if (!instance) |
83 return 0; | 84 return 0; |
84 // TODO(neb): Require callback to be present for untrusted plugins. | 85 // TODO(neb): Require callback to be present for untrusted plugins. |
85 scoped_refptr<Audio> audio(new Audio(instance->module())); | 86 scoped_refptr<Audio> audio(new Audio(instance->module(), instance_id)); |
86 if (!audio->Init(instance->delegate(), config_id, callback, user_data)) | 87 if (!audio->Init(instance->delegate(), config_id, |
88 user_callback, user_data)) | |
87 return 0; | 89 return 0; |
88 return audio->GetReference(); | 90 return audio->GetReference(); |
89 } | 91 } |
90 | 92 |
91 PP_Bool IsAudio(PP_Resource resource) { | 93 PP_Bool IsAudio(PP_Resource resource) { |
92 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(resource); | 94 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(resource); |
93 return BoolToPPBool(!!audio); | 95 return BoolToPPBool(!!audio); |
94 } | 96 } |
95 | 97 |
96 PP_Resource GetCurrentConfiguration(PP_Resource audio_id) { | 98 PP_Resource GetCurrentConfiguration(PP_Resource audio_id) { |
(...skipping 14 matching lines...) Expand all Loading... | |
111 const PPB_Audio_Dev ppb_audio = { | 113 const PPB_Audio_Dev ppb_audio = { |
112 &Create, | 114 &Create, |
113 &IsAudio, | 115 &IsAudio, |
114 &GetCurrentConfiguration, | 116 &GetCurrentConfiguration, |
115 &StartPlayback, | 117 &StartPlayback, |
116 &StopPlayback, | 118 &StopPlayback, |
117 }; | 119 }; |
118 | 120 |
119 // PPB_AudioTrusted ------------------------------------------------------------ | 121 // PPB_AudioTrusted ------------------------------------------------------------ |
120 | 122 |
121 PP_Resource GetBuffer(PP_Resource audio_id) { | 123 PP_Resource CreateTrusted(PP_Instance instance_id) { |
122 // TODO(neb): Implement me! | 124 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); |
123 return 0; | 125 if (!instance) |
126 return 0; | |
127 scoped_refptr<Audio> audio(new Audio(instance->module(), instance_id)); | |
128 return audio->GetReference(); | |
124 } | 129 } |
125 | 130 |
126 int GetOSDescriptor(PP_Resource audio_id) { | 131 int32_t Open(PP_Resource audio_id, |
127 // TODO(neb): Implement me! | 132 PP_Resource config_id, |
128 return -1; | 133 PP_CompletionCallback created) { |
134 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id); | |
135 if (!audio) { | |
136 PP_RunCompletionCallback(&created, -1); | |
brettw
2010/11/22 18:22:09
Don't hard code the error values. Use PP_ERROR_* i
nfullagar
2010/11/23 02:48:58
replaced with PP_ERROR_FAILED and removed PP_RunCo
| |
137 return -1; | |
138 } | |
139 PP_Instance instance_id = audio->GetInstance(); | |
140 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); | |
141 if (!instance) { | |
142 PP_RunCompletionCallback(&created, -1); | |
143 return -1; | |
144 } | |
145 // At this point we're passing ownership of |created| so |audio| will be | |
146 // responsible for firing the completion callback. | |
147 return audio->OpenTrusted(instance->delegate(), config_id, created); | |
148 } | |
149 | |
150 PP_Bool GetSyncSocket(PP_Resource audio_id, int* sync_socket) { | |
151 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id); | |
152 if (audio) { | |
brettw
2010/11/22 18:22:09
Be consistent about using {} for single-line condi
nfullagar
2010/11/23 02:48:58
Done.
| |
153 return BoolToPPBool(audio->GetSyncSocket(sync_socket)); | |
154 } | |
155 return PP_FALSE; | |
156 } | |
157 | |
158 PP_Bool GetSharedMemory(PP_Resource audio_id, | |
159 uint64_t* shm_handle, | |
160 int32_t* shm_size) { | |
161 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id); | |
162 if (audio) { | |
163 return BoolToPPBool(audio->GetSharedMemory(shm_handle, shm_size)); | |
164 } | |
165 return PP_FALSE; | |
166 } | |
167 | |
168 void Close(PP_Resource audio_id) { | |
169 scoped_refptr<Audio> audio = Resource::GetAs<Audio>(audio_id); | |
170 if (audio) | |
171 audio->CloseTrusted(); | |
129 } | 172 } |
130 | 173 |
131 const PPB_AudioTrusted_Dev ppb_audiotrusted = { | 174 const PPB_AudioTrusted_Dev ppb_audiotrusted = { |
132 &GetBuffer, | 175 &CreateTrusted, |
133 &GetOSDescriptor | 176 &Open, |
177 &GetSyncSocket, | |
178 &GetSharedMemory, | |
179 &Close | |
134 }; | 180 }; |
135 | 181 |
136 } // namespace | 182 } // namespace |
137 | 183 |
138 // AudioConfig ----------------------------------------------------------------- | 184 // AudioConfig ----------------------------------------------------------------- |
139 | 185 |
140 AudioConfig::AudioConfig(PluginModule* module, | 186 AudioConfig::AudioConfig(PluginModule* module, |
141 PP_AudioSampleRate_Dev sample_rate, | 187 PP_AudioSampleRate_Dev sample_rate, |
142 uint32_t sample_frame_count) | 188 uint32_t sample_frame_count) |
143 : Resource(module), | 189 : Resource(module), |
(...skipping 14 matching lines...) Expand all Loading... | |
158 const int kSizeOfSample = sizeof(int16_t); | 204 const int kSizeOfSample = sizeof(int16_t); |
159 return static_cast<size_t>(sample_frame_count_ * kSizeOfSample * kChannels); | 205 return static_cast<size_t>(sample_frame_count_ * kSizeOfSample * kChannels); |
160 } | 206 } |
161 | 207 |
162 AudioConfig* AudioConfig::AsAudioConfig() { | 208 AudioConfig* AudioConfig::AsAudioConfig() { |
163 return this; | 209 return this; |
164 } | 210 } |
165 | 211 |
166 // Audio ----------------------------------------------------------------------- | 212 // Audio ----------------------------------------------------------------------- |
167 | 213 |
168 Audio::Audio(PluginModule* module) | 214 Audio::Audio(PluginModule* module, PP_Instance instance_id) |
169 : Resource(module), | 215 : Resource(module), |
170 playing_(false), | 216 playing_(false), |
217 pp_instance_(instance_id), | |
218 audio_(NULL), | |
171 socket_(NULL), | 219 socket_(NULL), |
172 shared_memory_(NULL), | 220 shared_memory_(NULL), |
173 shared_memory_size_(0), | 221 shared_memory_size_(0), |
222 shared_memory_handle_(0), | |
174 callback_(NULL), | 223 callback_(NULL), |
175 user_data_(NULL) { | 224 user_data_(NULL), |
225 create_callback_pending_(false) { | |
226 create_callback_ = PP_MakeCompletionCallback(NULL, NULL); | |
176 } | 227 } |
177 | 228 |
178 Audio::~Audio() { | 229 Audio::~Audio() { |
179 // Calling ShutDown() makes sure StreamCreated cannot be called anymore. | 230 // Calling ShutDown() makes sure StreamCreated cannot be called anymore. |
180 audio_->ShutDown(); | 231 audio_->ShutDown(); |
232 audio_ = NULL; | |
181 // Closing the socket causes the thread to exit - wait for it. | 233 // Closing the socket causes the thread to exit - wait for it. |
182 socket_->Close(); | 234 socket_->Close(); |
183 if (audio_thread_.get()) { | 235 if (audio_thread_.get()) { |
184 audio_thread_->Join(); | 236 audio_thread_->Join(); |
185 audio_thread_.reset(); | 237 audio_thread_.reset(); |
186 } | 238 } |
239 // Fire pending completion callback if neccessary. | |
240 CloseTrusted(); | |
187 // Shared memory destructor will unmap the memory automatically. | 241 // Shared memory destructor will unmap the memory automatically. |
188 } | 242 } |
189 | 243 |
190 const PPB_Audio_Dev* Audio::GetInterface() { | 244 const PPB_Audio_Dev* Audio::GetInterface() { |
191 return &ppb_audio; | 245 return &ppb_audio; |
192 } | 246 } |
193 | 247 |
194 const PPB_AudioTrusted_Dev* Audio::GetTrustedInterface() { | 248 const PPB_AudioTrusted_Dev* Audio::GetTrustedInterface() { |
195 return &ppb_audiotrusted; | 249 return &ppb_audiotrusted; |
196 } | 250 } |
197 | 251 |
198 Audio* Audio::AsAudio() { | 252 Audio* Audio::AsAudio() { |
199 return this; | 253 return this; |
200 } | 254 } |
201 | 255 |
202 bool Audio::Init(PluginDelegate* plugin_delegate, PP_Resource config_id, | 256 bool Audio::Init(PluginDelegate* plugin_delegate, |
257 PP_Resource config_id, | |
203 PPB_Audio_Callback callback, void* user_data) { | 258 PPB_Audio_Callback callback, void* user_data) { |
204 CHECK(!audio_.get()); | 259 CHECK(!audio_); |
205 config_ = Resource::GetAs<AudioConfig>(config_id); | 260 config_ = Resource::GetAs<AudioConfig>(config_id); |
206 if (!config_) | 261 if (!config_) |
207 return false; | 262 return false; |
208 callback_ = callback; | 263 callback_ = callback; |
209 user_data_ = user_data; | 264 user_data_ = user_data; |
210 // When the stream is created, we'll get called back in StreamCreated(). | 265 // When the stream is created, we'll get called back on StreamCreated(). |
211 audio_.reset(plugin_delegate->CreateAudio(config_->sample_rate(), | 266 audio_ = plugin_delegate->CreateAudio(config_->sample_rate(), |
212 config_->sample_frame_count(), | 267 config_->sample_frame_count(), |
213 this)); | 268 this); |
214 return audio_.get() != NULL; | 269 return audio_ != NULL; |
270 } | |
271 | |
272 int32_t Audio::OpenTrusted(PluginDelegate* plugin_delegate, | |
273 PP_Resource config_id, | |
274 PP_CompletionCallback create_callback) { | |
275 CHECK(!audio_); | |
276 create_callback_ = create_callback; | |
277 create_callback_pending_ = true; | |
278 config_ = Resource::GetAs<AudioConfig>(config_id); | |
279 if (!config_) { | |
280 CloseTrusted(); | |
281 return -1; | |
282 } | |
283 // When the stream is created, we'll get called back on StreamCreated(). | |
284 audio_ = plugin_delegate->CreateAudio(config_->sample_rate(), | |
285 config_->sample_frame_count(), | |
286 this); | |
287 if (audio_ == NULL) { | |
288 CloseTrusted(); | |
289 return -1; | |
290 } | |
291 return 0; | |
292 } | |
293 | |
294 void Audio::CloseTrusted() { | |
295 // If the completion callback hasn't fired yet, do so here | |
brettw
2010/11/22 18:22:09
Be sure your comments are complete sentences with
nfullagar
2010/11/23 02:48:58
done (this comment continues on the next line :)
| |
296 // with an error condition. | |
297 if (create_callback_pending_) { | |
298 PP_RunCompletionCallback(&create_callback_, -1); | |
299 create_callback_pending_ = false; | |
300 } | |
301 // TODO(audio): what else should go here vs. ~Audio destructor | |
302 } | |
303 | |
304 bool Audio::GetSyncSocket(int *sync_socket) { | |
305 if (socket_ != NULL) { | |
306 *sync_socket = static_cast<int>(socket_->handle()); | |
307 return true; | |
308 } | |
309 return false; | |
310 } | |
311 | |
312 bool Audio::GetSharedMemory(uint64_t* shm_handle, int32_t* shm_size) { | |
313 if (shared_memory_ != NULL) { | |
314 *shm_handle = shared_memory_handle_; | |
315 *shm_size = shared_memory_size_; | |
316 return true; | |
317 } | |
318 return false; | |
215 } | 319 } |
216 | 320 |
217 bool Audio::StartPlayback() { | 321 bool Audio::StartPlayback() { |
218 if (playing_) | 322 if (playing_) |
219 return true; | 323 return true; |
220 | 324 |
221 CHECK(!audio_thread_.get()); | 325 CHECK(!audio_thread_.get()); |
222 if (callback_ && socket_.get()) { | 326 if (callback_ && socket_.get()) { |
223 audio_thread_.reset(new base::DelegateSimpleThread(this, | 327 audio_thread_.reset(new base::DelegateSimpleThread(this, |
224 "plugin_audio_thread")); | 328 "plugin_audio_thread")); |
(...skipping 17 matching lines...) Expand all Loading... | |
242 playing_ = false; | 346 playing_ = false; |
243 return true; | 347 return true; |
244 } | 348 } |
245 | 349 |
246 void Audio::StreamCreated(base::SharedMemoryHandle shared_memory_handle, | 350 void Audio::StreamCreated(base::SharedMemoryHandle shared_memory_handle, |
247 size_t shared_memory_size, | 351 size_t shared_memory_size, |
248 base::SyncSocket::Handle socket_handle) { | 352 base::SyncSocket::Handle socket_handle) { |
249 socket_.reset(new base::SyncSocket(socket_handle)); | 353 socket_.reset(new base::SyncSocket(socket_handle)); |
250 shared_memory_.reset(new base::SharedMemory(shared_memory_handle, false)); | 354 shared_memory_.reset(new base::SharedMemory(shared_memory_handle, false)); |
251 shared_memory_size_ = shared_memory_size; | 355 shared_memory_size_ = shared_memory_size; |
252 | 356 #if OS_LINUX || OS_MAC |
357 shared_memory_handle_ = static_cast<uint64_t>(shared_memory_handle.fd); | |
358 #elif OS_WIN | |
359 shared_memory_handle_ = static_cast<uint64_t>(shared_memory_handle); | |
360 #else | |
361 #error "Unknown OS" | |
362 #endif | |
363 // Trusted side of proxy can specify a callback to recieve handles on. | |
364 if (create_callback_pending_) { | |
365 PP_RunCompletionCallback(&create_callback_, 0); | |
366 create_callback_pending_ = false; | |
367 } | |
368 // Recurring callback to fill audio buffers. | |
253 if (callback_) { | 369 if (callback_) { |
254 shared_memory_->Map(shared_memory_size_); | 370 shared_memory_->Map(shared_memory_size_); |
255 // In common case StartPlayback() was called before StreamCreated(). | 371 // In common case StartPlayback() was called before StreamCreated(). |
256 if (playing_) { | 372 if (playing_) { |
257 audio_thread_.reset(new base::DelegateSimpleThread(this, | 373 audio_thread_.reset(new base::DelegateSimpleThread(this, |
258 "plugin_audio_thread")); | 374 "plugin_audio_thread")); |
259 audio_thread_->Start(); | 375 audio_thread_->Start(); |
260 } | 376 } |
261 } | 377 } |
262 } | 378 } |
263 | 379 |
264 void Audio::Run() { | 380 void Audio::Run() { |
265 int pending_data; | 381 int pending_data; |
266 void* buffer = shared_memory_->memory(); | 382 void* buffer = shared_memory_->memory(); |
267 size_t buffer_size_in_bytes = config_->BufferSize(); | 383 size_t buffer_size_in_bytes = config_->BufferSize(); |
268 | 384 |
269 while (sizeof(pending_data) == | 385 while (sizeof(pending_data) == |
270 socket_->Receive(&pending_data, sizeof(pending_data)) && | 386 socket_->Receive(&pending_data, sizeof(pending_data)) && |
271 pending_data >= 0) { | 387 pending_data >= 0) { |
272 // Exit the thread on pause. | 388 // Exit the thread on pause. |
273 if (pending_data < 0) | 389 if (pending_data < 0) |
274 return; | 390 return; |
275 callback_(buffer, buffer_size_in_bytes, user_data_); | 391 callback_(buffer, buffer_size_in_bytes, user_data_); |
276 } | 392 } |
277 } | 393 } |
278 | 394 |
279 } // namespace pepper | 395 } // namespace pepper |
280 | |
OLD | NEW |