Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(174)

Side by Side Diff: ppapi/proxy/ppb_audio_input_proxy.cc

Issue 8574029: Microphone support for Pepper Flash. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ppapi/proxy/ppb_audio_input_proxy.h ('k') | ppapi/proxy/resource_creation_proxy.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "ppapi/proxy/ppb_audio_input_proxy.h"
6
7 #include "base/compiler_specific.h"
8 #include "base/threading/simple_thread.h"
9 #include "ppapi/c/dev/ppb_audio_input_dev.h"
10 #include "ppapi/c/pp_errors.h"
11 #include "ppapi/c/ppb_audio_config.h"
12 #include "ppapi/c/ppb_var.h"
13 #include "ppapi/c/trusted/ppb_audio_trusted.h"
14 #include "ppapi/proxy/enter_proxy.h"
15 #include "ppapi/proxy/plugin_dispatcher.h"
16 #include "ppapi/proxy/ppapi_messages.h"
17 #include "ppapi/shared_impl/api_id.h"
18 #include "ppapi/shared_impl/audio_input_impl.h"
19 #include "ppapi/shared_impl/ppapi_globals.h"
20 #include "ppapi/shared_impl/resource.h"
21 #include "ppapi/thunk/enter.h"
22 #include "ppapi/thunk/ppb_audio_config_api.h"
23 #include "ppapi/thunk/resource_creation_api.h"
24 #include "ppapi/thunk/thunk.h"
25
26 using ppapi::thunk::EnterResourceNoLock;
27 using ppapi::thunk::PPB_AudioInput_API;
28 using ppapi::thunk::PPB_AudioConfig_API;
29
30 namespace ppapi {
31 namespace proxy {
32
33 class AudioInput : public Resource, public AudioInputImpl {
34 public:
35 AudioInput(const HostResource& audio_input_id,
36 PP_Resource config_id,
37 PPB_AudioInput_Callback callback,
38 void* user_data);
39 virtual ~AudioInput();
40
41 // Resource overrides.
42 virtual PPB_AudioInput_API* AsPPB_AudioInput_API() OVERRIDE;
43
44 // PPB_AudioInput_API implementation.
45 virtual PP_Resource GetCurrentConfig() OVERRIDE;
46 virtual PP_Bool StartCapture() OVERRIDE;
47 virtual PP_Bool StopCapture() OVERRIDE;
48
49 virtual int32_t OpenTrusted(PP_Resource config_id,
50 PP_CompletionCallback create_callback) OVERRIDE;
51 virtual int32_t GetSyncSocket(int* sync_socket) OVERRIDE;
52 virtual int32_t GetSharedMemory(int* shm_handle, uint32_t* shm_size) OVERRIDE;
53
54 private:
55 // Owning reference to the current config object. This isn't actually used,
56 // we just dish it out as requested by the plugin.
57 PP_Resource config_;
58
59 DISALLOW_COPY_AND_ASSIGN(AudioInput);
60 };
61
62 AudioInput::AudioInput(const HostResource& audio_input_id,
63 PP_Resource config_id,
64 PPB_AudioInput_Callback callback,
65 void* user_data)
66 : Resource(audio_input_id),
67 config_(config_id) {
68 SetCallback(callback, user_data);
69 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_);
70 }
71
72 AudioInput::~AudioInput() {
73 PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(config_);
74 }
75
76 PPB_AudioInput_API* AudioInput::AsPPB_AudioInput_API() {
77 return this;
78 }
79
80 PP_Resource AudioInput::GetCurrentConfig() {
81 // AddRef for the caller.
82 PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(config_);
83 return config_;
84 }
85
86 PP_Bool AudioInput::StartCapture() {
87 if (capturing())
88 return PP_TRUE;
89 SetStartCaptureState();
90 PluginDispatcher::GetForResource(this)->Send(
91 new PpapiHostMsg_PPBAudioInput_StartOrStop(
92 API_ID_PPB_AUDIO_INPUT_DEV, host_resource(), true));
93 return PP_TRUE;
94 }
95
96 PP_Bool AudioInput::StopCapture() {
97 if (!capturing())
98 return PP_TRUE;
99 PluginDispatcher::GetForResource(this)->Send(
100 new PpapiHostMsg_PPBAudioInput_StartOrStop(
101 API_ID_PPB_AUDIO_INPUT_DEV, host_resource(), false));
102 SetStopCaptureState();
103 return PP_TRUE;
104 }
105
106 int32_t AudioInput::OpenTrusted(PP_Resource config_id,
107 PP_CompletionCallback create_callback) {
108 return PP_ERROR_NOTSUPPORTED; // Don't proxy the trusted interface.
109 }
110
111 int32_t AudioInput::GetSyncSocket(int* sync_socket) {
112 return PP_ERROR_NOTSUPPORTED; // Don't proxy the trusted interface.
113 }
114
115 int32_t AudioInput::GetSharedMemory(int* shm_handle, uint32_t* shm_size) {
116 return PP_ERROR_NOTSUPPORTED; // Don't proxy the trusted interface.
117 }
118
119 namespace {
120
121 base::PlatformFile IntToPlatformFile(int32_t handle) {
122 // TODO(piman/brettw): Change trusted interface to return a PP_FileHandle,
123 // those casts are ugly.
124 #if defined(OS_WIN)
125 return reinterpret_cast<HANDLE>(static_cast<intptr_t>(handle));
126 #elif defined(OS_POSIX)
127 return handle;
128 #else
129 #error Not implemented.
130 #endif
131 }
132
133 } // namespace
134
135 PPB_AudioInput_Proxy::PPB_AudioInput_Proxy(Dispatcher* dispatcher)
136 : InterfaceProxy(dispatcher),
137 callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
138 }
139
140 PPB_AudioInput_Proxy::~PPB_AudioInput_Proxy() {
141 }
142
143 // static
144 PP_Resource PPB_AudioInput_Proxy::CreateProxyResource(
145 PP_Instance instance_id,
146 PP_Resource config_id,
147 PPB_AudioInput_Callback audio_input_callback,
148 void* user_data) {
149 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id);
150 if (!dispatcher)
151 return 0;
152
153 EnterResourceNoLock<PPB_AudioConfig_API> config(config_id, true);
154 if (config.failed())
155 return 0;
156
157 HostResource result;
158 dispatcher->Send(new PpapiHostMsg_PPBAudioInput_Create(
159 API_ID_PPB_AUDIO_INPUT_DEV, instance_id,
160 config.object()->GetSampleRate(), config.object()->GetSampleFrameCount(),
161 &result));
162 if (result.is_null())
163 return 0;
164
165 return (new AudioInput(result, config_id, audio_input_callback,
166 user_data))->GetReference();
167 }
168
169 bool PPB_AudioInput_Proxy::OnMessageReceived(const IPC::Message& msg) {
170 bool handled = true;
171 IPC_BEGIN_MESSAGE_MAP(PPB_AudioInput_Proxy, msg)
172 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudioInput_Create, OnMsgCreate)
173 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBAudioInput_StartOrStop,
174 OnMsgStartOrStop)
175 IPC_MESSAGE_HANDLER(PpapiMsg_PPBAudioInput_NotifyAudioStreamCreated,
176 OnMsgNotifyAudioStreamCreated)
177 IPC_MESSAGE_UNHANDLED(handled = false)
178 IPC_END_MESSAGE_MAP()
179 // TODO(brettw) handle bad messages!
180
181 return handled;
182 }
183
184 void PPB_AudioInput_Proxy::OnMsgCreate(PP_Instance instance_id,
185 int32_t sample_rate,
186 uint32_t sample_frame_count,
187 HostResource* result) {
188 thunk::EnterFunction<thunk::ResourceCreationAPI> resource_creation(
189 instance_id, true);
190 if (resource_creation.failed())
191 return;
192
193 // Make the resource and get the API pointer to its trusted interface.
194 result->SetHostResource(
195 instance_id,
196 resource_creation.functions()->CreateAudioInputTrusted(instance_id));
197 if (result->is_null())
198 return;
199
200 // At this point, we've set the result resource, and this is a sync request.
201 // Anything below this point must issue the AudioInputChannelConnected
202 // callback to the browser. Since that's an async message, it will be issued
203 // back to the plugin after the Create function returns (which is good
204 // because it would be weird to get a connected message with a failure code
205 // for a resource you haven't finished creating yet).
206 //
207 // The ...ForceCallback class will help ensure the callback is always called.
208 // All error cases must call SetResult on this class.
209
210 EnterHostFromHostResourceForceCallback<PPB_AudioInput_API> enter(
211 *result, callback_factory_,
212 &PPB_AudioInput_Proxy::AudioInputChannelConnected, *result);
213 if (enter.failed())
214 return; // When enter fails, it will internally schedule the callback.
215
216 // Make an audio config object.
217 PP_Resource audio_config_res =
218 resource_creation.functions()->CreateAudioConfig(
219 instance_id, static_cast<PP_AudioSampleRate>(sample_rate),
220 sample_frame_count);
221 if (!audio_config_res) {
222 enter.SetResult(PP_ERROR_FAILED);
223 return;
224 }
225
226 // Initiate opening the audio object.
227 enter.SetResult(enter.object()->OpenTrusted(audio_config_res,
228 enter.callback()));
229
230 // Clean up the temporary audio config resource we made.
231 const PPB_Core* core = static_cast<const PPB_Core*>(
232 dispatcher()->local_get_interface()(PPB_CORE_INTERFACE));
233 core->ReleaseResource(audio_config_res);
234 }
235
236 void PPB_AudioInput_Proxy::OnMsgStartOrStop(
237 const HostResource& resource,
238 bool capture) {
239 EnterHostFromHostResource<PPB_AudioInput_API> enter(resource);
240 if (enter.failed())
241 return;
242 if (capture)
243 enter.object()->StartCapture();
244 else
245 enter.object()->StopCapture();
246 }
247
248 // Processed in the plugin (message from host).
249 void PPB_AudioInput_Proxy::OnMsgNotifyAudioStreamCreated(
250 const HostResource& audio_id,
251 int32_t result_code,
252 IPC::PlatformFileForTransit socket_handle,
253 base::SharedMemoryHandle handle,
254 uint32_t length) {
255 EnterPluginFromHostResource<PPB_AudioInput_API> enter(audio_id);
256 if (enter.failed() || result_code != PP_OK) {
257 // The caller may still have given us these handles in the failure case.
258 // The easiest way to clean these up is to just put them in the objects
259 // and then close them. This failure case is not performance critical.
260 base::SyncSocket temp_socket(
261 IPC::PlatformFileForTransitToPlatformFile(socket_handle));
262 base::SharedMemory temp_mem(handle, false);
263 } else {
264 static_cast<AudioInput*>(enter.object())->SetStreamInfo(
265 handle, length,
266 IPC::PlatformFileForTransitToPlatformFile(socket_handle));
267 }
268 }
269
270 void PPB_AudioInput_Proxy::AudioInputChannelConnected(
271 int32_t result,
272 const HostResource& resource) {
273 IPC::PlatformFileForTransit socket_handle =
274 IPC::InvalidPlatformFileForTransit();
275 base::SharedMemoryHandle shared_memory = IPC::InvalidPlatformFileForTransit();
276 uint32_t shared_memory_length = 0;
277
278 int32_t result_code = result;
279 if (result_code == PP_OK) {
280 result_code = GetAudioInputConnectedHandles(resource, &socket_handle,
281 &shared_memory,
282 &shared_memory_length);
283 }
284
285 // Send all the values, even on error. This simplifies some of our cleanup
286 // code since the handles will be in the other process and could be
287 // inconvenient to clean up. Our IPC code will automatically handle this for
288 // us, as long as the remote side always closes the handles it receives
289 // (in OnMsgNotifyAudioStreamCreated), even in the failure case.
290 dispatcher()->Send(new PpapiMsg_PPBAudioInput_NotifyAudioStreamCreated(
291 API_ID_PPB_AUDIO_INPUT_DEV, resource, result_code, socket_handle,
292 shared_memory, shared_memory_length));
293 }
294
295 int32_t PPB_AudioInput_Proxy::GetAudioInputConnectedHandles(
296 const HostResource& resource,
297 IPC::PlatformFileForTransit* foreign_socket_handle,
298 base::SharedMemoryHandle* foreign_shared_memory_handle,
299 uint32_t* shared_memory_length) {
300 // Get the audio interface which will give us the handles.
301 EnterHostFromHostResource<PPB_AudioInput_API> enter(resource);
302 if (enter.failed())
303 return PP_ERROR_NOINTERFACE;
304
305 // Get the socket handle for signaling.
306 int32_t socket_handle;
307 int32_t result = enter.object()->GetSyncSocket(&socket_handle);
308 if (result != PP_OK)
309 return result;
310
311 // socket_handle doesn't belong to us: don't close it.
312 *foreign_socket_handle = dispatcher()->ShareHandleWithRemote(
313 IntToPlatformFile(socket_handle), false);
314 if (*foreign_socket_handle == IPC::InvalidPlatformFileForTransit())
315 return PP_ERROR_FAILED;
316
317 // Get the shared memory for the buffer.
318 int shared_memory_handle;
319 result = enter.object()->GetSharedMemory(&shared_memory_handle,
320 shared_memory_length);
321 if (result != PP_OK)
322 return result;
323
324 // shared_memory_handle doesn't belong to us: don't close it.
325 *foreign_shared_memory_handle = dispatcher()->ShareHandleWithRemote(
326 IntToPlatformFile(shared_memory_handle), false);
327 if (*foreign_shared_memory_handle == IPC::InvalidPlatformFileForTransit())
328 return PP_ERROR_FAILED;
329
330 return PP_OK;
331 }
332
333 } // namespace proxy
334 } // namespace ppapi
OLDNEW
« no previous file with comments | « ppapi/proxy/ppb_audio_input_proxy.h ('k') | ppapi/proxy/resource_creation_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698