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