diff options
author | yzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-05 02:44:18 +0000 |
---|---|---|
committer | yzshen@chromium.org <yzshen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-05 02:44:18 +0000 |
commit | 4f01c76ed760e674cb86f2b0a17a779431e2aa71 (patch) | |
tree | a2d874fb3f21b65e07f0d75db567487f6bd4a38a /ppapi/examples | |
parent | 4afef6e27ecbcf6430c5d37881eca04c6b1f8d78 (diff) | |
download | chromium_src-4f01c76ed760e674cb86f2b0a17a779431e2aa71.zip chromium_src-4f01c76ed760e674cb86f2b0a17a779431e2aa71.tar.gz chromium_src-4f01c76ed760e674cb86f2b0a17a779431e2aa71.tar.bz2 |
Introduce PPB_AudioInput_Dev v0.3 and refactor the device enumeration code:
- Add MonitorDeviceChange() for PPB_AudioInput_Dev.
- Change EnumerateDevices() to use PP_ArrayOutput.
- Move device enumeration code out of the audio input implementation, so that it can be shared by video capture.
- Update the audio_input manual test.
- Add unittests for the device enumeration code.
TEST=None
BUG=137799
Review URL: https://chromiumcodereview.appspot.com/11411047
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171132 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi/examples')
-rw-r--r-- | ppapi/examples/audio_input/audio_input.cc | 107 | ||||
-rw-r--r-- | ppapi/examples/audio_input/audio_input.html | 97 |
2 files changed, 146 insertions, 58 deletions
diff --git a/ppapi/examples/audio_input/audio_input.cc b/ppapi/examples/audio_input/audio_input.cc index 11efa63..e2df2b8 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 { diff --git a/ppapi/examples/audio_input/audio_input.html b/ppapi/examples/audio_input/audio_input.html index 8fa043c..2c764bb 100644 --- a/ppapi/examples/audio_input/audio_input.html +++ b/ppapi/examples/audio_input/audio_input.html @@ -8,13 +8,17 @@ <head> <title>Audio Input Example</title> <script type="text/javascript"> - var device_array = []; + var monitor_device_array = []; + var enumerate_device_array = []; + var monitor_notification_count = 0; function HandleMessage(message_event) { if (message_event.data) { var status = document.getElementById('status'); if (message_event.data == 'EnumerationFailed') { status.innerText = 'Device enumeration failed!'; + } else if (message_event.data == 'MonitorDeviceChangeFailed') { + status.innerText = 'Monitor device change failed!'; } else if (message_event.data == 'OpenFailed') { status.innerText = 'Open device failed!'; } else if (message_event.data == 'StartFailed') { @@ -22,23 +26,60 @@ } else if (message_event.data == 'StopFailed') { status.innerText = 'Stop capturing failed!'; } else { - device_array = message_event.data.split('#__#'); - - var list = document.getElementById('device_list'); - for (var i = 0; i < device_array.length; ++i) { - var list_item = document.createElement('li'); - var link = document.createElement('a'); - link.href = 'javascript:UseDesignatedDevice(' + i + ');'; - link.innerText = device_array[i]; - list_item.appendChild(link); - list.appendChild(list_item); - } + AddDevices(message_event.data); } } } - function UseDesignatedDevice(index) { - UseDevice(device_array[index], index); + function AddDevices(command) { + var serialized_names = ''; + var is_monitor = false; + if (command.search('Monitor:') == 0) { + serialized_names = command.substr(8); + is_monitor = true; + monitor_notification_count++; + var counter = document.getElementById('notification_counter'); + counter.innerText = monitor_notification_count; + } else if (command.search('Enumerate:') == 0) { + serialized_names = command.substr(10); + } else { + status.innerText = 'Unrecognized command!'; + return; + } + + var storage = serialized_names.length != 0 ? + serialized_names.split('#__#') : []; + if (is_monitor) + monitor_device_array = storage; + else + enumerate_device_array = storage; + + var list = document.getElementById( + is_monitor ? 'monitor_list' : 'enumerate_list'); + while (list.firstChild) + list.removeChild(list.firstChild); + + for (var i = 0; i < storage.length; ++i) { + AppendDevice( + list, storage[i], + 'javascript:UseDesignatedDevice(' + is_monitor + ',' + i + ');'); + } + } + + function AppendDevice(list, text, href) { + var list_item = document.createElement('li'); + var link = document.createElement('a'); + link.href = href; + link.innerText = text; + list_item.appendChild(link); + list.appendChild(list_item); + } + + function UseDesignatedDevice(is_monitor, index) { + if (is_monitor) + UseDevice(monitor_device_array[index], 'Monitor:' + index); + else + UseDevice(enumerate_device_array[index], 'Enumerate:' + index); } function UseDefaultDevice() { @@ -50,12 +91,6 @@ in_use_device.innerText = display_text; var plugin = document.getElementById('plugin'); plugin.postMessage(command); - - var available_devices = document.getElementById('available_devices'); - available_devices.parentNode.removeChild(available_devices); - - var control_panel = document.getElementById('control_panel'); - control_panel.style.display = 'block'; } function Stop() { @@ -70,7 +105,7 @@ function Initialize() { var plugin = document.getElementById('plugin'); - plugin.addEventListener('message', HandleMessage, false); + plugin.addEventListener('message', HandleMessage, false) plugin.postMessage('PageInitialized'); } @@ -86,14 +121,26 @@ </div> <div id="available_devices"> Available device(s), choose one to open: - <ul id="device_list"> + <ul> <li><a href="javascript:UseDefaultDevice();"> - Default - use interface version 0.2 and NULL device ref</a></li> + Default - use NULL device ref</a></li> </ul> + <div> + <ul>List retrieved by MonitorDeviceChange(), will change when + pluging/unpluging devices: (Notifications received: + <span style="font-weight:bold" id="notification_counter">0</span> + )</ul> + <ul id="monitor_list"/> + </div> + <div> + <ul>List retrieved by EnumerateDevices(), never updated after the page is + initialized:</ul> + <ul id="enumerate_list"/> + </div> </div> - <div id="control_panel" style="display:none"> + <div id="control_panel"> <a href="javascript:Stop();">Stop</a> - <a href="javascript:Start();">Start</a> + <a href="javascript:Start();">Start</a> (known issue: crbug.com/161058) </div> <div id="status"></div> </body> |