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 #include "content/renderer/pepper/ppb_audio_impl.h" 6 7 #include "base/logging.h" 8 #include "content/renderer/pepper/common.h" 9 #include "content/renderer/pepper/pepper_platform_audio_output.h" 10 #include "content/renderer/pepper/pepper_plugin_instance_impl.h" 11 #include "content/renderer/render_frame_impl.h" 12 #include "content/renderer/render_view_impl.h" 13 #include "media/audio/audio_output_controller.h" 14 #include "ppapi/c/pp_completion_callback.h" 15 #include "ppapi/c/ppb_audio.h" 16 #include "ppapi/c/ppb_audio_config.h" 17 #include "ppapi/shared_impl/resource_tracker.h" 18 #include "ppapi/thunk/enter.h" 19 #include "ppapi/thunk/ppb_audio_config_api.h" 20 #include "ppapi/thunk/thunk.h" 21 22 using ppapi::PpapiGlobals; 23 using ppapi::thunk::EnterResourceNoLock; 24 using ppapi::thunk::PPB_Audio_API; 25 using ppapi::thunk::PPB_AudioConfig_API; 26 using ppapi::TrackedCallback; 27 28 namespace content { 29 30 // PPB_Audio_Impl -------------------------------------------------------------- 31 32 PPB_Audio_Impl::PPB_Audio_Impl(PP_Instance instance) 33 : Resource(ppapi::OBJECT_IS_IMPL, instance), audio_(NULL) {} 34 35 PPB_Audio_Impl::~PPB_Audio_Impl() { 36 // Calling ShutDown() makes sure StreamCreated cannot be called anymore and 37 // releases the audio data associated with the pointer. Note however, that 38 // until ShutDown returns, StreamCreated may still be called. This will be 39 // OK since we'll just immediately clean up the data it stored later in this 40 // destructor. 41 if (audio_) { 42 audio_->ShutDown(); 43 audio_ = NULL; 44 } 45 } 46 47 PPB_Audio_API* PPB_Audio_Impl::AsPPB_Audio_API() { return this; } 48 49 PP_Resource PPB_Audio_Impl::GetCurrentConfig() { 50 // AddRef on behalf of caller, while keeping a ref for ourselves. 51 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_); 52 return config_; 53 } 54 55 PP_Bool PPB_Audio_Impl::StartPlayback() { 56 if (!audio_) 57 return PP_FALSE; 58 if (playing()) 59 return PP_TRUE; 60 SetStartPlaybackState(); 61 return BoolToPPBool(audio_->StartPlayback()); 62 } 63 64 PP_Bool PPB_Audio_Impl::StopPlayback() { 65 if (!audio_) 66 return PP_FALSE; 67 if (!playing()) 68 return PP_TRUE; 69 if (!audio_->StopPlayback()) 70 return PP_FALSE; 71 SetStopPlaybackState(); 72 return PP_TRUE; 73 } 74 75 int32_t PPB_Audio_Impl::Open(PP_Resource config, 76 scoped_refptr<TrackedCallback> create_callback) { 77 // Validate the config and keep a reference to it. 78 EnterResourceNoLock<PPB_AudioConfig_API> enter(config, true); 79 if (enter.failed()) 80 return PP_ERROR_FAILED; 81 config_ = config; 82 83 PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>( 84 PepperPluginInstance::Get(pp_instance())); 85 if (!instance) 86 return PP_ERROR_FAILED; 87 88 // When the stream is created, we'll get called back on StreamCreated(). 89 DCHECK(!audio_); 90 audio_ = PepperPlatformAudioOutput::Create( 91 static_cast<int>(enter.object()->GetSampleRate()), 92 static_cast<int>(enter.object()->GetSampleFrameCount()), 93 instance->GetRenderView()->GetRoutingID(), 94 instance->render_frame()->GetRoutingID(), 95 this); 96 if (!audio_) 97 return PP_ERROR_FAILED; 98 99 // At this point, we are guaranteeing ownership of the completion 100 // callback. Audio promises to fire the completion callback 101 // once and only once. 102 SetCreateCallback(create_callback); 103 104 return PP_OK_COMPLETIONPENDING; 105 } 106 107 int32_t PPB_Audio_Impl::GetSyncSocket(int* sync_socket) { 108 return GetSyncSocketImpl(sync_socket); 109 } 110 111 int32_t PPB_Audio_Impl::GetSharedMemory(int* shm_handle, uint32_t* shm_size) { 112 return GetSharedMemoryImpl(shm_handle, shm_size); 113 } 114 115 void PPB_Audio_Impl::OnSetStreamInfo( 116 base::SharedMemoryHandle shared_memory_handle, 117 size_t shared_memory_size, 118 base::SyncSocket::Handle socket_handle) { 119 EnterResourceNoLock<PPB_AudioConfig_API> enter(config_, true); 120 SetStreamInfo(pp_instance(), 121 shared_memory_handle, 122 shared_memory_size, 123 socket_handle, 124 enter.object()->GetSampleRate(), 125 enter.object()->GetSampleFrameCount()); 126 } 127 128 } // namespace content 129