aboutsummaryrefslogtreecommitdiff
path: root/www
diff options
context:
space:
mode:
authorCarlos J. Puga Medina <cpm@FreeBSD.org>2017-06-27 21:49:15 +0000
committerCarlos J. Puga Medina <cpm@FreeBSD.org>2017-06-27 21:49:15 +0000
commit3147ca34a4e3980ff609b8a9783b4bb252d87cdf (patch)
treebca0774af9b4492d93ccb2de3698e9f13e63306c /www
parent213a4299f5e742331eeb5cb9dd3de478dfc84748 (diff)
downloadports-3147ca34a4e3980ff609b8a9783b4bb252d87cdf.tar.gz
ports-3147ca34a4e3980ff609b8a9783b4bb252d87cdf.zip
www/iridium: add SNDIO option
PR: 220230 Submitted by: tobik
Notes
Notes: svn path=/head/; revision=444519
Diffstat (limited to 'www')
-rw-r--r--www/iridium/Makefile16
-rw-r--r--www/iridium/files/audio_manager_openbsd.cc205
-rw-r--r--www/iridium/files/audio_manager_openbsd.h69
-rw-r--r--www/iridium/files/patch-media_BUILD.gn13
-rw-r--r--www/iridium/files/patch-media_audio_BUILD.gn16
-rw-r--r--www/iridium/files/patch-media_media_options.gni13
-rw-r--r--www/iridium/files/sndio_input.cc190
-rw-r--r--www/iridium/files/sndio_input.h108
-rw-r--r--www/iridium/files/sndio_output.cc177
-rw-r--r--www/iridium/files/sndio_output.h92
10 files changed, 896 insertions, 3 deletions
diff --git a/www/iridium/Makefile b/www/iridium/Makefile
index 6a852c2f4da6..8cd9d559a19e 100644
--- a/www/iridium/Makefile
+++ b/www/iridium/Makefile
@@ -104,7 +104,7 @@ SUB_LIST+= COMMENT="${COMMENT}"
OPTIONS_DEFINE= CODECS DEBUG GCONF KERBEROS
CODECS_DESC= Compile and enable patented codecs like H.264
OPTIONS_GROUP= AUDIO
-OPTIONS_GROUP_AUDIO= ALSA PULSEAUDIO
+OPTIONS_GROUP_AUDIO= ALSA PULSEAUDIO SNDIO
OPTIONS_DEFAULT= ALSA CODECS GCONF KERBEROS
OPTIONS_SUB= yes
@@ -114,6 +114,14 @@ ALSA_LIB_DEPENDS= libasound.so:audio/alsa-lib
ALSA_RUN_DEPENDS= ${LOCALBASE}/lib/alsa-lib/libasound_module_pcm_oss.so:audio/alsa-plugins \
alsa-lib>=1.1.1_1:audio/alsa-lib
PULSEAUDIO_LIB_DEPENDS= libpulse.so:audio/pulseaudio
+# With SNDIO=on we exclude audio_manager_linux from the build (see
+# media/audio/BUILD.gn) and use audio_manager_openbsd which does not
+# support falling back to ALSA. In theory it supports falling back to
+# PulseAudio, but this is untested.
+SNDIO_PREVENTS= ALSA PULSEAUDIO
+SNDIO_LIB_DEPENDS= libsndio.so:audio/sndio
+SNDIO_VARS= GN_ARGS+=use_sndio=true
+SNDIO_VARS_OFF= GN_ARGS+=use_sndio=false
.include <bsd.port.options.mk>
@@ -192,6 +200,12 @@ pre-everything::
.endif
@${ECHO_MSG}
+post-patch-SNDIO-on:
+ @${MKDIR} ${WRKSRC}/media/audio/sndio ${WRKSRC}/media/audio/openbsd
+ @${CP} ${FILESDIR}/sndio_output.* ${WRKSRC}/media/audio/sndio
+ @${CP} ${FILESDIR}/sndio_input.* ${WRKSRC}/media/audio/sndio
+ @${CP} ${FILESDIR}/audio_manager_openbsd.* ${WRKSRC}/media/audio/openbsd
+
pre-configure:
# We used to remove bundled libraries to be sure that iridium uses
# system libraries and not shippen ones.
diff --git a/www/iridium/files/audio_manager_openbsd.cc b/www/iridium/files/audio_manager_openbsd.cc
new file mode 100644
index 000000000000..dd4a30fa4669
--- /dev/null
+++ b/www/iridium/files/audio_manager_openbsd.cc
@@ -0,0 +1,205 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/metrics/histogram_macros.h"
+
+#include "media/audio/openbsd/audio_manager_openbsd.h"
+
+#include "media/audio/audio_device_description.h"
+#include "media/audio/audio_output_dispatcher.h"
+#if defined(USE_PULSEAUDIO)
+#include "media/audio/pulse/audio_manager_pulse.h"
+#endif
+#if defined(USE_SNDIO)
+#include "media/audio/sndio/sndio_input.h"
+#include "media/audio/sndio/sndio_output.h"
+#else
+#include "media/audio/fake_audio_manager.h"
+#endif
+#include "media/base/limits.h"
+#include "media/base/media_switches.h"
+
+namespace media {
+
+enum OpenBSDAudioIO {
+ kPulse,
+ kSndio,
+ kAudioIOMax = kSndio
+};
+
+#if defined(USE_SNDIO)
+// Maximum number of output streams that can be open simultaneously.
+static const int kMaxOutputStreams = 4;
+
+// Default sample rate for input and output streams.
+static const int kDefaultSampleRate = 48000;
+
+void AddDefaultDevice(AudioDeviceNames* device_names) {
+ DCHECK(device_names->empty());
+ device_names->push_front(AudioDeviceName::CreateDefault());
+}
+
+bool AudioManagerOpenBSD::HasAudioOutputDevices() {
+ return true;
+}
+
+bool AudioManagerOpenBSD::HasAudioInputDevices() {
+ return true;
+}
+
+void AudioManagerOpenBSD::ShowAudioInputSettings() {
+ NOTIMPLEMENTED();
+}
+
+void AudioManagerOpenBSD::GetAudioInputDeviceNames(
+ AudioDeviceNames* device_names) {
+ DCHECK(device_names->empty());
+ AddDefaultDevice(device_names);
+}
+
+void AudioManagerOpenBSD::GetAudioOutputDeviceNames(
+ AudioDeviceNames* device_names) {
+ AddDefaultDevice(device_names);
+}
+
+#if defined(USE_SNDIO)
+const char* AudioManagerOpenBSD::GetName() {
+ return "SNDIO";
+}
+#endif
+
+AudioParameters AudioManagerOpenBSD::GetInputStreamParameters(
+ const std::string& device_id) {
+ static const int kDefaultInputBufferSize = 1024;
+
+ int user_buffer_size = GetUserBufferSize();
+ int buffer_size = user_buffer_size ?
+ user_buffer_size : kDefaultInputBufferSize;
+
+ return AudioParameters(
+ AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
+ kDefaultSampleRate, 16, buffer_size);
+}
+
+AudioManagerOpenBSD::AudioManagerOpenBSD(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory)
+ : AudioManagerBase(std::move(task_runner),
+ std::move(worker_task_runner),
+ audio_log_factory) {
+ DLOG(WARNING) << "AudioManagerOpenBSD";
+ SetMaxOutputStreamsAllowed(kMaxOutputStreams);
+}
+
+AudioManagerOpenBSD::~AudioManagerOpenBSD() {
+ Shutdown();
+}
+
+AudioOutputStream* AudioManagerOpenBSD::MakeLinearOutputStream(
+ const AudioParameters& params,
+ const LogCallback& log_callback) {
+ DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
+ return MakeOutputStream(params);
+}
+
+AudioOutputStream* AudioManagerOpenBSD::MakeLowLatencyOutputStream(
+ const AudioParameters& params,
+ const std::string& device_id,
+ const LogCallback& log_callback) {
+ DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
+ DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+ return MakeOutputStream(params);
+}
+
+AudioInputStream* AudioManagerOpenBSD::MakeLinearInputStream(
+ const AudioParameters& params,
+ const std::string& device_id,
+ const LogCallback& log_callback) {
+ DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
+ return MakeInputStream(params);
+}
+
+AudioInputStream* AudioManagerOpenBSD::MakeLowLatencyInputStream(
+ const AudioParameters& params,
+ const std::string& device_id,
+ const LogCallback& log_callback) {
+ DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
+ return MakeInputStream(params);
+}
+
+AudioParameters AudioManagerOpenBSD::GetPreferredOutputStreamParameters(
+ const std::string& output_device_id,
+ const AudioParameters& input_params) {
+ // TODO(tommi): Support |output_device_id|.
+ DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
+ static const int kDefaultOutputBufferSize = 2048;
+
+ ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
+ int sample_rate = kDefaultSampleRate;
+ int buffer_size = kDefaultOutputBufferSize;
+ int bits_per_sample = 16;
+ if (input_params.IsValid()) {
+ sample_rate = input_params.sample_rate();
+ bits_per_sample = input_params.bits_per_sample();
+ channel_layout = input_params.channel_layout();
+ buffer_size = std::min(buffer_size, input_params.frames_per_buffer());
+ }
+
+ int user_buffer_size = GetUserBufferSize();
+ if (user_buffer_size)
+ buffer_size = user_buffer_size;
+
+ return AudioParameters(
+ AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
+ sample_rate, bits_per_sample, buffer_size);
+}
+
+AudioInputStream* AudioManagerOpenBSD::MakeInputStream(
+ const AudioParameters& params) {
+ DLOG(WARNING) << "MakeInputStream";
+ return new SndioAudioInputStream(this,
+ AudioDeviceDescription::kDefaultDeviceId, params);
+}
+
+AudioOutputStream* AudioManagerOpenBSD::MakeOutputStream(
+ const AudioParameters& params) {
+ DLOG(WARNING) << "MakeOutputStream";
+ return new SndioAudioOutputStream(params, this);
+}
+#endif
+
+ScopedAudioManagerPtr CreateAudioManager(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory) {
+ DLOG(WARNING) << "CreateAudioManager";
+#if defined(USE_PULSEAUDIO)
+ // Do not move task runners when creating AudioManagerPulse.
+ // If the creation fails, we need to use the task runners to create other
+ // AudioManager implementations.
+ std::unique_ptr<AudioManagerPulse, AudioManagerDeleter> manager(
+ new AudioManagerPulse(task_runner, worker_task_runner,
+ audio_log_factory));
+ if (manager->Init()) {
+ UMA_HISTOGRAM_ENUMERATION("Media.OpenBSDAudioIO", kPulse, kAudioIOMax + 1);
+ return std::move(manager);
+ }
+ DVLOG(1) << "PulseAudio is not available on the OS";
+#endif
+
+#if defined(USE_SNDIO)
+ UMA_HISTOGRAM_ENUMERATION("Media.OpenBSDAudioIO", kSndio, kAudioIOMax + 1);
+ return ScopedAudioManagerPtr(
+ new AudioManagerOpenBSD(std::move(task_runner),
+ std::move(worker_task_runner),audio_log_factory));
+#else
+ return ScopedAudioManagerPtr(
+ new FakeAudioManager(std::move(task_runner),
+ std::move(worker_task_runner), audio_log_factory));
+#endif
+
+}
+
+} // namespace media
diff --git a/www/iridium/files/audio_manager_openbsd.h b/www/iridium/files/audio_manager_openbsd.h
new file mode 100644
index 000000000000..2972e3661d0d
--- /dev/null
+++ b/www/iridium/files/audio_manager_openbsd.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
+#define MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
+
+#include <set>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/threading/thread.h"
+#include "media/audio/audio_manager_base.h"
+
+namespace media {
+
+class MEDIA_EXPORT AudioManagerOpenBSD : public AudioManagerBase {
+ public:
+ AudioManagerOpenBSD(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
+ AudioLogFactory* audio_log_factory);
+
+ // Implementation of AudioManager.
+ bool HasAudioOutputDevices() override;
+ bool HasAudioInputDevices() override;
+ void ShowAudioInputSettings() override;
+ void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
+ void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override;
+ AudioParameters GetInputStreamParameters(
+ const std::string& device_id) override;
+ const char* GetName() override;
+
+ // Implementation of AudioManagerBase.
+ AudioOutputStream* MakeLinearOutputStream(
+ const AudioParameters& params,
+ const LogCallback& log_callback) override;
+ AudioOutputStream* MakeLowLatencyOutputStream(
+ const AudioParameters& params,
+ const std::string& device_id,
+ const LogCallback& log_callback) override;
+ AudioInputStream* MakeLinearInputStream(
+ const AudioParameters& params,
+ const std::string& device_id,
+ const LogCallback& log_callback) override;
+ AudioInputStream* MakeLowLatencyInputStream(
+ const AudioParameters& params,
+ const std::string& device_id,
+ const LogCallback& log_callback) override;
+
+ protected:
+ ~AudioManagerOpenBSD() override;
+
+ AudioParameters GetPreferredOutputStreamParameters(
+ const std::string& output_device_id,
+ const AudioParameters& input_params) override;
+
+ private:
+ // Called by MakeLinearOutputStream and MakeLowLatencyOutputStream.
+ AudioOutputStream* MakeOutputStream(const AudioParameters& params);
+ AudioInputStream* MakeInputStream(const AudioParameters& params);
+
+ DISALLOW_COPY_AND_ASSIGN(AudioManagerOpenBSD);
+};
+
+} // namespace media
+
+#endif // MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
diff --git a/www/iridium/files/patch-media_BUILD.gn b/www/iridium/files/patch-media_BUILD.gn
new file mode 100644
index 000000000000..4940a243030a
--- /dev/null
+++ b/www/iridium/files/patch-media_BUILD.gn
@@ -0,0 +1,13 @@
+$OpenBSD: patch-media_BUILD_gn,v 1.2 2017/04/28 22:22:36 robert Exp $
+--- media/BUILD.gn.orig.port Wed Apr 19 21:06:35 2017
++++ media/BUILD.gn Thu Apr 27 19:56:02 2017
+@@ -56,6 +56,9 @@ config("media_config") {
+ defines += [ "DLOPEN_PULSEAUDIO" ]
+ }
+ }
++ if (use_sndio) {
++ defines += [ "USE_SNDIO" ]
++ }
+ if (use_cras) {
+ defines += [ "USE_CRAS" ]
+ }
diff --git a/www/iridium/files/patch-media_audio_BUILD.gn b/www/iridium/files/patch-media_audio_BUILD.gn
index 0c873b467e77..93a30a4e7abd 100644
--- a/www/iridium/files/patch-media_audio_BUILD.gn
+++ b/www/iridium/files/patch-media_audio_BUILD.gn
@@ -1,14 +1,26 @@
--- media/audio/BUILD.gn.orig 2017-04-19 19:06:35 UTC
+++ media/audio/BUILD.gn
-@@ -212,7 +212,7 @@ source_set("audio") {
+@@ -212,9 +212,19 @@ source_set("audio") {
deps += [ "//media/base/android:media_jni_headers" ]
}
- if (is_linux) {
-+ if (is_linux || is_bsd) {
++ if (is_linux || (is_bsd && !use_sndio)) {
sources += [ "linux/audio_manager_linux.cc" ]
}
++ if (use_sndio) {
++ libs += [ "sndio" ]
++ sources += [
++ "openbsd/audio_manager_openbsd.cc",
++ "sndio/sndio_input.cc",
++ "sndio/sndio_input.h",
++ "sndio/sndio_output.cc",
++ "sndio/sndio_output.h"
++ ]
++ }
+ if (use_alsa) {
+ libs += [ "asound" ]
@@ -261,10 +261,12 @@ source_set("audio") {
configs += [ ":libpulse" ]
} else {
diff --git a/www/iridium/files/patch-media_media_options.gni b/www/iridium/files/patch-media_media_options.gni
new file mode 100644
index 000000000000..882c7016b00d
--- /dev/null
+++ b/www/iridium/files/patch-media_media_options.gni
@@ -0,0 +1,13 @@
+$OpenBSD: patch-media_media_options_gni,v 1.3 2017/04/28 22:22:36 robert Exp $
+--- media/media_options.gni.orig 2017-04-19 21:06:35.000000000 +0200
++++ media/media_options.gni 2017-05-06 22:11:03.288488000 +0200
+@@ -73,6 +73,9 @@
+ # Enables runtime selection of ALSA library for audio.
+ use_alsa = false
+
++ # Enable runtime selection of sndio(7)
++ use_sndio = false
++
+ # Alsa should be used on non-Android, non-Mac POSIX systems.
+ # Alsa should be used on desktop Chromecast and audio-only Chromecast builds.
+ if (is_posix && !is_android && !is_mac &&
diff --git a/www/iridium/files/sndio_input.cc b/www/iridium/files/sndio_input.cc
new file mode 100644
index 000000000000..948fb1089f7c
--- /dev/null
+++ b/www/iridium/files/sndio_input.cc
@@ -0,0 +1,190 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/audio/sndio/sndio_input.h"
+
+#include <stddef.h>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/message_loop/message_loop.h"
+#include "media/audio/openbsd/audio_manager_openbsd.h"
+#include "media/audio/audio_manager.h"
+
+namespace media {
+
+void sndio_in_onmove(void *arg, int delta) {
+ NOTIMPLEMENTED();
+ SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
+
+ self->hw_delay_ = delta - self->params_.GetBytesPerFrame();
+}
+
+void *sndio_in_threadstart(void *arg) {
+ NOTIMPLEMENTED();
+ SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
+
+ self->ReadAudio();
+ return NULL;
+}
+
+SndioAudioInputStream::SndioAudioInputStream(AudioManagerBase* audio_manager,
+ const std::string& device_name,
+ const AudioParameters& params)
+ : audio_manager_(audio_manager),
+ device_name_(device_name),
+ params_(params),
+ bytes_per_buffer_(params.frames_per_buffer() *
+ (params.channels() * params.bits_per_sample()) /
+ 8),
+ buffer_duration_(base::TimeDelta::FromMicroseconds(
+ params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
+ static_cast<float>(params.sample_rate()))),
+ callback_(NULL),
+ device_handle_(NULL),
+ read_callback_behind_schedule_(false),
+ audio_bus_(AudioBus::Create(params)) {
+}
+
+SndioAudioInputStream::~SndioAudioInputStream() {}
+
+bool SndioAudioInputStream::Open() {
+ struct sio_par par;
+ int sig;
+
+ if (device_handle_)
+ return false; // Already open.
+
+ if (params_.format() != AudioParameters::AUDIO_PCM_LINEAR &&
+ params_.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
+ LOG(WARNING) << "Unsupported audio format.";
+ return false;
+ }
+
+ sio_initpar(&par);
+ par.rate = params_.sample_rate();
+ par.pchan = params_.channels();
+ par.bits = params_.bits_per_sample();
+ par.bps = par.bits / 8;
+ par.sig = sig = par.bits != 8 ? 1 : 0;
+ par.le = SIO_LE_NATIVE;
+ par.appbufsz = params_.frames_per_buffer();
+ sndio_rec_bufsz_ = par.bufsz;
+ sndio_rec_bufsize_ = par.round * par.bps * par.rchan;
+
+ device_handle_ = sio_open(SIO_DEVANY, SIO_REC, 0);
+
+ if (device_handle_ == NULL) {
+ LOG(ERROR) << "Couldn't open audio device.";
+ return false;
+ }
+
+ if (!sio_setpar(device_handle_, &par) || !sio_getpar(device_handle_, &par)) {
+ LOG(ERROR) << "Couldn't set audio parameters.";
+ goto bad_close;
+ }
+
+ if (par.rate != (unsigned int)params_.sample_rate() ||
+ par.pchan != (unsigned int)params_.channels() ||
+ par.bits != (unsigned int)params_.bits_per_sample() ||
+ par.sig != (unsigned int)sig ||
+ (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
+ (par.bits != par.bps * 8)) {
+ LOG(ERROR) << "Unsupported audio parameters.";
+ goto bad_close;
+ }
+ sio_onmove(device_handle_, sndio_in_onmove, this);
+
+ audio_buffer_.reset(new uint8_t[bytes_per_buffer_]);
+
+ return true;
+bad_close:
+ sio_close(device_handle_);
+ return false;
+}
+
+void SndioAudioInputStream::Start(AudioInputCallback* callback) {
+ DCHECK(!callback_ && callback);
+ callback_ = callback;
+ StartAgc();
+
+ // We start reading data half |buffer_duration_| later than when the
+ // buffer might have got filled, to accommodate some delays in the audio
+ // driver. This could also give us a smooth read sequence going forward.
+ base::TimeDelta delay = buffer_duration_ + buffer_duration_ / 2;
+ next_read_time_ = base::TimeTicks::Now() + delay;
+ if (pthread_create(&thread_, NULL, sndio_in_threadstart, this) != 0)
+ LOG(ERROR) << "Failed to create real-time thread.";
+}
+
+void SndioAudioInputStream::ReadAudio() {
+ NOTIMPLEMENTED();
+ DCHECK(callback_);
+
+ int num_buffers = sndio_rec_bufsize_ / params_.frames_per_buffer();
+ double normalized_volume = 0.0;
+
+ // Update the AGC volume level once every second. Note that, |volume| is
+ // also updated each time SetVolume() is called through IPC by the
+ // render-side AGC.
+ GetAgcVolume(&normalized_volume);
+
+ while (num_buffers--) {
+ int frames_read = sio_read(device_handle_, audio_buffer_.get(),
+ params_.frames_per_buffer());
+ if (frames_read == params_.frames_per_buffer()) {
+ audio_bus_->FromInterleaved(audio_buffer_.get(),
+ audio_bus_->frames(),
+ params_.bits_per_sample() / 8);
+ callback_->OnData(
+ this, audio_bus_.get(), hw_delay_, normalized_volume);
+ } else {
+ LOG(WARNING) << "sio_read() returning less than expected frames: "
+ << frames_read << " vs. " << params_.frames_per_buffer()
+ << ". Dropping this buffer.";
+ }
+ }
+}
+
+void SndioAudioInputStream::Stop() {
+ if (!device_handle_ || !callback_)
+ return;
+
+ StopAgc();
+
+ pthread_join(thread_, NULL);
+ sio_stop(device_handle_);
+
+ callback_ = NULL;
+}
+
+void SndioAudioInputStream::Close() {
+ if (device_handle_) {
+ sio_close(device_handle_);
+ audio_buffer_.reset();
+ device_handle_ = NULL;
+ }
+
+ audio_manager_->ReleaseInputStream(this);
+}
+
+double SndioAudioInputStream::GetMaxVolume() {
+ return static_cast<double>(SIO_MAXVOL);
+}
+
+void SndioAudioInputStream::SetVolume(double volume) {
+ NOTIMPLEMENTED();
+}
+
+double SndioAudioInputStream::GetVolume() {
+ long current_volume = 0;
+ return static_cast<double>(current_volume);
+}
+
+bool SndioAudioInputStream::IsMuted() {
+ return false;
+}
+
+} // namespace media
diff --git a/www/iridium/files/sndio_input.h b/www/iridium/files/sndio_input.h
new file mode 100644
index 000000000000..b354f66fd55a
--- /dev/null
+++ b/www/iridium/files/sndio_input.h
@@ -0,0 +1,108 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
+#define MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
+
+#include <stdint.h>
+#include <string>
+#include <sndio.h>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "media/audio/agc_audio_stream.h"
+#include "media/audio/audio_io.h"
+#include "media/audio/audio_device_description.h"
+#include "media/base/audio_parameters.h"
+
+namespace media {
+
+class AudioManagerBase;
+
+// call-backs invoked from C libraries, thus requiring C linkage
+extern "C" {
+ // Invoked (on the real-time thread) at each sound card clock tick
+ void sndio_in_onmove(void *arg, int delta);
+ // Invoked (on the real-time thread) whenever the volume changes
+ void sndio_in_onvol(void *arg, unsigned int vol);
+ // Real-time thread entry point
+ void *sndio_in_threadstart(void *arg);
+}
+
+// Provides an input stream for audio capture based on the SNDIO PCM interface.
+// This object is not thread safe and all methods should be invoked in the
+// thread that created the object.
+class SndioAudioInputStream : public AgcAudioStream<AudioInputStream> {
+ public:
+ // Pass this to the constructor if you want to attempt auto-selection
+ // of the audio recording device.
+ static const char kAutoSelectDevice[];
+
+ // Create a PCM Output stream for the SNDIO device identified by
+ // |device_name|. If unsure of what to use for |device_name|, use
+ // |kAutoSelectDevice|.
+ SndioAudioInputStream(AudioManagerBase* audio_manager,
+ const std::string& device_name,
+ const AudioParameters& params);
+
+ ~SndioAudioInputStream() override;
+
+ // Implementation of AudioInputStream.
+ bool Open() override;
+ void Start(AudioInputCallback* callback) override;
+ void Stop() override;
+ void Close() override;
+ double GetMaxVolume() override;
+ void SetVolume(double volume) override;
+ double GetVolume() override;
+ bool IsMuted() override;
+
+ // C-linkage call-backs are friends to access private data
+ friend void sndio_in_onmove(void *arg, int delta);
+ friend void sndio_in_onvol(void *arg, unsigned int vol);
+ friend void *sndio_in_threadstart(void *arg);
+
+ private:
+ // Logs the error and invokes any registered callbacks.
+ void HandleError(const char* method, int error);
+
+ // Reads one or more buffers of audio from the device, passes on to the
+ // registered callback and schedules the next read.
+ void ReadAudio();
+
+ // Recovers from any device errors if possible.
+ bool Recover(int error);
+
+ // Non-refcounted pointer back to the audio manager.
+ // The AudioManager indirectly holds on to stream objects, so we don't
+ // want circular references. Additionally, stream objects live on the audio
+ // thread, which is owned by the audio manager and we don't want to addref
+ // the manager from that thread.
+ AudioManagerBase* audio_manager_;
+ std::string device_name_;
+ AudioParameters params_;
+ int bytes_per_buffer_;
+ base::TimeDelta buffer_duration_; // Length of each recorded buffer.
+ AudioInputCallback* callback_; // Valid during a recording session.
+ base::TimeTicks next_read_time_; // Scheduled time for next read callback.
+ struct sio_hdl* device_handle_; // Handle to the SNDIO PCM recording device.
+ std::unique_ptr<uint8_t[]> audio_buffer_; // Buffer used for reading audio data.
+ bool read_callback_behind_schedule_;
+ std::unique_ptr<AudioBus> audio_bus_;
+
+ int hw_delay_;
+ int sndio_rec_bufsize_;
+ int sndio_rec_bufsz_;
+
+ // High priority thread running RealTimeThread()
+ pthread_t thread_;
+
+ DISALLOW_COPY_AND_ASSIGN(SndioAudioInputStream);
+};
+
+} // namespace media
+
+#endif // MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
diff --git a/www/iridium/files/sndio_output.cc b/www/iridium/files/sndio_output.cc
new file mode 100644
index 000000000000..27c6c1db285a
--- /dev/null
+++ b/www/iridium/files/sndio_output.cc
@@ -0,0 +1,177 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "base/time/time.h"
+#include "base/time/default_tick_clock.h"
+#include "media/audio/audio_manager_base.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/audio/sndio/sndio_output.h"
+
+namespace media {
+
+void sndio_onmove(void *arg, int delta) {
+ SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
+
+ self->hw_delay = delta;
+}
+
+void sndio_onvol(void *arg, unsigned int vol) {
+ SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
+
+ self->vol = vol;
+}
+
+void *sndio_threadstart(void *arg) {
+ SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
+
+ self->RealTimeThread();
+ return NULL;
+}
+
+SndioAudioOutputStream::SndioAudioOutputStream(const AudioParameters& params,
+ AudioManagerBase* manager)
+ : manager(manager),
+ params(params),
+ audio_bus(AudioBus::Create(params)),
+ bytes_per_frame(params.GetBytesPerFrame()),
+ state(kClosed),
+ mutex(PTHREAD_MUTEX_INITIALIZER) {
+}
+
+SndioAudioOutputStream::~SndioAudioOutputStream() {
+ if (state != kClosed)
+ Close();
+}
+
+bool SndioAudioOutputStream::Open() {
+ struct sio_par par;
+ int sig;
+
+ if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
+ params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
+ LOG(WARNING) << "Unsupported audio format.";
+ return false;
+ }
+ sio_initpar(&par);
+ par.rate = params.sample_rate();
+ par.pchan = params.channels();
+ par.bits = params.bits_per_sample();
+ par.bps = par.bits / 8;
+ par.sig = sig = par.bits != 8 ? 1 : 0;
+ par.le = SIO_LE_NATIVE;
+ par.appbufsz = params.frames_per_buffer();
+
+ hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
+ if (hdl == NULL) {
+ LOG(ERROR) << "Couldn't open audio device.";
+ return false;
+ }
+ if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
+ LOG(ERROR) << "Couldn't set audio parameters.";
+ goto bad_close;
+ }
+ if (par.rate != (unsigned int)params.sample_rate() ||
+ par.pchan != (unsigned int)params.channels() ||
+ par.bits != (unsigned int)params.bits_per_sample() ||
+ par.sig != (unsigned int)sig ||
+ (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
+ (par.bits != par.bps * 8)) {
+ LOG(ERROR) << "Unsupported audio parameters.";
+ goto bad_close;
+ }
+ state = kStopped;
+ volpending = 0;
+ vol = 0;
+ buffer = new char[audio_bus->frames() * params.GetBytesPerFrame()];
+ sio_onmove(hdl, sndio_onmove, this);
+ sio_onvol(hdl, sndio_onvol, this);
+ return true;
+ bad_close:
+ sio_close(hdl);
+ return false;
+}
+
+void SndioAudioOutputStream::Close() {
+ if (state == kClosed)
+ return;
+ if (state == kRunning)
+ Stop();
+ state = kClosed;
+ delete [] buffer;
+ sio_close(hdl);
+ manager->ReleaseOutputStream(this); // Calls the destructor
+}
+
+void SndioAudioOutputStream::Start(AudioSourceCallback* callback) {
+ state = kRunning;
+ hw_delay = 0;
+ source = callback;
+ sio_start(hdl);
+ if (pthread_create(&thread, NULL, sndio_threadstart, this) != 0) {
+ LOG(ERROR) << "Failed to create real-time thread.";
+ sio_stop(hdl);
+ state = kStopped;
+ }
+}
+
+void SndioAudioOutputStream::Stop() {
+ if (state == kStopped)
+ return;
+ state = kStopWait;
+ pthread_join(thread, NULL);
+ sio_stop(hdl);
+ state = kStopped;
+}
+
+void SndioAudioOutputStream::SetVolume(double v) {
+ pthread_mutex_lock(&mutex);
+ vol = v * SIO_MAXVOL;
+ volpending = 1;
+ pthread_mutex_unlock(&mutex);
+}
+
+void SndioAudioOutputStream::GetVolume(double* v) {
+ pthread_mutex_lock(&mutex);
+ *v = vol * (1. / SIO_MAXVOL);
+ pthread_mutex_unlock(&mutex);
+}
+
+void SndioAudioOutputStream::RealTimeThread(void) {
+ int avail, count;
+
+ while (state == kRunning) {
+ // Update volume if needed
+ pthread_mutex_lock(&mutex);
+ if (volpending) {
+ volpending = 0;
+ sio_setvol(hdl, vol);
+ }
+ pthread_mutex_unlock(&mutex);
+
+ // Get data to play
+ const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay, params.sample_rate() * 1000);
+ count = source->OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get());
+ audio_bus->ToInterleaved(count, params.bits_per_sample() / 8, buffer);
+ if (count == 0) {
+ // We have to submit something to the device
+ count = audio_bus->frames();
+ memset(buffer, 0, count * params.GetBytesPerFrame());
+ LOG(WARNING) << "No data to play, running empty cycle.";
+ }
+
+ // Submit data to the device
+ avail = count * params.GetBytesPerFrame();
+ count = sio_write(hdl, buffer, avail);
+ if (count == 0) {
+ LOG(WARNING) << "Audio device disconnected.";
+ break;
+ }
+
+ // Update hardware pointer
+ hw_delay += count;
+ }
+}
+
+} // namespace media
diff --git a/www/iridium/files/sndio_output.h b/www/iridium/files/sndio_output.h
new file mode 100644
index 000000000000..4bc644d9a3ff
--- /dev/null
+++ b/www/iridium/files/sndio_output.h
@@ -0,0 +1,92 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
+#define MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
+
+#include <pthread.h>
+#include <sndio.h>
+
+#include "base/time/tick_clock.h"
+#include "base/time/time.h"
+#include "media/audio/audio_io.h"
+
+
+namespace media {
+
+class AudioParameters;
+class AudioManagerBase;
+
+// call-backs invoked from C libraries, thus requiring C linkage
+extern "C" {
+ // Invoked (on the real-time thread) at each sound card clock tick
+ void sndio_onmove(void *arg, int delta);
+ // Invoked (on the real-time thread) whenever the volume changes
+ void sndio_onvol(void *arg, unsigned int vol);
+ // Real-time thread entry point
+ void *sndio_threadstart(void *arg);
+}
+
+// Implementation of AudioOutputStream using sndio(7)
+class SndioAudioOutputStream : public AudioOutputStream {
+ public:
+ // The manager is creating this object
+ SndioAudioOutputStream(const AudioParameters& params,
+ AudioManagerBase* manager);
+ virtual ~SndioAudioOutputStream();
+
+ // Implementation of AudioOutputStream.
+ virtual bool Open() override;
+ virtual void Close() override;
+ virtual void Start(AudioSourceCallback* callback) override;
+ virtual void Stop() override;
+ virtual void SetVolume(double volume) override;
+ virtual void GetVolume(double* volume) override;
+
+ // C-linkage call-backs are friends to access private data
+ friend void sndio_onmove(void *arg, int delta);
+ friend void sndio_onvol(void *arg, unsigned int vol);
+ friend void *sndio_threadstart(void *arg);
+
+ private:
+ enum StreamState {
+ kClosed, // Not opened yet
+ kStopped, // Device opened, but not started yet
+ kRunning, // Started, device playing
+ kStopWait // Stopping, waiting for the real-time thread to exit
+ };
+ // Continuously moves data from the audio bus to the device
+ void RealTimeThread(void);
+ // Our creator, the audio manager needs to be notified when we close.
+ AudioManagerBase* manager;
+ // Parameters of the source
+ AudioParameters params;
+ // Source stores data here
+ std::unique_ptr<AudioBus> audio_bus;
+ int bytes_per_frame;
+ // Call-back that produces data to play
+ AudioSourceCallback* source;
+ // Handle of the audio device
+ struct sio_hdl* hdl;
+ // Current state of the stream
+ enum StreamState state;
+ // High priority thread running RealTimeThread()
+ pthread_t thread;
+ // Protects vol, volpending and hw_delay
+ pthread_mutex_t mutex;
+ // Current volume in the 0..SIO_MAXVOL range
+ int vol;
+ // Set to 1 if volumes must be refreshed in the realtime thread
+ int volpending;
+ // Number of bytes buffered in the hardware
+ int hw_delay;
+ // Temporary buffer where data is stored sndio-compatible format
+ char* buffer;
+
+ DISALLOW_COPY_AND_ASSIGN(SndioAudioOutputStream);
+};
+
+} // namespace media
+
+#endif // MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_