Index: ppapi/examples/audio_input/audio_input.cc |
diff --git a/ppapi/examples/audio_input/audio_input.cc b/ppapi/examples/audio_input/audio_input.cc |
index 11efa6306ec23e7f2436390fc7948ca462d8e2ef..e2df2b87ba373efd7ff54e32938bf713a068f146 100644 |
--- a/ppapi/examples/audio_input/audio_input.cc |
+++ b/ppapi/examples/audio_input/audio_input.cc |
@@ -2,6 +2,7 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include <stdlib.h> |
#include <string.h> |
#include <algorithm> |
@@ -32,6 +33,7 @@ namespace { |
const PP_AudioSampleRate kSampleFrequency = PP_AUDIOSAMPLERATE_44100; |
const uint32_t kSampleCount = 1024; |
const uint32_t kChannelCount = 1; |
+const char* const kDelimiter = "#__#"; |
} // namespace |
@@ -48,6 +50,7 @@ class MyInstance : public pp::Instance { |
waiting_for_flush_completion_(false) { |
} |
virtual ~MyInstance() { |
+ device_detector_.MonitorDeviceChange(NULL, NULL); |
audio_input_.Close(); |
delete[] samples_; |
@@ -62,7 +65,7 @@ class MyInstance : public pp::Instance { |
samples_ = new int16_t[sample_count_ * channel_count_]; |
memset(samples_, 0, sample_count_ * channel_count_ * sizeof(int16_t)); |
- audio_input_ = pp::AudioInput_Dev(this); |
+ device_detector_ = pp::AudioInput_Dev(this); |
// Try to ensure that we pick up a new set of samples between each |
// timer-generated repaint. |
@@ -88,10 +91,15 @@ class MyInstance : public pp::Instance { |
if (message_data.is_string()) { |
std::string event = message_data.AsString(); |
if (event == "PageInitialized") { |
+ int32_t result = device_detector_.MonitorDeviceChange( |
+ &MyInstance::MonitorDeviceChangeCallback, this); |
+ if (result != PP_OK) |
+ PostMessage(pp::Var("MonitorDeviceChangeFailed")); |
+ |
pp::CompletionCallbackWithOutput<std::vector<pp::DeviceRef_Dev> > |
callback = callback_factory_.NewCallbackWithOutput( |
&MyInstance::EnumerateDevicesFinished); |
- int32_t result = audio_input_.EnumerateDevices(callback); |
+ result = device_detector_.EnumerateDevices(callback); |
if (result != PP_OK_COMPLETIONPENDING) |
PostMessage(pp::Var("EnumerationFailed")); |
} else if (event == "UseDefault") { |
@@ -100,13 +108,20 @@ class MyInstance : public pp::Instance { |
Stop(); |
} else if (event == "Start") { |
Start(); |
- } |
- } else if (message_data.is_number()) { |
- int index = message_data.AsInt(); |
- if (index >= 0 && index < static_cast<int>(devices_.size())) { |
- Open(devices_[index]); |
- } else { |
- PP_NOTREACHED(); |
+ } else if (event.find("Monitor:") == 0) { |
+ std::string index_str = event.substr(strlen("Monitor:")); |
+ int index = atoi(index_str.c_str()); |
+ if (index >= 0 && index < static_cast<int>(monitor_devices_.size())) |
+ Open(monitor_devices_[index]); |
+ else |
+ PP_NOTREACHED(); |
+ } else if (event.find("Enumerate:") == 0) { |
+ std::string index_str = event.substr(strlen("Enumerate:")); |
+ int index = atoi(index_str.c_str()); |
+ if (index >= 0 && index < static_cast<int>(enumerate_devices_.size())) |
+ Open(enumerate_devices_[index]); |
+ else |
+ PP_NOTREACHED(); |
} |
} |
} |
@@ -184,24 +199,10 @@ class MyInstance : public pp::Instance { |
return image; |
} |
- // TODO(viettrungluu): Danger! We really should lock, but which thread |
- // primitives to use? In any case, the |StopCapture()| in the destructor |
- // shouldn't return until this callback is done, so at least we should be |
- // writing to a valid region of memory. |
- static void CaptureCallback(const void* samples, |
- uint32_t num_bytes, |
- void* ctx) { |
- MyInstance* thiz = static_cast<MyInstance*>(ctx); |
- uint32_t buffer_size = |
- thiz->sample_count_ * thiz->channel_count_ * sizeof(int16_t); |
- PP_DCHECK(num_bytes <= buffer_size); |
- PP_DCHECK(num_bytes % (thiz->channel_count_ * sizeof(int16_t)) == 0); |
- memcpy(thiz->samples_, samples, num_bytes); |
- memset(reinterpret_cast<char*>(thiz->samples_) + num_bytes, 0, |
- buffer_size - num_bytes); |
- } |
- |
void Open(const pp::DeviceRef_Dev& device) { |
+ audio_input_.Close(); |
+ audio_input_ = pp::AudioInput_Dev(this); |
+ |
pp::AudioConfig config = pp::AudioConfig(this, |
kSampleFrequency, |
sample_count_); |
@@ -225,13 +226,11 @@ class MyInstance : public pp::Instance { |
void EnumerateDevicesFinished(int32_t result, |
std::vector<pp::DeviceRef_Dev>& devices) { |
- static const char* const kDelimiter = "#__#"; |
- |
if (result == PP_OK) { |
- devices_.swap(devices); |
- std::string device_names; |
- for (size_t index = 0; index < devices_.size(); ++index) { |
- pp::Var name = devices_[index].GetName(); |
+ enumerate_devices_.swap(devices); |
+ std::string device_names = "Enumerate:"; |
+ for (size_t index = 0; index < enumerate_devices_.size(); ++index) { |
+ pp::Var name = enumerate_devices_[index].GetName(); |
PP_DCHECK(name.is_string()); |
if (index != 0) |
@@ -253,6 +252,43 @@ class MyInstance : public pp::Instance { |
} |
} |
+ // TODO(viettrungluu): Danger! We really should lock, but which thread |
+ // primitives to use? In any case, the |StopCapture()| in the destructor |
+ // shouldn't return until this callback is done, so at least we should be |
+ // writing to a valid region of memory. |
+ static void CaptureCallback(const void* samples, |
+ uint32_t num_bytes, |
+ void* ctx) { |
+ MyInstance* thiz = static_cast<MyInstance*>(ctx); |
+ uint32_t buffer_size = |
+ thiz->sample_count_ * thiz->channel_count_ * sizeof(int16_t); |
+ PP_DCHECK(num_bytes <= buffer_size); |
+ PP_DCHECK(num_bytes % (thiz->channel_count_ * sizeof(int16_t)) == 0); |
+ memcpy(thiz->samples_, samples, num_bytes); |
+ memset(reinterpret_cast<char*>(thiz->samples_) + num_bytes, 0, |
+ buffer_size - num_bytes); |
+ } |
+ |
+ static void MonitorDeviceChangeCallback(void* user_data, |
+ uint32_t device_count, |
+ const PP_Resource devices[]) { |
+ MyInstance* thiz = static_cast<MyInstance*>(user_data); |
+ |
+ std::string device_names = "Monitor:"; |
+ thiz->monitor_devices_.clear(); |
+ thiz->monitor_devices_.reserve(device_count); |
+ for (size_t index = 0; index < device_count; ++index) { |
+ thiz->monitor_devices_.push_back(pp::DeviceRef_Dev(devices[index])); |
+ pp::Var name = thiz->monitor_devices_.back().GetName(); |
+ PP_DCHECK(name.is_string()); |
+ |
+ if (index != 0) |
+ device_names += kDelimiter; |
+ device_names += name.AsString(); |
+ } |
+ thiz->PostMessage(pp::Var(device_names)); |
+ } |
+ |
pp::CompletionCallbackFactory<MyInstance> callback_factory_; |
uint32_t sample_count_; |
@@ -267,9 +303,14 @@ class MyInstance : public pp::Instance { |
bool pending_paint_; |
bool waiting_for_flush_completion_; |
+ // There is no need to have two resources to do capturing and device detecting |
+ // separately. However, this makes the code of monitoring device change |
+ // easier. |
pp::AudioInput_Dev audio_input_; |
+ pp::AudioInput_Dev device_detector_; |
- std::vector<pp::DeviceRef_Dev> devices_; |
+ std::vector<pp::DeviceRef_Dev> enumerate_devices_; |
+ std::vector<pp::DeviceRef_Dev> monitor_devices_; |
}; |
class MyModule : public pp::Module { |