15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "content/renderer/pepper/ppb_audio_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
8558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/renderer/pepper/pepper_platform_audio_output.h"
9558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/renderer/render_frame_impl.h"
11558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/renderer/render_view_impl.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_output_controller.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_completion_callback.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_audio.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_audio_config.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/resource_tracker.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/thunk/enter.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/thunk/ppb_audio_config_api.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/thunk/thunk.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::PpapiGlobals;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::thunk::EnterResourceNoLock;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::thunk::PPB_Audio_API;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::thunk::PPB_AudioConfig_API;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::TrackedCallback;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochnamespace content {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PPB_Audio_Impl --------------------------------------------------------------
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_Audio_Impl::PPB_Audio_Impl(PP_Instance instance)
32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : Resource(ppapi::OBJECT_IS_IMPL, instance), audio_(NULL) {}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_Audio_Impl::~PPB_Audio_Impl() {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Calling ShutDown() makes sure StreamCreated cannot be called anymore and
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // releases the audio data associated with the pointer. Note however, that
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // until ShutDown returns, StreamCreated may still be called. This will be
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OK since we'll just immediately clean up the data it stored later in this
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // destructor.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (audio_) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_->ShutDown();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_ = NULL;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochPPB_Audio_API* PPB_Audio_Impl::AsPPB_Audio_API() { return this; }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Resource PPB_Audio_Impl::GetCurrentConfig() {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AddRef on behalf of caller, while keeping a ref for ourselves.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return config_;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool PPB_Audio_Impl::StartPlayback() {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!audio_)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (playing())
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_TRUE;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartPlaybackState();
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return PP_FromBool(audio_->StartPlayback());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool PPB_Audio_Impl::StopPlayback() {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!audio_)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!playing())
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_TRUE;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!audio_->StopPlayback())
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_FALSE;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStopPlaybackState();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_TRUE;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
74a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochint32_t PPB_Audio_Impl::Open(PP_Resource config,
75a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                             scoped_refptr<TrackedCallback> create_callback) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validate the config and keep a reference to it.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterResourceNoLock<PPB_AudioConfig_API> enter(config, true);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enter.failed())
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_FAILED;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_ = config;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>(
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      PepperPluginInstance::Get(pp_instance()));
84558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!instance)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_FAILED;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When the stream is created, we'll get called back on StreamCreated().
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!audio_);
89558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  audio_ = PepperPlatformAudioOutput::Create(
90558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      static_cast<int>(enter.object()->GetSampleRate()),
91558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      static_cast<int>(enter.object()->GetSampleFrameCount()),
92558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      instance->GetRenderView()->GetRoutingID(),
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      instance->render_frame()->GetRoutingID(),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!audio_)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_FAILED;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At this point, we are guaranteeing ownership of the completion
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callback.  Audio promises to fire the completion callback
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // once and only once.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetCreateCallback(create_callback);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_OK_COMPLETIONPENDING;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t PPB_Audio_Impl::GetSyncSocket(int* sync_socket) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetSyncSocketImpl(sync_socket);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochint32_t PPB_Audio_Impl::GetSharedMemory(int* shm_handle, uint32_t* shm_size) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetSharedMemoryImpl(shm_handle, shm_size);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Audio_Impl::OnSetStreamInfo(
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemoryHandle shared_memory_handle,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t shared_memory_size,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SyncSocket::Handle socket_handle) {
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EnterResourceNoLock<PPB_AudioConfig_API> enter(config_, true);
119a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  SetStreamInfo(pp_instance(),
120a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                shared_memory_handle,
121a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                shared_memory_size,
122a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                socket_handle,
123a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                enter.object()->GetSampleRate(),
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                enter.object()->GetSampleFrameCount());
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch}  // namespace content
128