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

Side by Side Diff: ppapi/examples/audio_input/audio_input.cc

Issue 11411047: Introduce PPB_AudioInput_Dev v0.3 and refactor the device enumeration code: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years 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/cpp/dev/audio_input_dev.cc ('k') | ppapi/examples/audio_input/audio_input.html » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stdlib.h>
5 #include <string.h> 6 #include <string.h>
6 7
7 #include <algorithm> 8 #include <algorithm>
8 #include <limits> 9 #include <limits>
9 #include <vector> 10 #include <vector>
10 11
11 #include "ppapi/cpp/audio_config.h" 12 #include "ppapi/cpp/audio_config.h"
12 #include "ppapi/cpp/dev/audio_input_dev.h" 13 #include "ppapi/cpp/dev/audio_input_dev.h"
13 #include "ppapi/cpp/dev/device_ref_dev.h" 14 #include "ppapi/cpp/dev/device_ref_dev.h"
14 #include "ppapi/cpp/graphics_2d.h" 15 #include "ppapi/cpp/graphics_2d.h"
(...skipping 10 matching lines...) Expand all
25 #ifdef PostMessage 26 #ifdef PostMessage
26 #undef PostMessage 27 #undef PostMessage
27 #endif 28 #endif
28 29
29 namespace { 30 namespace {
30 31
31 // This sample frequency is guaranteed to work. 32 // This sample frequency is guaranteed to work.
32 const PP_AudioSampleRate kSampleFrequency = PP_AUDIOSAMPLERATE_44100; 33 const PP_AudioSampleRate kSampleFrequency = PP_AUDIOSAMPLERATE_44100;
33 const uint32_t kSampleCount = 1024; 34 const uint32_t kSampleCount = 1024;
34 const uint32_t kChannelCount = 1; 35 const uint32_t kChannelCount = 1;
36 const char* const kDelimiter = "#__#";
35 37
36 } // namespace 38 } // namespace
37 39
38 class MyInstance : public pp::Instance { 40 class MyInstance : public pp::Instance {
39 public: 41 public:
40 explicit MyInstance(PP_Instance instance) 42 explicit MyInstance(PP_Instance instance)
41 : pp::Instance(instance), 43 : pp::Instance(instance),
42 callback_factory_(this), 44 callback_factory_(this),
43 sample_count_(0), 45 sample_count_(0),
44 channel_count_(0), 46 channel_count_(0),
45 samples_(NULL), 47 samples_(NULL),
46 timer_interval_(0), 48 timer_interval_(0),
47 pending_paint_(false), 49 pending_paint_(false),
48 waiting_for_flush_completion_(false) { 50 waiting_for_flush_completion_(false) {
49 } 51 }
50 virtual ~MyInstance() { 52 virtual ~MyInstance() {
53 device_detector_.MonitorDeviceChange(NULL, NULL);
51 audio_input_.Close(); 54 audio_input_.Close();
52 55
53 delete[] samples_; 56 delete[] samples_;
54 } 57 }
55 58
56 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { 59 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
57 sample_count_ = pp::AudioConfig::RecommendSampleFrameCount(this, 60 sample_count_ = pp::AudioConfig::RecommendSampleFrameCount(this,
58 kSampleFrequency, 61 kSampleFrequency,
59 kSampleCount); 62 kSampleCount);
60 PP_DCHECK(sample_count_ > 0); 63 PP_DCHECK(sample_count_ > 0);
61 channel_count_ = kChannelCount; 64 channel_count_ = kChannelCount;
62 samples_ = new int16_t[sample_count_ * channel_count_]; 65 samples_ = new int16_t[sample_count_ * channel_count_];
63 memset(samples_, 0, sample_count_ * channel_count_ * sizeof(int16_t)); 66 memset(samples_, 0, sample_count_ * channel_count_ * sizeof(int16_t));
64 67
65 audio_input_ = pp::AudioInput_Dev(this); 68 device_detector_ = pp::AudioInput_Dev(this);
66 69
67 // Try to ensure that we pick up a new set of samples between each 70 // Try to ensure that we pick up a new set of samples between each
68 // timer-generated repaint. 71 // timer-generated repaint.
69 timer_interval_ = (sample_count_ * 1000) / kSampleFrequency + 5; 72 timer_interval_ = (sample_count_ * 1000) / kSampleFrequency + 5;
70 ScheduleNextTimer(); 73 ScheduleNextTimer();
71 74
72 return true; 75 return true;
73 } 76 }
74 77
75 virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) { 78 virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
76 if (position.size() == size_) 79 if (position.size() == size_)
77 return; 80 return;
78 81
79 size_ = position.size(); 82 size_ = position.size();
80 device_context_ = pp::Graphics2D(this, size_, false); 83 device_context_ = pp::Graphics2D(this, size_, false);
81 if (!BindGraphics(device_context_)) 84 if (!BindGraphics(device_context_))
82 return; 85 return;
83 86
84 Paint(); 87 Paint();
85 } 88 }
86 89
87 virtual void HandleMessage(const pp::Var& message_data) { 90 virtual void HandleMessage(const pp::Var& message_data) {
88 if (message_data.is_string()) { 91 if (message_data.is_string()) {
89 std::string event = message_data.AsString(); 92 std::string event = message_data.AsString();
90 if (event == "PageInitialized") { 93 if (event == "PageInitialized") {
94 int32_t result = device_detector_.MonitorDeviceChange(
95 &MyInstance::MonitorDeviceChangeCallback, this);
96 if (result != PP_OK)
97 PostMessage(pp::Var("MonitorDeviceChangeFailed"));
98
91 pp::CompletionCallbackWithOutput<std::vector<pp::DeviceRef_Dev> > 99 pp::CompletionCallbackWithOutput<std::vector<pp::DeviceRef_Dev> >
92 callback = callback_factory_.NewCallbackWithOutput( 100 callback = callback_factory_.NewCallbackWithOutput(
93 &MyInstance::EnumerateDevicesFinished); 101 &MyInstance::EnumerateDevicesFinished);
94 int32_t result = audio_input_.EnumerateDevices(callback); 102 result = device_detector_.EnumerateDevices(callback);
95 if (result != PP_OK_COMPLETIONPENDING) 103 if (result != PP_OK_COMPLETIONPENDING)
96 PostMessage(pp::Var("EnumerationFailed")); 104 PostMessage(pp::Var("EnumerationFailed"));
97 } else if (event == "UseDefault") { 105 } else if (event == "UseDefault") {
98 Open(pp::DeviceRef_Dev()); 106 Open(pp::DeviceRef_Dev());
99 } else if (event == "Stop") { 107 } else if (event == "Stop") {
100 Stop(); 108 Stop();
101 } else if (event == "Start") { 109 } else if (event == "Start") {
102 Start(); 110 Start();
103 } 111 } else if (event.find("Monitor:") == 0) {
104 } else if (message_data.is_number()) { 112 std::string index_str = event.substr(strlen("Monitor:"));
105 int index = message_data.AsInt(); 113 int index = atoi(index_str.c_str());
106 if (index >= 0 && index < static_cast<int>(devices_.size())) { 114 if (index >= 0 && index < static_cast<int>(monitor_devices_.size()))
107 Open(devices_[index]); 115 Open(monitor_devices_[index]);
108 } else { 116 else
109 PP_NOTREACHED(); 117 PP_NOTREACHED();
118 } else if (event.find("Enumerate:") == 0) {
119 std::string index_str = event.substr(strlen("Enumerate:"));
120 int index = atoi(index_str.c_str());
121 if (index >= 0 && index < static_cast<int>(enumerate_devices_.size()))
122 Open(enumerate_devices_[index]);
123 else
124 PP_NOTREACHED();
110 } 125 }
111 } 126 }
112 } 127 }
113 128
114 private: 129 private:
115 void ScheduleNextTimer() { 130 void ScheduleNextTimer() {
116 PP_DCHECK(timer_interval_ > 0); 131 PP_DCHECK(timer_interval_ > 0);
117 pp::Module::Get()->core()->CallOnMainThread( 132 pp::Module::Get()->core()->CallOnMainThread(
118 timer_interval_, 133 timer_interval_,
119 callback_factory_.NewCallback(&MyInstance::OnTimer), 134 callback_factory_.NewCallback(&MyInstance::OnTimer),
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 x < std::min(size.width(), static_cast<int>(sample_count_)); 192 x < std::min(size.width(), static_cast<int>(sample_count_));
178 x++, i += channel_count_) { 193 x++, i += channel_count_) {
179 int y = samples_[i] * max_amplitude / 194 int y = samples_[i] * max_amplitude /
180 (std::numeric_limits<int16_t>::max() + 1) + mid_height; 195 (std::numeric_limits<int16_t>::max() + 1) + mid_height;
181 *image.GetAddr32(pp::Point(x, y)) = 0xffffffff; 196 *image.GetAddr32(pp::Point(x, y)) = 0xffffffff;
182 } 197 }
183 198
184 return image; 199 return image;
185 } 200 }
186 201
187 // TODO(viettrungluu): Danger! We really should lock, but which thread 202 void Open(const pp::DeviceRef_Dev& device) {
188 // primitives to use? In any case, the |StopCapture()| in the destructor 203 audio_input_.Close();
189 // shouldn't return until this callback is done, so at least we should be 204 audio_input_ = pp::AudioInput_Dev(this);
190 // writing to a valid region of memory.
191 static void CaptureCallback(const void* samples,
192 uint32_t num_bytes,
193 void* ctx) {
194 MyInstance* thiz = static_cast<MyInstance*>(ctx);
195 uint32_t buffer_size =
196 thiz->sample_count_ * thiz->channel_count_ * sizeof(int16_t);
197 PP_DCHECK(num_bytes <= buffer_size);
198 PP_DCHECK(num_bytes % (thiz->channel_count_ * sizeof(int16_t)) == 0);
199 memcpy(thiz->samples_, samples, num_bytes);
200 memset(reinterpret_cast<char*>(thiz->samples_) + num_bytes, 0,
201 buffer_size - num_bytes);
202 }
203 205
204 void Open(const pp::DeviceRef_Dev& device) {
205 pp::AudioConfig config = pp::AudioConfig(this, 206 pp::AudioConfig config = pp::AudioConfig(this,
206 kSampleFrequency, 207 kSampleFrequency,
207 sample_count_); 208 sample_count_);
208 pp::CompletionCallback callback = callback_factory_.NewCallback( 209 pp::CompletionCallback callback = callback_factory_.NewCallback(
209 &MyInstance::OpenFinished); 210 &MyInstance::OpenFinished);
210 int32_t result = audio_input_.Open(device, config, CaptureCallback, this, 211 int32_t result = audio_input_.Open(device, config, CaptureCallback, this,
211 callback); 212 callback);
212 if (result != PP_OK_COMPLETIONPENDING) 213 if (result != PP_OK_COMPLETIONPENDING)
213 PostMessage(pp::Var("OpenFailed")); 214 PostMessage(pp::Var("OpenFailed"));
214 } 215 }
215 216
216 void Stop() { 217 void Stop() {
217 if (!audio_input_.StopCapture()) 218 if (!audio_input_.StopCapture())
218 PostMessage(pp::Var("StopFailed")); 219 PostMessage(pp::Var("StopFailed"));
219 } 220 }
220 221
221 void Start() { 222 void Start() {
222 if (!audio_input_.StartCapture()) 223 if (!audio_input_.StartCapture())
223 PostMessage(pp::Var("StartFailed")); 224 PostMessage(pp::Var("StartFailed"));
224 } 225 }
225 226
226 void EnumerateDevicesFinished(int32_t result, 227 void EnumerateDevicesFinished(int32_t result,
227 std::vector<pp::DeviceRef_Dev>& devices) { 228 std::vector<pp::DeviceRef_Dev>& devices) {
228 static const char* const kDelimiter = "#__#";
229
230 if (result == PP_OK) { 229 if (result == PP_OK) {
231 devices_.swap(devices); 230 enumerate_devices_.swap(devices);
232 std::string device_names; 231 std::string device_names = "Enumerate:";
233 for (size_t index = 0; index < devices_.size(); ++index) { 232 for (size_t index = 0; index < enumerate_devices_.size(); ++index) {
234 pp::Var name = devices_[index].GetName(); 233 pp::Var name = enumerate_devices_[index].GetName();
235 PP_DCHECK(name.is_string()); 234 PP_DCHECK(name.is_string());
236 235
237 if (index != 0) 236 if (index != 0)
238 device_names += kDelimiter; 237 device_names += kDelimiter;
239 device_names += name.AsString(); 238 device_names += name.AsString();
240 } 239 }
241 PostMessage(pp::Var(device_names)); 240 PostMessage(pp::Var(device_names));
242 } else { 241 } else {
243 PostMessage(pp::Var("EnumerationFailed")); 242 PostMessage(pp::Var("EnumerationFailed"));
244 } 243 }
245 } 244 }
246 245
247 void OpenFinished(int32_t result) { 246 void OpenFinished(int32_t result) {
248 if (result == PP_OK) { 247 if (result == PP_OK) {
249 if (!audio_input_.StartCapture()) 248 if (!audio_input_.StartCapture())
250 PostMessage(pp::Var("StartFailed")); 249 PostMessage(pp::Var("StartFailed"));
251 } else { 250 } else {
252 PostMessage(pp::Var("OpenFailed")); 251 PostMessage(pp::Var("OpenFailed"));
253 } 252 }
254 } 253 }
255 254
255 // TODO(viettrungluu): Danger! We really should lock, but which thread
256 // primitives to use? In any case, the |StopCapture()| in the destructor
257 // shouldn't return until this callback is done, so at least we should be
258 // writing to a valid region of memory.
259 static void CaptureCallback(const void* samples,
260 uint32_t num_bytes,
261 void* ctx) {
262 MyInstance* thiz = static_cast<MyInstance*>(ctx);
263 uint32_t buffer_size =
264 thiz->sample_count_ * thiz->channel_count_ * sizeof(int16_t);
265 PP_DCHECK(num_bytes <= buffer_size);
266 PP_DCHECK(num_bytes % (thiz->channel_count_ * sizeof(int16_t)) == 0);
267 memcpy(thiz->samples_, samples, num_bytes);
268 memset(reinterpret_cast<char*>(thiz->samples_) + num_bytes, 0,
269 buffer_size - num_bytes);
270 }
271
272 static void MonitorDeviceChangeCallback(void* user_data,
273 uint32_t device_count,
274 const PP_Resource devices[]) {
275 MyInstance* thiz = static_cast<MyInstance*>(user_data);
276
277 std::string device_names = "Monitor:";
278 thiz->monitor_devices_.clear();
279 thiz->monitor_devices_.reserve(device_count);
280 for (size_t index = 0; index < device_count; ++index) {
281 thiz->monitor_devices_.push_back(pp::DeviceRef_Dev(devices[index]));
282 pp::Var name = thiz->monitor_devices_.back().GetName();
283 PP_DCHECK(name.is_string());
284
285 if (index != 0)
286 device_names += kDelimiter;
287 device_names += name.AsString();
288 }
289 thiz->PostMessage(pp::Var(device_names));
290 }
291
256 pp::CompletionCallbackFactory<MyInstance> callback_factory_; 292 pp::CompletionCallbackFactory<MyInstance> callback_factory_;
257 293
258 uint32_t sample_count_; 294 uint32_t sample_count_;
259 uint32_t channel_count_; 295 uint32_t channel_count_;
260 int16_t* samples_; 296 int16_t* samples_;
261 297
262 int32_t timer_interval_; 298 int32_t timer_interval_;
263 299
264 // Painting stuff. 300 // Painting stuff.
265 pp::Size size_; 301 pp::Size size_;
266 pp::Graphics2D device_context_; 302 pp::Graphics2D device_context_;
267 bool pending_paint_; 303 bool pending_paint_;
268 bool waiting_for_flush_completion_; 304 bool waiting_for_flush_completion_;
269 305
306 // There is no need to have two resources to do capturing and device detecting
307 // separately. However, this makes the code of monitoring device change
308 // easier.
270 pp::AudioInput_Dev audio_input_; 309 pp::AudioInput_Dev audio_input_;
310 pp::AudioInput_Dev device_detector_;
271 311
272 std::vector<pp::DeviceRef_Dev> devices_; 312 std::vector<pp::DeviceRef_Dev> enumerate_devices_;
313 std::vector<pp::DeviceRef_Dev> monitor_devices_;
273 }; 314 };
274 315
275 class MyModule : public pp::Module { 316 class MyModule : public pp::Module {
276 public: 317 public:
277 virtual pp::Instance* CreateInstance(PP_Instance instance) { 318 virtual pp::Instance* CreateInstance(PP_Instance instance) {
278 return new MyInstance(instance); 319 return new MyInstance(instance);
279 } 320 }
280 }; 321 };
281 322
282 namespace pp { 323 namespace pp {
283 324
284 // Factory function for your specialization of the Module object. 325 // Factory function for your specialization of the Module object.
285 Module* CreateModule() { 326 Module* CreateModule() {
286 return new MyModule(); 327 return new MyModule();
287 } 328 }
288 329
289 } // namespace pp 330 } // namespace pp
OLDNEW
« no previous file with comments | « ppapi/cpp/dev/audio_input_dev.cc ('k') | ppapi/examples/audio_input/audio_input.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698