Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 <string.h> | 5 #include <string.h> |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <vector> | |
| 9 | 10 |
| 10 #include "ppapi/cpp/audio_config.h" | 11 #include "ppapi/cpp/audio_config.h" |
| 11 #include "ppapi/cpp/dev/audio_input_dev.h" | 12 #include "ppapi/cpp/dev/audio_input_dev.h" |
| 13 #include "ppapi/cpp/dev/device_ref_dev.h" | |
| 12 #include "ppapi/cpp/graphics_2d.h" | 14 #include "ppapi/cpp/graphics_2d.h" |
| 13 #include "ppapi/cpp/image_data.h" | 15 #include "ppapi/cpp/image_data.h" |
| 14 #include "ppapi/cpp/instance.h" | 16 #include "ppapi/cpp/instance.h" |
| 15 #include "ppapi/cpp/logging.h" | 17 #include "ppapi/cpp/logging.h" |
| 16 #include "ppapi/cpp/module.h" | 18 #include "ppapi/cpp/module.h" |
| 17 #include "ppapi/cpp/rect.h" | 19 #include "ppapi/cpp/rect.h" |
| 18 #include "ppapi/cpp/size.h" | 20 #include "ppapi/cpp/size.h" |
| 19 #include "ppapi/utility/completion_callback_factory.h" | 21 #include "ppapi/utility/completion_callback_factory.h" |
| 20 | 22 |
| 21 class MyInstance : public pp::Instance { | 23 class MyInstance : public pp::Instance { |
| 22 public: | 24 public: |
| 23 explicit MyInstance(PP_Instance instance) | 25 explicit MyInstance(PP_Instance instance) |
| 24 : pp::Instance(instance), | 26 : pp::Instance(instance), |
| 25 callback_factory_(this), | 27 callback_factory_(this), |
| 26 sample_count_(0), | 28 sample_count_(0), |
| 27 channel_count_(0), | 29 channel_count_(0), |
| 28 samples_(NULL), | 30 samples_(NULL), |
| 29 timer_interval_(0), | 31 timer_interval_(0), |
| 30 pending_paint_(false), | 32 pending_paint_(false), |
| 31 waiting_for_flush_completion_(false) { | 33 waiting_for_flush_completion_(false), |
| 34 audio_input_0_1_(0), | |
| 35 audio_input_interface_0_1_(NULL) { | |
| 32 } | 36 } |
| 33 virtual ~MyInstance() { | 37 virtual ~MyInstance() { |
| 34 audio_input_.StopCapture(); | 38 if (!audio_input_.is_null()) { |
| 39 audio_input_.Close(); | |
| 40 } else if (audio_input_0_1_ != 0) { | |
| 41 audio_input_interface_0_1_->StopCapture(audio_input_0_1_); | |
| 42 pp::Module::Get()->core()->ReleaseResource(audio_input_0_1_); | |
| 43 } | |
| 44 | |
| 35 delete[] samples_; | 45 delete[] samples_; |
| 36 } | 46 } |
| 37 | 47 |
| 38 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { | 48 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { |
| 39 // This sample frequency is guaranteed to work. | 49 // This sample frequency is guaranteed to work. |
| 40 const PP_AudioSampleRate kSampleFrequency = PP_AUDIOSAMPLERATE_44100; | 50 const PP_AudioSampleRate kSampleFrequency = PP_AUDIOSAMPLERATE_44100; |
| 41 const uint32_t kSampleCount = 1024; | 51 const uint32_t kSampleCount = 1024; |
| 42 const uint32_t kChannelCount = 1; | 52 const uint32_t kChannelCount = 1; |
| 43 | 53 |
| 44 sample_count_ = pp::AudioConfig::RecommendSampleFrameCount(this, | 54 sample_count_ = pp::AudioConfig::RecommendSampleFrameCount(this, |
| 45 kSampleFrequency, | 55 kSampleFrequency, |
| 46 kSampleCount); | 56 kSampleCount); |
| 47 PP_DCHECK(sample_count_ > 0); | 57 PP_DCHECK(sample_count_ > 0); |
| 48 channel_count_ = kChannelCount; | 58 channel_count_ = kChannelCount; |
| 49 pp::AudioConfig config = pp::AudioConfig(this, | 59 pp::AudioConfig config = pp::AudioConfig(this, |
| 50 kSampleFrequency, | 60 kSampleFrequency, |
| 51 sample_count_); | 61 sample_count_); |
| 52 samples_ = new int16_t[sample_count_ * channel_count_]; | 62 samples_ = new int16_t[sample_count_ * channel_count_]; |
| 53 memset(samples_, 0, sample_count_ * channel_count_ * sizeof(int16_t)); | 63 memset(samples_, 0, sample_count_ * channel_count_ * sizeof(int16_t)); |
| 54 audio_input_ = pp::AudioInput_Dev(this, config, CaptureCallback, this); | 64 audio_input_ = pp::AudioInput_Dev(this, config, CaptureCallback, this); |
| 55 if (!audio_input_.StartCapture()) | 65 |
| 66 audio_input_interface_0_1_ = static_cast<const PPB_AudioInput_Dev_0_1*>( | |
| 67 pp::Module::Get()->GetBrowserInterface( | |
| 68 PPB_AUDIO_INPUT_DEV_INTERFACE_0_1)); | |
| 69 if (!audio_input_interface_0_1_) | |
| 56 return false; | 70 return false; |
| 57 | 71 |
| 58 // Try to ensure that we pick up a new set of samples between each | 72 // Try to ensure that we pick up a new set of samples between each |
| 59 // timer-generated repaint. | 73 // timer-generated repaint. |
| 60 timer_interval_ = (sample_count_ * 1000) / kSampleFrequency + 5; | 74 timer_interval_ = (sample_count_ * 1000) / kSampleFrequency + 5; |
| 61 ScheduleNextTimer(); | 75 ScheduleNextTimer(); |
| 62 | 76 |
| 63 return true; | 77 return true; |
| 64 } | 78 } |
| 65 | 79 |
| 66 virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) { | 80 virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) { |
| 67 if (position.size() == size_) | 81 if (position.size() == size_) |
| 68 return; | 82 return; |
| 69 | 83 |
| 70 size_ = position.size(); | 84 size_ = position.size(); |
| 71 device_context_ = pp::Graphics2D(this, size_, false); | 85 device_context_ = pp::Graphics2D(this, size_, false); |
| 72 if (!BindGraphics(device_context_)) | 86 if (!BindGraphics(device_context_)) |
| 73 return; | 87 return; |
| 74 | 88 |
| 75 Paint(); | 89 Paint(); |
| 76 } | 90 } |
| 77 | 91 |
| 92 virtual void HandleMessage(const pp::Var& message_data) { | |
| 93 if (message_data.is_string()) { | |
| 94 std::string event = message_data.AsString(); | |
| 95 if (event == "PageInitialized") { | |
| 96 pp::CompletionCallback callback = callback_factory_.NewCallback( | |
| 97 &MyInstance::EnumerateDevicesFinished); | |
| 98 audio_input_.EnumerateDevices(&devices_, callback); | |
| 99 } else if (event == "UseDefault") { | |
| 100 Open(pp::DeviceRef_Dev()); | |
| 101 } else if (event == "UseDefault(v0.1)") { | |
| 102 audio_input_0_1_ = audio_input_interface_0_1_->Create( | |
| 103 pp_instance(), audio_input_.config().pp_resource(), | |
| 104 CaptureCallback, this); | |
| 105 if (audio_input_0_1_ != 0) { | |
| 106 audio_input_interface_0_1_->StartCapture(audio_input_0_1_); | |
| 107 } else { | |
| 108 PostMessage(pp::Var("OpenFailed")); | |
|
viettrungluu
2012/03/06 19:26:30
Admittedly, it's a bit strange that you check that
yzshen1
2012/03/07 00:30:36
More checks added.
On 2012/03/06 19:26:30, viettr
| |
| 109 } | |
| 110 | |
| 111 audio_input_ = pp::AudioInput_Dev(); | |
| 112 } else if (event == "Stop") { | |
| 113 Stop(); | |
| 114 } | |
| 115 } else if (message_data.is_number()) { | |
| 116 int index = message_data.AsInt(); | |
| 117 if (index >= 0 && index < static_cast<int>(devices_.size())) { | |
| 118 Open(devices_[index]); | |
| 119 } else { | |
| 120 assert(false); | |
|
viettrungluu
2012/03/06 19:26:30
You should probably include some header for this.
yzshen1
2012/03/07 00:30:36
Done.
| |
| 121 } | |
| 122 } | |
| 123 } | |
| 124 | |
| 78 private: | 125 private: |
| 79 void ScheduleNextTimer() { | 126 void ScheduleNextTimer() { |
| 80 PP_DCHECK(timer_interval_ > 0); | 127 PP_DCHECK(timer_interval_ > 0); |
| 81 pp::Module::Get()->core()->CallOnMainThread( | 128 pp::Module::Get()->core()->CallOnMainThread( |
| 82 timer_interval_, | 129 timer_interval_, |
| 83 callback_factory_.NewRequiredCallback(&MyInstance::OnTimer), | 130 callback_factory_.NewRequiredCallback(&MyInstance::OnTimer), |
| 84 0); | 131 0); |
| 85 } | 132 } |
| 86 | 133 |
| 87 void OnTimer(int32_t) { | 134 void OnTimer(int32_t) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 154 // writing to a valid region of memory. | 201 // writing to a valid region of memory. |
| 155 static void CaptureCallback(const void* samples, | 202 static void CaptureCallback(const void* samples, |
| 156 uint32_t num_bytes, | 203 uint32_t num_bytes, |
| 157 void* ctx) { | 204 void* ctx) { |
| 158 MyInstance* thiz = static_cast<MyInstance*>(ctx); | 205 MyInstance* thiz = static_cast<MyInstance*>(ctx); |
| 159 PP_DCHECK(num_bytes == | 206 PP_DCHECK(num_bytes == |
| 160 thiz->sample_count_ * thiz->channel_count_ * sizeof(int16_t)); | 207 thiz->sample_count_ * thiz->channel_count_ * sizeof(int16_t)); |
| 161 memcpy(thiz->samples_, samples, num_bytes); | 208 memcpy(thiz->samples_, samples, num_bytes); |
| 162 } | 209 } |
| 163 | 210 |
| 211 void Open(const pp::DeviceRef_Dev& device) { | |
| 212 pp::CompletionCallback callback = callback_factory_.NewCallback( | |
| 213 &MyInstance::OpenFinished); | |
| 214 audio_input_.Open(device, callback); | |
| 215 } | |
| 216 | |
| 217 void Stop() { | |
| 218 if (!audio_input_.is_null()) { | |
| 219 audio_input_.StopCapture(); | |
| 220 } else if (audio_input_0_1_ != 0) { | |
| 221 audio_input_interface_0_1_->StopCapture(audio_input_0_1_); | |
| 222 } | |
| 223 } | |
| 224 | |
| 225 void EnumerateDevicesFinished(int32_t result) { | |
| 226 static const char* const kDelimiter = "#__#"; | |
| 227 | |
| 228 if (result == PP_OK) { | |
| 229 std::string device_names; | |
| 230 for (size_t index = 0; index < devices_.size(); ++index) { | |
| 231 pp::Var name = devices_[index].GetName(); | |
| 232 assert(name.is_string()); | |
| 233 | |
| 234 if (index != 0) | |
| 235 device_names += kDelimiter; | |
| 236 device_names += name.AsString(); | |
| 237 } | |
| 238 PostMessage(pp::Var(device_names)); | |
| 239 } else { | |
| 240 PostMessage(pp::Var("EnumerationFailed")); | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 void OpenFinished(int32_t result) { | |
| 245 if (result == PP_OK) { | |
| 246 audio_input_.StartCapture(); | |
| 247 } else { | |
| 248 PostMessage(pp::Var("OpenFailed")); | |
| 249 } | |
| 250 } | |
| 251 | |
| 164 pp::CompletionCallbackFactory<MyInstance> callback_factory_; | 252 pp::CompletionCallbackFactory<MyInstance> callback_factory_; |
| 165 | 253 |
| 166 uint32_t sample_count_; | 254 uint32_t sample_count_; |
| 167 uint32_t channel_count_; | 255 uint32_t channel_count_; |
| 168 int16_t* samples_; | 256 int16_t* samples_; |
| 169 | 257 |
| 170 int32_t timer_interval_; | 258 int32_t timer_interval_; |
| 171 | 259 |
| 172 // Painting stuff. | 260 // Painting stuff. |
| 173 pp::Size size_; | 261 pp::Size size_; |
| 174 pp::Graphics2D device_context_; | 262 pp::Graphics2D device_context_; |
| 175 bool pending_paint_; | 263 bool pending_paint_; |
| 176 bool waiting_for_flush_completion_; | 264 bool waiting_for_flush_completion_; |
| 177 | 265 |
| 178 pp::AudioInput_Dev audio_input_; | 266 pp::AudioInput_Dev audio_input_; |
| 267 | |
| 268 PP_Resource audio_input_0_1_; | |
| 269 const PPB_AudioInput_Dev_0_1* audio_input_interface_0_1_; | |
| 270 | |
| 271 std::vector<pp::DeviceRef_Dev> devices_; | |
| 179 }; | 272 }; |
| 180 | 273 |
| 181 class MyModule : public pp::Module { | 274 class MyModule : public pp::Module { |
| 182 public: | 275 public: |
| 183 virtual pp::Instance* CreateInstance(PP_Instance instance) { | 276 virtual pp::Instance* CreateInstance(PP_Instance instance) { |
| 184 return new MyInstance(instance); | 277 return new MyInstance(instance); |
| 185 } | 278 } |
| 186 }; | 279 }; |
| 187 | 280 |
| 188 namespace pp { | 281 namespace pp { |
| 189 | 282 |
| 190 // Factory function for your specialization of the Module object. | 283 // Factory function for your specialization of the Module object. |
| 191 Module* CreateModule() { | 284 Module* CreateModule() { |
| 192 return new MyModule(); | 285 return new MyModule(); |
| 193 } | 286 } |
| 194 | 287 |
| 195 } // namespace pp | 288 } // namespace pp |
| OLD | NEW |