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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppb_audio_proxy.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/simple_thread.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/pp_errors.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_audio.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_audio_config.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/c/ppb_var.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/enter_proxy.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/plugin_dispatcher.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/api_id.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/platform_file.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/ppapi_globals.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/ppb_audio_shared.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/resource.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/thunk/ppb_audio_config_api.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/thunk/enter.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/thunk/resource_creation_api.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/thunk/thunk.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::IntToPlatformFile;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::proxy::SerializedHandle;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::thunk::EnterResourceNoLock;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::thunk::PPB_Audio_API;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ppapi::thunk::PPB_AudioConfig_API;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace proxy {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Audio : public Resource, public PPB_Audio_Shared {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Audio(const HostResource& audio_id,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PP_Resource config_id,
3958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        const AudioCallbackCombined& callback,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        void* user_data);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~Audio();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Resource overrides.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PPB_Audio_API* AsPPB_Audio_API();
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // PPB_Audio_API implementation.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PP_Resource GetCurrentConfig() OVERRIDE;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PP_Bool StartPlayback() OVERRIDE;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual PP_Bool StopPlayback() OVERRIDE;
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual int32_t Open(
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PP_Resource config_id,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<TrackedCallback> create_callback) OVERRIDE;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int32_t GetSyncSocket(int* sync_socket) OVERRIDE;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int32_t GetSharedMemory(int* shm_handle, uint32_t* shm_size) OVERRIDE;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Owning reference to the current config object. This isn't actually used,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we just dish it out as requested by the plugin.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource config_;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Audio);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Audio::Audio(const HostResource& audio_id,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             PP_Resource config_id,
6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             const AudioCallbackCombined& callback,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             void* user_data)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Resource(OBJECT_IS_PROXY, audio_id),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config_(config_id) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetCallback(callback, user_data);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Audio::~Audio() {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_NACL)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoke StopPlayback() to ensure audio back-end has a chance to send the
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // escape value over the sync socket, which will terminate the client side
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // audio callback loop.  This is required for NaCl Plugins that can't escape
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by shutting down the sync_socket.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopPlayback();
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(config_);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_Audio_API* Audio::AsPPB_Audio_API() {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Resource Audio::GetCurrentConfig() {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AddRef for the caller.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return config_;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool Audio::StartPlayback() {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (playing())
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_TRUE;
980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!PPB_Audio_Shared::IsThreadFunctionReady())
990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return PP_FALSE;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStartPlaybackState();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginDispatcher::GetForResource(this)->Send(
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new PpapiHostMsg_PPBAudio_StartOrStop(
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          API_ID_PPB_AUDIO, host_resource(), true));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_TRUE;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Bool Audio::StopPlayback() {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!playing())
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_TRUE;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginDispatcher::GetForResource(this)->Send(
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new PpapiHostMsg_PPBAudio_StartOrStop(
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          API_ID_PPB_AUDIO, host_resource(), false));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStopPlaybackState();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_TRUE;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int32_t Audio::Open(PP_Resource config_id,
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    scoped_refptr<TrackedCallback> create_callback) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_ERROR_NOTSUPPORTED;  // Don't proxy the trusted interface.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t Audio::GetSyncSocket(int* sync_socket) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_ERROR_NOTSUPPORTED;  // Don't proxy the trusted interface.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t Audio::GetSharedMemory(int* shm_handle, uint32_t* shm_size) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_ERROR_NOTSUPPORTED;  // Don't proxy the trusted interface.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_Audio_Proxy::PPB_Audio_Proxy(Dispatcher* dispatcher)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : InterfaceProxy(dispatcher),
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback_factory_(this) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PPB_Audio_Proxy::~PPB_Audio_Proxy() {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PP_Resource PPB_Audio_Proxy::CreateProxyResource(
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Instance instance_id,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PP_Resource config_id,
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const AudioCallbackCombined& audio_callback,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* user_data) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dispatcher)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterResourceNoLock<PPB_AudioConfig_API> config(config_id, true);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (config.failed())
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!audio_callback.IsValid())
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostResource result;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dispatcher->Send(new PpapiHostMsg_PPBAudio_Create(
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      API_ID_PPB_AUDIO, instance_id,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config.object()->GetSampleRate(), config.object()->GetSampleFrameCount(),
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &result));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result.is_null())
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (new Audio(result, config_id,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    audio_callback, user_data))->GetReference();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PPB_Audio_Proxy::OnMessageReceived(const IPC::Message& msg) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool handled = true;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_BEGIN_MESSAGE_MAP(PPB_Audio_Proxy, msg)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Don't build host side into NaCl IRT.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_NACL)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudio_Create, OnMsgCreate)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudio_StartOrStop,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnMsgStartOrStop)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_HANDLER(PpapiMsg_PPBAudio_NotifyAudioStreamCreated,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OnMsgNotifyAudioStreamCreated)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC_MESSAGE_UNHANDLED(handled = false)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC_END_MESSAGE_MAP()
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return handled;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_NACL)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Audio_Proxy::OnMsgCreate(PP_Instance instance_id,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int32_t sample_rate,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  uint32_t sample_frame_count,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  HostResource* result) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  thunk::EnterResourceCreation resource_creation(instance_id);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (resource_creation.failed())
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make the resource and get the API pointer to its trusted interface.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->SetHostResource(
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      instance_id,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resource_creation.functions()->CreateAudioTrusted(instance_id));
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result->is_null())
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At this point, we've set the result resource, and this is a sync request.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Anything below this point must issue the AudioChannelConnected callback
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to the browser. Since that's an async message, it will be issued back to
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the plugin after the Create function returns (which is good because it
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // would be weird to get a connected message with a failure code for a
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // resource you haven't finished creating yet).
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The ...ForceCallback class will help ensure the callback is always called.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // All error cases must call SetResult on this class.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterHostFromHostResourceForceCallback<PPB_Audio_API> enter(
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result, callback_factory_,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &PPB_Audio_Proxy::AudioChannelConnected, *result);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enter.failed())
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // When enter fails, it will internally schedule the callback.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make an audio config object.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PP_Resource audio_config_res =
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resource_creation.functions()->CreateAudioConfig(
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          instance_id, static_cast<PP_AudioSampleRate>(sample_rate),
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          sample_frame_count);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!audio_config_res) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enter.SetResult(PP_ERROR_FAILED);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initiate opening the audio object.
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  enter.SetResult(enter.object()->Open(audio_config_res,
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       enter.callback()));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clean up the temporary audio config resource we made.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PPB_Core* core = static_cast<const PPB_Core*>(
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dispatcher()->local_get_interface()(PPB_CORE_INTERFACE));
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core->ReleaseResource(audio_config_res);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Audio_Proxy::OnMsgStartOrStop(const HostResource& audio_id,
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       bool play) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterHostFromHostResource<PPB_Audio_API> enter(audio_id);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enter.failed())
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (play)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enter.object()->StartPlayback();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enter.object()->StopPlayback();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Audio_Proxy::AudioChannelConnected(
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostResource& resource) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPC::PlatformFileForTransit socket_handle =
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IPC::InvalidPlatformFileForTransit();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SharedMemoryHandle shared_memory = IPC::InvalidPlatformFileForTransit();
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32_t audio_buffer_length = 0;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result_code = result;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result_code == PP_OK) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result_code = GetAudioConnectedHandles(resource, &socket_handle,
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           &shared_memory,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           &audio_buffer_length);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send all the values, even on error. This simplifies some of our cleanup
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // code since the handles will be in the other process and could be
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inconvenient to clean up. Our IPC code will automatically handle this for
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // us, as long as the remote side always closes the handles it receives
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (in OnMsgNotifyAudioStreamCreated), even in the failure case.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SerializedHandle fd_wrapper(SerializedHandle::SOCKET, socket_handle);
2661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  SerializedHandle handle_wrapper(shared_memory, audio_buffer_length);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dispatcher()->Send(new PpapiMsg_PPBAudio_NotifyAudioStreamCreated(
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      API_ID_PPB_AUDIO, resource, result_code, fd_wrapper, handle_wrapper));
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t PPB_Audio_Proxy::GetAudioConnectedHandles(
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostResource& resource,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPC::PlatformFileForTransit* foreign_socket_handle,
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemoryHandle* foreign_shared_memory_handle,
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32_t* shared_memory_length) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the audio interface which will give us the handles.
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterHostFromHostResource<PPB_Audio_API> enter(resource);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enter.failed())
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_NOINTERFACE;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the socket handle for signaling.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t socket_handle;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32_t result = enter.object()->GetSyncSocket(&socket_handle);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != PP_OK)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // socket_handle doesn't belong to us: don't close it.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *foreign_socket_handle = dispatcher()->ShareHandleWithRemote(
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IntToPlatformFile(socket_handle), false);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*foreign_socket_handle == IPC::InvalidPlatformFileForTransit())
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_FAILED;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the shared memory for the buffer.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int shared_memory_handle;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = enter.object()->GetSharedMemory(&shared_memory_handle,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           shared_memory_length);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != PP_OK)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // shared_memory_handle doesn't belong to us: don't close it.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *foreign_shared_memory_handle = dispatcher()->ShareHandleWithRemote(
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IntToPlatformFile(shared_memory_handle), false);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*foreign_shared_memory_handle == IPC::InvalidPlatformFileForTransit())
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PP_ERROR_FAILED;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PP_OK;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // !defined(OS_NACL)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Processed in the plugin (message from host).
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPB_Audio_Proxy::OnMsgNotifyAudioStreamCreated(
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostResource& audio_id,
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32_t result_code,
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedHandle socket_handle,
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SerializedHandle handle) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(socket_handle.is_socket());
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(handle.is_shmem());
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnterPluginFromHostResource<PPB_Audio_API> enter(audio_id);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enter.failed() || result_code != PP_OK) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The caller may still have given us these handles in the failure case.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The easiest way to clean these up is to just put them in the objects
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and then close them. This failure case is not performance critical.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SyncSocket temp_socket(
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IPC::PlatformFileForTransitToPlatformFile(socket_handle.descriptor()));
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SharedMemory temp_mem(handle.shmem(), false);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnterResourceNoLock<PPB_AudioConfig_API> config(
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<Audio*>(enter.object())->GetCurrentConfig(), true);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static_cast<Audio*>(enter.object())->SetStreamInfo(
3301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        enter.resource()->pp_instance(), handle.shmem(), handle.size(),
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IPC::PlatformFileForTransitToPlatformFile(socket_handle.descriptor()),
33258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        config.object()->GetSampleRate(),
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        config.object()->GetSampleFrameCount());
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace proxy
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ppapi
339