summaryrefslogtreecommitdiff
path: root/gr-audio/lib
diff options
context:
space:
mode:
authorMarcus Müller <mmueller@gnuradio.org>2019-08-07 21:45:12 +0200
committerMarcus Müller <marcus@hostalia.de>2019-08-09 23:04:28 +0200
commitf7bbf2c1d8d780294f3e016aff239ca35eb6516e (patch)
treee09ab6112e02b2215b2d59ac24d3d6ea2edac745 /gr-audio/lib
parent78431dc6941e3acc67c858277dfe4a0ed583643c (diff)
Tree: clang-format without the include sorting
Diffstat (limited to 'gr-audio/lib')
-rw-r--r--gr-audio/lib/alsa/alsa_impl.cc271
-rw-r--r--gr-audio/lib/alsa/alsa_impl.h20
-rw-r--r--gr-audio/lib/alsa/alsa_sink.cc797
-rw-r--r--gr-audio/lib/alsa/alsa_sink.h144
-rw-r--r--gr-audio/lib/alsa/alsa_source.cc792
-rw-r--r--gr-audio/lib/alsa/alsa_source.h150
-rw-r--r--gr-audio/lib/audio_registry.cc216
-rw-r--r--gr-audio/lib/audio_registry.h113
-rw-r--r--gr-audio/lib/jack/jack_sink.cc320
-rw-r--r--gr-audio/lib/jack/jack_sink.h84
-rw-r--r--gr-audio/lib/jack/jack_source.cc321
-rw-r--r--gr-audio/lib/jack/jack_source.h84
-rw-r--r--gr-audio/lib/oss/oss_sink.cc191
-rw-r--r--gr-audio/lib/oss/oss_sink.h58
-rw-r--r--gr-audio/lib/oss/oss_source.cc188
-rw-r--r--gr-audio/lib/oss/oss_source.h60
-rw-r--r--gr-audio/lib/osx/circular_buffer.h531
-rw-r--r--gr-audio/lib/osx/osx_common.h46
-rw-r--r--gr-audio/lib/osx/osx_impl.cc412
-rw-r--r--gr-audio/lib/osx/osx_sink.cc1310
-rw-r--r--gr-audio/lib/osx/osx_sink.h142
-rw-r--r--gr-audio/lib/osx/osx_source.cc2002
-rw-r--r--gr-audio/lib/osx/osx_source.h199
-rw-r--r--gr-audio/lib/portaudio/portaudio_impl.cc105
-rw-r--r--gr-audio/lib/portaudio/portaudio_impl.h8
-rw-r--r--gr-audio/lib/portaudio/portaudio_sink.cc485
-rw-r--r--gr-audio/lib/portaudio/portaudio_sink.h78
-rw-r--r--gr-audio/lib/portaudio/portaudio_source.cc513
-rw-r--r--gr-audio/lib/portaudio/portaudio_source.h76
-rw-r--r--gr-audio/lib/windows/windows_sink.cc552
-rw-r--r--gr-audio/lib/windows/windows_sink.h74
-rw-r--r--gr-audio/lib/windows/windows_source.cc542
-rw-r--r--gr-audio/lib/windows/windows_source.h78
33 files changed, 5327 insertions, 5635 deletions
diff --git a/gr-audio/lib/alsa/alsa_impl.cc b/gr-audio/lib/alsa/alsa_impl.cc
index 7080ae8f7a..839dca5fc6 100644
--- a/gr-audio/lib/alsa/alsa_impl.cc
+++ b/gr-audio/lib/alsa/alsa_impl.cc
@@ -27,149 +27,156 @@
#include "alsa_impl.h"
#include <algorithm>
-static snd_pcm_access_t access_types[] = {
- SND_PCM_ACCESS_MMAP_INTERLEAVED,
- SND_PCM_ACCESS_MMAP_NONINTERLEAVED,
- SND_PCM_ACCESS_MMAP_COMPLEX,
- SND_PCM_ACCESS_RW_INTERLEAVED,
- SND_PCM_ACCESS_RW_NONINTERLEAVED
-};
+static snd_pcm_access_t access_types[] = { SND_PCM_ACCESS_MMAP_INTERLEAVED,
+ SND_PCM_ACCESS_MMAP_NONINTERLEAVED,
+ SND_PCM_ACCESS_MMAP_COMPLEX,
+ SND_PCM_ACCESS_RW_INTERLEAVED,
+ SND_PCM_ACCESS_RW_NONINTERLEAVED };
static snd_pcm_format_t format_types[] = {
- // SND_PCM_FORMAT_UNKNOWN,
- SND_PCM_FORMAT_S8,
- SND_PCM_FORMAT_U8,
- SND_PCM_FORMAT_S16_LE,
- SND_PCM_FORMAT_S16_BE,
- SND_PCM_FORMAT_U16_LE,
- SND_PCM_FORMAT_U16_BE,
- SND_PCM_FORMAT_S24_LE,
- SND_PCM_FORMAT_S24_BE,
- SND_PCM_FORMAT_U24_LE,
- SND_PCM_FORMAT_U24_BE,
- SND_PCM_FORMAT_S32_LE,
- SND_PCM_FORMAT_S32_BE,
- SND_PCM_FORMAT_U32_LE,
- SND_PCM_FORMAT_U32_BE,
- SND_PCM_FORMAT_FLOAT_LE,
- SND_PCM_FORMAT_FLOAT_BE,
- SND_PCM_FORMAT_FLOAT64_LE,
- SND_PCM_FORMAT_FLOAT64_BE,
- SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
- SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
- SND_PCM_FORMAT_MU_LAW,
- SND_PCM_FORMAT_A_LAW,
- SND_PCM_FORMAT_IMA_ADPCM,
- SND_PCM_FORMAT_MPEG,
- SND_PCM_FORMAT_GSM,
- SND_PCM_FORMAT_SPECIAL,
- SND_PCM_FORMAT_S24_3LE,
- SND_PCM_FORMAT_S24_3BE,
- SND_PCM_FORMAT_U24_3LE,
- SND_PCM_FORMAT_U24_3BE,
- SND_PCM_FORMAT_S20_3LE,
- SND_PCM_FORMAT_S20_3BE,
- SND_PCM_FORMAT_U20_3LE,
- SND_PCM_FORMAT_U20_3BE,
- SND_PCM_FORMAT_S18_3LE,
- SND_PCM_FORMAT_S18_3BE,
- SND_PCM_FORMAT_U18_3LE,
- SND_PCM_FORMAT_U18_3BE
+ // SND_PCM_FORMAT_UNKNOWN,
+ SND_PCM_FORMAT_S8,
+ SND_PCM_FORMAT_U8,
+ SND_PCM_FORMAT_S16_LE,
+ SND_PCM_FORMAT_S16_BE,
+ SND_PCM_FORMAT_U16_LE,
+ SND_PCM_FORMAT_U16_BE,
+ SND_PCM_FORMAT_S24_LE,
+ SND_PCM_FORMAT_S24_BE,
+ SND_PCM_FORMAT_U24_LE,
+ SND_PCM_FORMAT_U24_BE,
+ SND_PCM_FORMAT_S32_LE,
+ SND_PCM_FORMAT_S32_BE,
+ SND_PCM_FORMAT_U32_LE,
+ SND_PCM_FORMAT_U32_BE,
+ SND_PCM_FORMAT_FLOAT_LE,
+ SND_PCM_FORMAT_FLOAT_BE,
+ SND_PCM_FORMAT_FLOAT64_LE,
+ SND_PCM_FORMAT_FLOAT64_BE,
+ SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
+ SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
+ SND_PCM_FORMAT_MU_LAW,
+ SND_PCM_FORMAT_A_LAW,
+ SND_PCM_FORMAT_IMA_ADPCM,
+ SND_PCM_FORMAT_MPEG,
+ SND_PCM_FORMAT_GSM,
+ SND_PCM_FORMAT_SPECIAL,
+ SND_PCM_FORMAT_S24_3LE,
+ SND_PCM_FORMAT_S24_3BE,
+ SND_PCM_FORMAT_U24_3LE,
+ SND_PCM_FORMAT_U24_3BE,
+ SND_PCM_FORMAT_S20_3LE,
+ SND_PCM_FORMAT_S20_3BE,
+ SND_PCM_FORMAT_U20_3LE,
+ SND_PCM_FORMAT_U20_3BE,
+ SND_PCM_FORMAT_S18_3LE,
+ SND_PCM_FORMAT_S18_3BE,
+ SND_PCM_FORMAT_U18_3LE,
+ SND_PCM_FORMAT_U18_3BE
};
-static unsigned int test_rates[] = {
- 8000, 16000, 22050, 32000, 44100, 48000, 96000, 192000
-};
+static unsigned int test_rates[] = { 8000, 16000, 22050, 32000,
+ 44100, 48000, 96000, 192000 };
-#define NELEMS(x) (sizeof(x)/sizeof(x[0]))
+#define NELEMS(x) (sizeof(x) / sizeof(x[0]))
-void
-gri_alsa_dump_hw_params (snd_pcm_t *pcm, snd_pcm_hw_params_t *hwparams, FILE *fp)
+void gri_alsa_dump_hw_params(snd_pcm_t* pcm, snd_pcm_hw_params_t* hwparams, FILE* fp)
{
- fprintf (fp, "PCM name: %s\n", snd_pcm_name (pcm));
-
- fprintf (fp, "Access types:\n");
- for (unsigned i = 0; i < NELEMS (access_types); i++){
- snd_pcm_access_t at = access_types[i];
- fprintf (fp, " %-20s %s\n",
- snd_pcm_access_name (at),
- snd_pcm_hw_params_test_access (pcm, hwparams, at) == 0 ? "YES" : "NO");
- }
-
- fprintf (fp, "Formats:\n");
- for (unsigned i = 0; i < NELEMS (format_types); i++){
- snd_pcm_format_t ft = format_types[i];
- if (0)
- fprintf (fp, " %-20s %s\n",
- snd_pcm_format_name (ft),
- snd_pcm_hw_params_test_format (pcm, hwparams, ft) == 0 ? "YES" : "NO");
- else {
- if (snd_pcm_hw_params_test_format (pcm, hwparams, ft) == 0)
- fprintf (fp, " %-20s YES\n", snd_pcm_format_name (ft));
+ fprintf(fp, "PCM name: %s\n", snd_pcm_name(pcm));
+
+ fprintf(fp, "Access types:\n");
+ for (unsigned i = 0; i < NELEMS(access_types); i++) {
+ snd_pcm_access_t at = access_types[i];
+ fprintf(fp,
+ " %-20s %s\n",
+ snd_pcm_access_name(at),
+ snd_pcm_hw_params_test_access(pcm, hwparams, at) == 0 ? "YES" : "NO");
}
- }
-
- fprintf (fp, "Number of channels\n");
- unsigned int min_chan, max_chan;
- snd_pcm_hw_params_get_channels_min (hwparams, &min_chan);
- snd_pcm_hw_params_get_channels_max (hwparams, &max_chan);
- fprintf (fp, " min channels: %d\n", min_chan);
- fprintf (fp, " max channels: %d\n", max_chan);
- unsigned int chan;
- max_chan = std::min (max_chan, 16U); // truncate display...
- for (chan = min_chan; chan <= max_chan; chan++){
- fprintf (fp, " %d channels\t%s\n", chan,
- snd_pcm_hw_params_test_channels (pcm, hwparams, chan) == 0 ? "YES" : "NO");
- }
-
- fprintf (fp, "Sample Rates:\n");
- unsigned int min_rate, max_rate;
- int min_dir, max_dir;
-
- snd_pcm_hw_params_get_rate_min (hwparams, &min_rate, &min_dir);
- snd_pcm_hw_params_get_rate_max (hwparams, &max_rate, &max_dir);
- fprintf (fp, " min rate: %7d (dir = %d)\n", min_rate, min_dir);
- fprintf (fp, " max rate: %7d (dir = %d)\n", max_rate, max_dir);
- for (unsigned i = 0; i < NELEMS (test_rates); i++){
- unsigned int rate = test_rates[i];
- fprintf (fp, " %6u %s\n", rate,
- snd_pcm_hw_params_test_rate (pcm, hwparams, rate, 0) == 0 ? "YES" : "NO");
- }
-
- fflush (fp);
+
+ fprintf(fp, "Formats:\n");
+ for (unsigned i = 0; i < NELEMS(format_types); i++) {
+ snd_pcm_format_t ft = format_types[i];
+ if (0)
+ fprintf(fp,
+ " %-20s %s\n",
+ snd_pcm_format_name(ft),
+ snd_pcm_hw_params_test_format(pcm, hwparams, ft) == 0 ? "YES" : "NO");
+ else {
+ if (snd_pcm_hw_params_test_format(pcm, hwparams, ft) == 0)
+ fprintf(fp, " %-20s YES\n", snd_pcm_format_name(ft));
+ }
+ }
+
+ fprintf(fp, "Number of channels\n");
+ unsigned int min_chan, max_chan;
+ snd_pcm_hw_params_get_channels_min(hwparams, &min_chan);
+ snd_pcm_hw_params_get_channels_max(hwparams, &max_chan);
+ fprintf(fp, " min channels: %d\n", min_chan);
+ fprintf(fp, " max channels: %d\n", max_chan);
+ unsigned int chan;
+ max_chan = std::min(max_chan, 16U); // truncate display...
+ for (chan = min_chan; chan <= max_chan; chan++) {
+ fprintf(fp,
+ " %d channels\t%s\n",
+ chan,
+ snd_pcm_hw_params_test_channels(pcm, hwparams, chan) == 0 ? "YES" : "NO");
+ }
+
+ fprintf(fp, "Sample Rates:\n");
+ unsigned int min_rate, max_rate;
+ int min_dir, max_dir;
+
+ snd_pcm_hw_params_get_rate_min(hwparams, &min_rate, &min_dir);
+ snd_pcm_hw_params_get_rate_max(hwparams, &max_rate, &max_dir);
+ fprintf(fp, " min rate: %7d (dir = %d)\n", min_rate, min_dir);
+ fprintf(fp, " max rate: %7d (dir = %d)\n", max_rate, max_dir);
+ for (unsigned i = 0; i < NELEMS(test_rates); i++) {
+ unsigned int rate = test_rates[i];
+ fprintf(fp,
+ " %6u %s\n",
+ rate,
+ snd_pcm_hw_params_test_rate(pcm, hwparams, rate, 0) == 0 ? "YES" : "NO");
+ }
+
+ fflush(fp);
}
-bool
-gri_alsa_pick_acceptable_format (snd_pcm_t *pcm,
- snd_pcm_hw_params_t *hwparams,
- snd_pcm_format_t acceptable_formats[],
- unsigned nacceptable_formats,
- snd_pcm_format_t *selected_format,
- const char *error_msg_tag,
- bool verbose)
+bool gri_alsa_pick_acceptable_format(snd_pcm_t* pcm,
+ snd_pcm_hw_params_t* hwparams,
+ snd_pcm_format_t acceptable_formats[],
+ unsigned nacceptable_formats,
+ snd_pcm_format_t* selected_format,
+ const char* error_msg_tag,
+ bool verbose)
{
- int err;
-
- // pick a format that we like...
- for (unsigned i = 0; i < nacceptable_formats; i++){
- if (snd_pcm_hw_params_test_format (pcm, hwparams,
- acceptable_formats[i]) == 0){
- err = snd_pcm_hw_params_set_format (pcm, hwparams, acceptable_formats[i]);
- if (err < 0){
- fprintf (stderr, "%s[%s]: failed to set format: %s\n",
- error_msg_tag, snd_pcm_name (pcm), snd_strerror (err));
- return false;
- }
- if (verbose)
- fprintf (stdout, "%s[%s]: using %s\n",
- error_msg_tag, snd_pcm_name (pcm),
- snd_pcm_format_name (acceptable_formats[i]));
- *selected_format = acceptable_formats[i];
- return true;
+ int err;
+
+ // pick a format that we like...
+ for (unsigned i = 0; i < nacceptable_formats; i++) {
+ if (snd_pcm_hw_params_test_format(pcm, hwparams, acceptable_formats[i]) == 0) {
+ err = snd_pcm_hw_params_set_format(pcm, hwparams, acceptable_formats[i]);
+ if (err < 0) {
+ fprintf(stderr,
+ "%s[%s]: failed to set format: %s\n",
+ error_msg_tag,
+ snd_pcm_name(pcm),
+ snd_strerror(err));
+ return false;
+ }
+ if (verbose)
+ fprintf(stdout,
+ "%s[%s]: using %s\n",
+ error_msg_tag,
+ snd_pcm_name(pcm),
+ snd_pcm_format_name(acceptable_formats[i]));
+ *selected_format = acceptable_formats[i];
+ return true;
+ }
}
- }
- fprintf (stderr, "%s[%s]: failed to find acceptable format",
- error_msg_tag, snd_pcm_name (pcm));
- return false;
+ fprintf(stderr,
+ "%s[%s]: failed to find acceptable format",
+ error_msg_tag,
+ snd_pcm_name(pcm));
+ return false;
}
diff --git a/gr-audio/lib/alsa/alsa_impl.h b/gr-audio/lib/alsa/alsa_impl.h
index 1340ce403a..a85ef166f7 100644
--- a/gr-audio/lib/alsa/alsa_impl.h
+++ b/gr-audio/lib/alsa/alsa_impl.h
@@ -26,19 +26,15 @@
#include <stdio.h>
#include <alsa/asoundlib.h>
-void
-gri_alsa_dump_hw_params (snd_pcm_t *pcm,
- snd_pcm_hw_params_t *hwparams,
- FILE *fp);
+void gri_alsa_dump_hw_params(snd_pcm_t* pcm, snd_pcm_hw_params_t* hwparams, FILE* fp);
-bool
-gri_alsa_pick_acceptable_format (snd_pcm_t *pcm,
- snd_pcm_hw_params_t *hwparams,
- snd_pcm_format_t acceptable_formats[],
- unsigned nacceptable_formats,
- snd_pcm_format_t *selected_format,
- const char *error_msg_tag,
- bool verbose);
+bool gri_alsa_pick_acceptable_format(snd_pcm_t* pcm,
+ snd_pcm_hw_params_t* hwparams,
+ snd_pcm_format_t acceptable_formats[],
+ unsigned nacceptable_formats,
+ snd_pcm_format_t* selected_format,
+ const char* error_msg_tag,
+ bool verbose);
#endif /* INCLUDED_GRI_ALSA_H */
diff --git a/gr-audio/lib/alsa/alsa_sink.cc b/gr-audio/lib/alsa/alsa_sink.cc
index 924e4f88a2..5df5a83dc6 100644
--- a/gr-audio/lib/alsa/alsa_sink.cc
+++ b/gr-audio/lib/alsa/alsa_sink.cc
@@ -34,515 +34,504 @@
#include <stdexcept>
namespace gr {
- namespace audio {
-
- sink::sptr
- alsa_sink_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block)
- {
- return sink::sptr
- (new alsa_sink(sampling_rate, device_name, ok_to_block));
- }
-
- static bool CHATTY_DEBUG = true;
-
- static snd_pcm_format_t acceptable_formats[] = {
- // these are in our preferred order...
- SND_PCM_FORMAT_S32,
- SND_PCM_FORMAT_S16
- };
-
-#define NELEMS(x) (sizeof(x)/sizeof(x[0]))
-
- static std::string
- default_device_name()
- {
- return prefs::singleton()->get_string("audio_alsa", "default_output_device", "default");
- }
-
- static double
- default_period_time()
- {
- return std::max(0.001,
- prefs::singleton()->get_double("audio_alsa", "period_time", 0.010));
- }
-
- static int
- default_nperiods()
- {
- return std::max(2L,
- prefs::singleton()->get_long("audio_alsa", "nperiods", 4));
- }
-
- // ----------------------------------------------------------------
-
- alsa_sink::alsa_sink(int sampling_rate,
- const std::string device_name,
- bool ok_to_block)
- : sync_block("audio_alsa_sink",
- io_signature::make(0, 0, 0),
- io_signature::make(0, 0, 0)),
- d_sampling_rate(sampling_rate),
- d_device_name(device_name.empty() ? default_device_name() : device_name),
- d_pcm_handle(0),
- d_hw_params((snd_pcm_hw_params_t*)(new char[snd_pcm_hw_params_sizeof()])),
- d_sw_params((snd_pcm_sw_params_t*)(new char[snd_pcm_sw_params_sizeof()])),
- d_nperiods(default_nperiods()),
- d_period_time_us((unsigned int)(default_period_time() * 1e6)),
- d_period_size(0),
- d_buffer_size_bytes(0), d_buffer(0),
- d_worker(0), d_special_case_mono_to_stereo(false),
- d_nunderuns(0), d_nsuspends(0), d_ok_to_block(ok_to_block)
- {
- CHATTY_DEBUG = prefs::singleton()->get_bool("audio_alsa", "verbose", false);
-
- int error=-1;
- int dir;
-
- // open the device for playback
- int attempts = 10;
- while((error!=0)&&(attempts-->0)){
- error = snd_pcm_open(&d_pcm_handle, d_device_name.c_str(),
- SND_PCM_STREAM_PLAYBACK, 0);
- if(error<0){
- boost::this_thread::sleep( boost::posix_time::milliseconds(10));
- }
+namespace audio {
+
+sink::sptr
+alsa_sink_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block)
+{
+ return sink::sptr(new alsa_sink(sampling_rate, device_name, ok_to_block));
+}
+
+static bool CHATTY_DEBUG = true;
+
+static snd_pcm_format_t acceptable_formats[] = {
+ // these are in our preferred order...
+ SND_PCM_FORMAT_S32,
+ SND_PCM_FORMAT_S16
+};
+
+#define NELEMS(x) (sizeof(x) / sizeof(x[0]))
+
+static std::string default_device_name()
+{
+ return prefs::singleton()->get_string(
+ "audio_alsa", "default_output_device", "default");
+}
+
+static double default_period_time()
+{
+ return std::max(0.001,
+ prefs::singleton()->get_double("audio_alsa", "period_time", 0.010));
+}
+
+static int default_nperiods()
+{
+ return std::max(2L, prefs::singleton()->get_long("audio_alsa", "nperiods", 4));
+}
+
+// ----------------------------------------------------------------
+
+alsa_sink::alsa_sink(int sampling_rate, const std::string device_name, bool ok_to_block)
+ : sync_block(
+ "audio_alsa_sink", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)),
+ d_sampling_rate(sampling_rate),
+ d_device_name(device_name.empty() ? default_device_name() : device_name),
+ d_pcm_handle(0),
+ d_hw_params((snd_pcm_hw_params_t*)(new char[snd_pcm_hw_params_sizeof()])),
+ d_sw_params((snd_pcm_sw_params_t*)(new char[snd_pcm_sw_params_sizeof()])),
+ d_nperiods(default_nperiods()),
+ d_period_time_us((unsigned int)(default_period_time() * 1e6)),
+ d_period_size(0),
+ d_buffer_size_bytes(0),
+ d_buffer(0),
+ d_worker(0),
+ d_special_case_mono_to_stereo(false),
+ d_nunderuns(0),
+ d_nsuspends(0),
+ d_ok_to_block(ok_to_block)
+{
+ CHATTY_DEBUG = prefs::singleton()->get_bool("audio_alsa", "verbose", false);
+
+ int error = -1;
+ int dir;
+
+ // open the device for playback
+ int attempts = 10;
+ while ((error != 0) && (attempts-- > 0)) {
+ error = snd_pcm_open(
+ &d_pcm_handle, d_device_name.c_str(), SND_PCM_STREAM_PLAYBACK, 0);
+ if (error < 0) {
+ boost::this_thread::sleep(boost::posix_time::milliseconds(10));
}
- if(ok_to_block == false)
+ }
+ if (ok_to_block == false)
snd_pcm_nonblock(d_pcm_handle, !ok_to_block);
- if(error < 0){
- GR_LOG_ERROR(d_logger, boost::format("[%1%]: %2%") \
- % (d_device_name) % (snd_strerror(error)));
+ if (error < 0) {
+ GR_LOG_ERROR(d_logger,
+ boost::format("[%1%]: %2%") % (d_device_name) %
+ (snd_strerror(error)));
throw std::runtime_error("audio_alsa_sink");
- }
+ }
- // Fill params with a full configuration space for a PCM.
- error = snd_pcm_hw_params_any(d_pcm_handle, d_hw_params);
- if(error < 0)
+ // Fill params with a full configuration space for a PCM.
+ error = snd_pcm_hw_params_any(d_pcm_handle, d_hw_params);
+ if (error < 0)
bail("broken configuration for playback", error);
- if(CHATTY_DEBUG)
+ if (CHATTY_DEBUG)
gri_alsa_dump_hw_params(d_pcm_handle, d_hw_params, stdout);
- // now that we know how many channels the h/w can handle, set input signature
- unsigned int umin_chan, umax_chan;
- snd_pcm_hw_params_get_channels_min(d_hw_params, &umin_chan);
- snd_pcm_hw_params_get_channels_max(d_hw_params, &umax_chan);
- int min_chan = std::min(umin_chan, 1000U);
- int max_chan = std::min(umax_chan, 1000U);
+ // now that we know how many channels the h/w can handle, set input signature
+ unsigned int umin_chan, umax_chan;
+ snd_pcm_hw_params_get_channels_min(d_hw_params, &umin_chan);
+ snd_pcm_hw_params_get_channels_max(d_hw_params, &umax_chan);
+ int min_chan = std::min(umin_chan, 1000U);
+ int max_chan = std::min(umax_chan, 1000U);
- // As a special case, if the hw's min_chan is two, we'll accept
- // a single input and handle the duplication ourselves.
- if(min_chan == 2) {
+ // As a special case, if the hw's min_chan is two, we'll accept
+ // a single input and handle the duplication ourselves.
+ if (min_chan == 2) {
min_chan = 1;
d_special_case_mono_to_stereo = true;
- }
- set_input_signature(io_signature::make(min_chan, max_chan,
- sizeof(float)));
-
- // fill in portions of the d_hw_params that we know now...
-
- // Specify the access methods we implement
- // For now, we only handle RW_INTERLEAVED...
- snd_pcm_access_mask_t *access_mask;
- snd_pcm_access_mask_t **access_mask_ptr = &access_mask; // FIXME: workaround for compiler warning
- snd_pcm_access_mask_alloca(access_mask_ptr);
- snd_pcm_access_mask_none(access_mask);
- snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
- // snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED);
-
- if((error = snd_pcm_hw_params_set_access_mask(d_pcm_handle,
- d_hw_params, access_mask)) < 0)
+ }
+ set_input_signature(io_signature::make(min_chan, max_chan, sizeof(float)));
+
+ // fill in portions of the d_hw_params that we know now...
+
+ // Specify the access methods we implement
+ // For now, we only handle RW_INTERLEAVED...
+ snd_pcm_access_mask_t* access_mask;
+ snd_pcm_access_mask_t** access_mask_ptr =
+ &access_mask; // FIXME: workaround for compiler warning
+ snd_pcm_access_mask_alloca(access_mask_ptr);
+ snd_pcm_access_mask_none(access_mask);
+ snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
+ // snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED);
+
+ if ((error = snd_pcm_hw_params_set_access_mask(
+ d_pcm_handle, d_hw_params, access_mask)) < 0)
bail("failed to set access mask", error);
- // set sample format
- if(!gri_alsa_pick_acceptable_format(d_pcm_handle, d_hw_params,
- acceptable_formats,
- NELEMS(acceptable_formats),
- &d_format,
- "audio_alsa_sink",
- CHATTY_DEBUG))
+ // set sample format
+ if (!gri_alsa_pick_acceptable_format(d_pcm_handle,
+ d_hw_params,
+ acceptable_formats,
+ NELEMS(acceptable_formats),
+ &d_format,
+ "audio_alsa_sink",
+ CHATTY_DEBUG))
throw std::runtime_error("audio_alsa_sink");
- // sampling rate
- unsigned int orig_sampling_rate = d_sampling_rate;
- if((error = snd_pcm_hw_params_set_rate_near(d_pcm_handle, d_hw_params,
- &d_sampling_rate, 0)) < 0)
+ // sampling rate
+ unsigned int orig_sampling_rate = d_sampling_rate;
+ if ((error = snd_pcm_hw_params_set_rate_near(
+ d_pcm_handle, d_hw_params, &d_sampling_rate, 0)) < 0)
bail("failed to set rate near", error);
- if(orig_sampling_rate != d_sampling_rate) {
- GR_LOG_INFO(d_logger, boost::format("[%1%]: unable to support sampling rate %2%\n\tCard requested %3% instead.") \
- % snd_pcm_name(d_pcm_handle) % orig_sampling_rate \
- % d_sampling_rate);
- }
-
- /*
- * ALSA transfers data in units of "periods".
- * We indirectly determine the underlying buffersize by specifying
- * the number of periods we want (typically 4) and the length of each
- * period in units of time (typically 1ms).
- */
- unsigned int min_nperiods, max_nperiods;
- snd_pcm_hw_params_get_periods_min(d_hw_params, &min_nperiods, &dir);
- snd_pcm_hw_params_get_periods_max(d_hw_params, &max_nperiods, &dir);
-
- unsigned int orig_nperiods = d_nperiods;
- d_nperiods = std::min (std::max (min_nperiods, d_nperiods), max_nperiods);
-
- // adjust period time so that total buffering remains more-or-less constant
- d_period_time_us = (d_period_time_us * orig_nperiods) / d_nperiods;
-
- error = snd_pcm_hw_params_set_periods(d_pcm_handle, d_hw_params,
- d_nperiods, 0);
- if(error < 0)
+ if (orig_sampling_rate != d_sampling_rate) {
+ GR_LOG_INFO(d_logger,
+ boost::format("[%1%]: unable to support sampling rate %2%\n\tCard "
+ "requested %3% instead.") %
+ snd_pcm_name(d_pcm_handle) % orig_sampling_rate %
+ d_sampling_rate);
+ }
+
+ /*
+ * ALSA transfers data in units of "periods".
+ * We indirectly determine the underlying buffersize by specifying
+ * the number of periods we want (typically 4) and the length of each
+ * period in units of time (typically 1ms).
+ */
+ unsigned int min_nperiods, max_nperiods;
+ snd_pcm_hw_params_get_periods_min(d_hw_params, &min_nperiods, &dir);
+ snd_pcm_hw_params_get_periods_max(d_hw_params, &max_nperiods, &dir);
+
+ unsigned int orig_nperiods = d_nperiods;
+ d_nperiods = std::min(std::max(min_nperiods, d_nperiods), max_nperiods);
+
+ // adjust period time so that total buffering remains more-or-less constant
+ d_period_time_us = (d_period_time_us * orig_nperiods) / d_nperiods;
+
+ error = snd_pcm_hw_params_set_periods(d_pcm_handle, d_hw_params, d_nperiods, 0);
+ if (error < 0)
bail("set_periods failed", error);
- dir = 0;
- error = snd_pcm_hw_params_set_period_time_near(d_pcm_handle, d_hw_params,
- &d_period_time_us, &dir);
- if(error < 0)
+ dir = 0;
+ error = snd_pcm_hw_params_set_period_time_near(
+ d_pcm_handle, d_hw_params, &d_period_time_us, &dir);
+ if (error < 0)
bail("set_period_time_near failed", error);
- dir = 0;
- error = snd_pcm_hw_params_get_period_size(d_hw_params,
- &d_period_size, &dir);
- if(error < 0)
+ dir = 0;
+ error = snd_pcm_hw_params_get_period_size(d_hw_params, &d_period_size, &dir);
+ if (error < 0)
bail("get_period_size failed", error);
- set_output_multiple(d_period_size);
- }
-
- bool
- alsa_sink::check_topology(int ninputs, int noutputs)
- {
- // ninputs is how many channels the user has connected.
- // Now we can finish up setting up the hw params...
-
- int nchan = ninputs;
- int err;
-
- // Check the state of the stream
- // Ensure that the pcm is in a state where we can still mess with the hw_params
- snd_pcm_state_t state;
- state = snd_pcm_state(d_pcm_handle);
- if(state == SND_PCM_STATE_RUNNING)
- return true; // If stream is running, don't change any parameters
- else if(state == SND_PCM_STATE_XRUN)
- snd_pcm_prepare(d_pcm_handle); // Prepare stream on underrun, and we can set parameters;
-
- bool special_case = nchan == 1 && d_special_case_mono_to_stereo;
- if(special_case)
+ set_output_multiple(d_period_size);
+}
+
+bool alsa_sink::check_topology(int ninputs, int noutputs)
+{
+ // ninputs is how many channels the user has connected.
+ // Now we can finish up setting up the hw params...
+
+ int nchan = ninputs;
+ int err;
+
+ // Check the state of the stream
+ // Ensure that the pcm is in a state where we can still mess with the hw_params
+ snd_pcm_state_t state;
+ state = snd_pcm_state(d_pcm_handle);
+ if (state == SND_PCM_STATE_RUNNING)
+ return true; // If stream is running, don't change any parameters
+ else if (state == SND_PCM_STATE_XRUN)
+ snd_pcm_prepare(
+ d_pcm_handle); // Prepare stream on underrun, and we can set parameters;
+
+ bool special_case = nchan == 1 && d_special_case_mono_to_stereo;
+ if (special_case)
nchan = 2;
- err = snd_pcm_hw_params_set_channels(d_pcm_handle, d_hw_params, nchan);
+ err = snd_pcm_hw_params_set_channels(d_pcm_handle, d_hw_params, nchan);
- if(err < 0) {
+ if (err < 0) {
output_error_msg("set_channels failed", err);
return false;
- }
+ }
- // set the parameters into the driver...
- err = snd_pcm_hw_params(d_pcm_handle, d_hw_params);
- if(err < 0) {
+ // set the parameters into the driver...
+ err = snd_pcm_hw_params(d_pcm_handle, d_hw_params);
+ if (err < 0) {
output_error_msg("snd_pcm_hw_params failed", err);
return false;
- }
+ }
- // get current s/w params
- err = snd_pcm_sw_params_current(d_pcm_handle, d_sw_params);
- if(err < 0)
+ // get current s/w params
+ err = snd_pcm_sw_params_current(d_pcm_handle, d_sw_params);
+ if (err < 0)
bail("snd_pcm_sw_params_current", err);
- // Tell the PCM device to wait to start until we've filled
- // it's buffers half way full. This helps avoid audio underruns.
+ // Tell the PCM device to wait to start until we've filled
+ // it's buffers half way full. This helps avoid audio underruns.
- err = snd_pcm_sw_params_set_start_threshold(d_pcm_handle,
- d_sw_params,
- d_nperiods * d_period_size / 2);
- if(err < 0)
+ err = snd_pcm_sw_params_set_start_threshold(
+ d_pcm_handle, d_sw_params, d_nperiods * d_period_size / 2);
+ if (err < 0)
bail("snd_pcm_sw_params_set_start_threshold", err);
- // store the s/w params
- err = snd_pcm_sw_params(d_pcm_handle, d_sw_params);
- if(err < 0)
+ // store the s/w params
+ err = snd_pcm_sw_params(d_pcm_handle, d_sw_params);
+ if (err < 0)
bail("snd_pcm_sw_params", err);
- d_buffer_size_bytes =
- d_period_size * nchan * snd_pcm_format_size(d_format, 1);
+ d_buffer_size_bytes = d_period_size * nchan * snd_pcm_format_size(d_format, 1);
- d_buffer = new char[d_buffer_size_bytes];
+ d_buffer = new char[d_buffer_size_bytes];
- if(CHATTY_DEBUG) {
- GR_LOG_DEBUG(d_logger,boost::format("[%1%]: sample resolution = %2% bits") \
- % snd_pcm_name(d_pcm_handle) \
- % snd_pcm_hw_params_get_sbits(d_hw_params));
- }
+ if (CHATTY_DEBUG) {
+ GR_LOG_DEBUG(d_logger,
+ boost::format("[%1%]: sample resolution = %2% bits") %
+ snd_pcm_name(d_pcm_handle) %
+ snd_pcm_hw_params_get_sbits(d_hw_params));
+ }
- switch(d_format) {
- case SND_PCM_FORMAT_S16:
- if(special_case)
- d_worker = &alsa_sink::work_s16_1x2;
+ switch (d_format) {
+ case SND_PCM_FORMAT_S16:
+ if (special_case)
+ d_worker = &alsa_sink::work_s16_1x2;
else
- d_worker = &alsa_sink::work_s16;
+ d_worker = &alsa_sink::work_s16;
break;
- case SND_PCM_FORMAT_S32:
- if(special_case)
- d_worker = &alsa_sink::work_s32_1x2;
+ case SND_PCM_FORMAT_S32:
+ if (special_case)
+ d_worker = &alsa_sink::work_s32_1x2;
else
- d_worker = &alsa_sink::work_s32;
+ d_worker = &alsa_sink::work_s32;
break;
- default:
+ default:
assert(0);
- }
- return true;
}
+ return true;
+}
- alsa_sink::~alsa_sink()
- {
- if(snd_pcm_state(d_pcm_handle) == SND_PCM_STATE_RUNNING)
+alsa_sink::~alsa_sink()
+{
+ if (snd_pcm_state(d_pcm_handle) == SND_PCM_STATE_RUNNING)
snd_pcm_drop(d_pcm_handle);
- snd_pcm_close(d_pcm_handle);
- delete [] ((char*)d_hw_params);
- delete [] ((char*)d_sw_params);
- delete [] d_buffer;
- }
+ snd_pcm_close(d_pcm_handle);
+ delete[]((char*)d_hw_params);
+ delete[]((char*)d_sw_params);
+ delete[] d_buffer;
+}
- int
- alsa_sink::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- assert((noutput_items % d_period_size) == 0);
+int alsa_sink::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ assert((noutput_items % d_period_size) == 0);
- // this is a call through a pointer to a method...
- return (this->*d_worker)(noutput_items, input_items, output_items);
- }
+ // this is a call through a pointer to a method...
+ return (this->*d_worker)(noutput_items, input_items, output_items);
+}
- /*
- * Work function that deals with float to S16 conversion
- */
- int
- alsa_sink::work_s16(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- typedef int16_t sample_t; // the type of samples we're creating
- static const float scale_factor = std::pow(2.0f, 16-1) - 1;
-
- unsigned int nchan = input_items.size();
- const float **in = (const float **)&input_items[0];
- sample_t *buf = (sample_t *)d_buffer;
- int bi;
- int n;
-
- unsigned int sizeof_frame = nchan * sizeof(sample_t);
- assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
-
- for(n = 0; n < noutput_items; n += d_period_size) {
+/*
+ * Work function that deals with float to S16 conversion
+ */
+int alsa_sink::work_s16(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ typedef int16_t sample_t; // the type of samples we're creating
+ static const float scale_factor = std::pow(2.0f, 16 - 1) - 1;
+
+ unsigned int nchan = input_items.size();
+ const float** in = (const float**)&input_items[0];
+ sample_t* buf = (sample_t*)d_buffer;
+ int bi;
+ int n;
+
+ unsigned int sizeof_frame = nchan * sizeof(sample_t);
+ assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
+
+ for (n = 0; n < noutput_items; n += d_period_size) {
// process one period of data
bi = 0;
- for(unsigned int i = 0; i < d_period_size; i++) {
- for (unsigned int chan = 0; chan < nchan; chan++) {
- buf[bi++] = (sample_t) (in[chan][i] * scale_factor);
- }
+ for (unsigned int i = 0; i < d_period_size; i++) {
+ for (unsigned int chan = 0; chan < nchan; chan++) {
+ buf[bi++] = (sample_t)(in[chan][i] * scale_factor);
+ }
}
// update src pointers
- for(unsigned int chan = 0; chan < nchan; chan++)
- in[chan] += d_period_size;
+ for (unsigned int chan = 0; chan < nchan; chan++)
+ in[chan] += d_period_size;
- if(!write_buffer (buf, d_period_size, sizeof_frame))
- return -1; // No fixing this problem. Say we're done.
- }
-
- return n;
+ if (!write_buffer(buf, d_period_size, sizeof_frame))
+ return -1; // No fixing this problem. Say we're done.
}
- /*
- * Work function that deals with float to S32 conversion
- */
- int
- alsa_sink::work_s32(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- typedef int32_t sample_t; // the type of samples we're creating
- static const float scale_factor = std::pow(2.0f, 32-1) - 1;
-
- unsigned int nchan = input_items.size();
- const float **in = (const float **)&input_items[0];
- sample_t *buf = (sample_t *)d_buffer;
- int bi;
- int n;
-
- unsigned int sizeof_frame = nchan * sizeof (sample_t);
- assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
-
- for(n = 0; n < noutput_items; n += d_period_size) {
+ return n;
+}
+
+/*
+ * Work function that deals with float to S32 conversion
+ */
+int alsa_sink::work_s32(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ typedef int32_t sample_t; // the type of samples we're creating
+ static const float scale_factor = std::pow(2.0f, 32 - 1) - 1;
+
+ unsigned int nchan = input_items.size();
+ const float** in = (const float**)&input_items[0];
+ sample_t* buf = (sample_t*)d_buffer;
+ int bi;
+ int n;
+
+ unsigned int sizeof_frame = nchan * sizeof(sample_t);
+ assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
+
+ for (n = 0; n < noutput_items; n += d_period_size) {
// process one period of data
bi = 0;
- for(unsigned int i = 0; i < d_period_size; i++) {
- for(unsigned int chan = 0; chan < nchan; chan++) {
- buf[bi++] = (sample_t)(in[chan][i] * scale_factor);
- }
+ for (unsigned int i = 0; i < d_period_size; i++) {
+ for (unsigned int chan = 0; chan < nchan; chan++) {
+ buf[bi++] = (sample_t)(in[chan][i] * scale_factor);
+ }
}
// update src pointers
- for(unsigned int chan = 0; chan < nchan; chan++)
- in[chan] += d_period_size;
-
- if(!write_buffer (buf, d_period_size, sizeof_frame))
- return -1; // No fixing this problem. Say we're done.
- }
+ for (unsigned int chan = 0; chan < nchan; chan++)
+ in[chan] += d_period_size;
- return n;
+ if (!write_buffer(buf, d_period_size, sizeof_frame))
+ return -1; // No fixing this problem. Say we're done.
}
- /*
- * Work function that deals with float to S16 conversion and
- * mono to stereo kludge.
- */
- int
- alsa_sink::work_s16_1x2(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- typedef int16_t sample_t; // the type of samples we're creating
- static const float scale_factor = std::pow(2.0f, 16-1) - 1;
-
- assert(input_items.size () == 1);
- static const unsigned int nchan = 2;
- const float **in = (const float **)&input_items[0];
- sample_t *buf = (sample_t *)d_buffer;
- int bi;
- int n;
-
- unsigned int sizeof_frame = nchan * sizeof(sample_t);
- assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
-
- for(n = 0; n < noutput_items; n += d_period_size) {
+ return n;
+}
+
+/*
+ * Work function that deals with float to S16 conversion and
+ * mono to stereo kludge.
+ */
+int alsa_sink::work_s16_1x2(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ typedef int16_t sample_t; // the type of samples we're creating
+ static const float scale_factor = std::pow(2.0f, 16 - 1) - 1;
+
+ assert(input_items.size() == 1);
+ static const unsigned int nchan = 2;
+ const float** in = (const float**)&input_items[0];
+ sample_t* buf = (sample_t*)d_buffer;
+ int bi;
+ int n;
+
+ unsigned int sizeof_frame = nchan * sizeof(sample_t);
+ assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
+
+ for (n = 0; n < noutput_items; n += d_period_size) {
// process one period of data
bi = 0;
- for(unsigned int i = 0; i < d_period_size; i++) {
- sample_t t = (sample_t) (in[0][i] * scale_factor);
- buf[bi++] = t;
- buf[bi++] = t;
+ for (unsigned int i = 0; i < d_period_size; i++) {
+ sample_t t = (sample_t)(in[0][i] * scale_factor);
+ buf[bi++] = t;
+ buf[bi++] = t;
}
// update src pointers
in[0] += d_period_size;
- if(!write_buffer (buf, d_period_size, sizeof_frame))
- return -1; // No fixing this problem. Say we're done.
- }
-
- return n;
+ if (!write_buffer(buf, d_period_size, sizeof_frame))
+ return -1; // No fixing this problem. Say we're done.
}
- /*
- * Work function that deals with float to S32 conversion and
- * mono to stereo kludge.
- */
- int
- alsa_sink::work_s32_1x2(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- typedef int32_t sample_t; // the type of samples we're creating
- static const float scale_factor = std::pow(2.0f, 32-1) - 1;
-
- assert(input_items.size () == 1);
- static unsigned int nchan = 2;
- const float **in = (const float **)&input_items[0];
- sample_t *buf = (sample_t*)d_buffer;
- int bi;
- int n;
-
- unsigned int sizeof_frame = nchan * sizeof(sample_t);
- assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
-
- for(n = 0; n < noutput_items; n += d_period_size) {
+ return n;
+}
+
+/*
+ * Work function that deals with float to S32 conversion and
+ * mono to stereo kludge.
+ */
+int alsa_sink::work_s32_1x2(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ typedef int32_t sample_t; // the type of samples we're creating
+ static const float scale_factor = std::pow(2.0f, 32 - 1) - 1;
+
+ assert(input_items.size() == 1);
+ static unsigned int nchan = 2;
+ const float** in = (const float**)&input_items[0];
+ sample_t* buf = (sample_t*)d_buffer;
+ int bi;
+ int n;
+
+ unsigned int sizeof_frame = nchan * sizeof(sample_t);
+ assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
+
+ for (n = 0; n < noutput_items; n += d_period_size) {
// process one period of data
bi = 0;
- for(unsigned int i = 0; i < d_period_size; i++) {
- sample_t t = (sample_t)(in[0][i] * scale_factor);
- buf[bi++] = t;
- buf[bi++] = t;
+ for (unsigned int i = 0; i < d_period_size; i++) {
+ sample_t t = (sample_t)(in[0][i] * scale_factor);
+ buf[bi++] = t;
+ buf[bi++] = t;
}
// update src pointers
in[0] += d_period_size;
- if(!write_buffer (buf, d_period_size, sizeof_frame))
- return -1; // No fixing this problem. Say we're done.
- }
-
- return n;
+ if (!write_buffer(buf, d_period_size, sizeof_frame))
+ return -1; // No fixing this problem. Say we're done.
}
- bool
- alsa_sink::write_buffer(const void *vbuffer,
- unsigned nframes, unsigned sizeof_frame)
- {
- const unsigned char *buffer = (const unsigned char *)vbuffer;
+ return n;
+}
- while(nframes > 0){
+bool alsa_sink::write_buffer(const void* vbuffer, unsigned nframes, unsigned sizeof_frame)
+{
+ const unsigned char* buffer = (const unsigned char*)vbuffer;
+
+ while (nframes > 0) {
int r = snd_pcm_writei(d_pcm_handle, buffer, nframes);
- if(r == -EAGAIN) {
- if(d_ok_to_block == true)
- continue; // try again
- break;
+ if (r == -EAGAIN) {
+ if (d_ok_to_block == true)
+ continue; // try again
+ break;
}
- else if(r == -EPIPE) { // underrun
- d_nunderuns++;
- fputs("aU", stderr);
- if((r = snd_pcm_prepare (d_pcm_handle)) < 0){
- output_error_msg("snd_pcm_prepare failed. Can't recover from underrun", r);
- return false;
- }
- continue; // try again
+ else if (r == -EPIPE) { // underrun
+ d_nunderuns++;
+ fputs("aU", stderr);
+ if ((r = snd_pcm_prepare(d_pcm_handle)) < 0) {
+ output_error_msg("snd_pcm_prepare failed. Can't recover from underrun",
+ r);
+ return false;
+ }
+ continue; // try again
}
#ifdef ESTRPIPE
- else if(r == -ESTRPIPE) { // h/w is suspended (whatever that means)
- // This is apparently related to power management
- d_nsuspends++;
- if((r = snd_pcm_resume (d_pcm_handle)) < 0) {
- output_error_msg("failed to resume from suspend", r);
- return false;
- }
- continue; // try again
+ else if (r == -ESTRPIPE) { // h/w is suspended (whatever that means)
+ // This is apparently related to power management
+ d_nsuspends++;
+ if ((r = snd_pcm_resume(d_pcm_handle)) < 0) {
+ output_error_msg("failed to resume from suspend", r);
+ return false;
+ }
+ continue; // try again
}
#endif
else if (r < 0) {
- output_error_msg("snd_pcm_writei failed", r);
- return false;
+ output_error_msg("snd_pcm_writei failed", r);
+ return false;
}
nframes -= r;
buffer += r * sizeof_frame;
- }
-
- return true;
}
- void
- alsa_sink::output_error_msg (const char *msg, int err)
- {
- GR_LOG_ERROR(d_logger, boost::format("[%1%]: %2%: %3%") \
- % snd_pcm_name(d_pcm_handle) % msg % snd_strerror(err));
- }
+ return true;
+}
- void
- alsa_sink::bail(const char *msg, int err)
- {
- output_error_msg(msg, err);
- throw std::runtime_error("audio_alsa_sink");
- }
+void alsa_sink::output_error_msg(const char* msg, int err)
+{
+ GR_LOG_ERROR(d_logger,
+ boost::format("[%1%]: %2%: %3%") % snd_pcm_name(d_pcm_handle) % msg %
+ snd_strerror(err));
+}
+
+void alsa_sink::bail(const char* msg, int err)
+{
+ output_error_msg(msg, err);
+ throw std::runtime_error("audio_alsa_sink");
+}
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/alsa/alsa_sink.h b/gr-audio/lib/alsa/alsa_sink.h
index 27ca047507..50edc99616 100644
--- a/gr-audio/lib/alsa/alsa_sink.h
+++ b/gr-audio/lib/alsa/alsa_sink.h
@@ -33,79 +33,77 @@
#include <stdexcept>
namespace gr {
- namespace audio {
-
- /*!
- * \brief audio sink using ALSA
- * \ingroup audio_blk
- *
- * The sink has N input streams of floats, where N depends
- * on the hardware characteristics of the selected device.
- *
- * Input samples must be in the range [-1,1].
- */
- class alsa_sink : public sink
- {
- // typedef for pointer to class work method
- typedef int(alsa_sink::*work_t)(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-
- unsigned int d_sampling_rate;
- std::string d_device_name;
- snd_pcm_t *d_pcm_handle;
- snd_pcm_hw_params_t *d_hw_params;
- snd_pcm_sw_params_t *d_sw_params;
- snd_pcm_format_t d_format;
- unsigned int d_nperiods;
- unsigned int d_period_time_us; // microseconds
- snd_pcm_uframes_t d_period_size; // in frames
- unsigned int d_buffer_size_bytes; // sizeof of d_buffer
- char *d_buffer;
- work_t d_worker; // the work method to use
- bool d_special_case_mono_to_stereo;
-
- // random stats
- int d_nunderuns; // count of underruns
- int d_nsuspends; // count of suspends
- bool d_ok_to_block; // defaults to "true", controls blocking/non-block I/O
-
- void output_error_msg(const char *msg, int err);
- void bail(const char *msg, int err);
-
- public:
- alsa_sink(int sampling_rate,
- const std::string device_name,
- bool ok_to_block);
- ~alsa_sink();
-
- bool check_topology(int ninputs, int noutputs);
-
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-
- protected:
- bool write_buffer(const void *buffer, unsigned nframes, unsigned sizeof_frame);
-
- int work_s16(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-
- int work_s16_1x2(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-
- int work_s32(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-
- int work_s32_1x2(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
-
- } /* namespace audio */
+namespace audio {
+
+/*!
+ * \brief audio sink using ALSA
+ * \ingroup audio_blk
+ *
+ * The sink has N input streams of floats, where N depends
+ * on the hardware characteristics of the selected device.
+ *
+ * Input samples must be in the range [-1,1].
+ */
+class alsa_sink : public sink
+{
+ // typedef for pointer to class work method
+ typedef int (alsa_sink::*work_t)(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+
+ unsigned int d_sampling_rate;
+ std::string d_device_name;
+ snd_pcm_t* d_pcm_handle;
+ snd_pcm_hw_params_t* d_hw_params;
+ snd_pcm_sw_params_t* d_sw_params;
+ snd_pcm_format_t d_format;
+ unsigned int d_nperiods;
+ unsigned int d_period_time_us; // microseconds
+ snd_pcm_uframes_t d_period_size; // in frames
+ unsigned int d_buffer_size_bytes; // sizeof of d_buffer
+ char* d_buffer;
+ work_t d_worker; // the work method to use
+ bool d_special_case_mono_to_stereo;
+
+ // random stats
+ int d_nunderuns; // count of underruns
+ int d_nsuspends; // count of suspends
+ bool d_ok_to_block; // defaults to "true", controls blocking/non-block I/O
+
+ void output_error_msg(const char* msg, int err);
+ void bail(const char* msg, int err);
+
+public:
+ alsa_sink(int sampling_rate, const std::string device_name, bool ok_to_block);
+ ~alsa_sink();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+
+protected:
+ bool write_buffer(const void* buffer, unsigned nframes, unsigned sizeof_frame);
+
+ int work_s16(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+
+ int work_s16_1x2(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+
+ int work_s32(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+
+ int work_s32_1x2(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
+
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_AUDIO_ALSA_SINK_H */
diff --git a/gr-audio/lib/alsa/alsa_source.cc b/gr-audio/lib/alsa/alsa_source.cc
index 6655849362..82443268c4 100644
--- a/gr-audio/lib/alsa/alsa_source.cc
+++ b/gr-audio/lib/alsa/alsa_source.cc
@@ -34,480 +34,468 @@
#include <stdexcept>
namespace gr {
- namespace audio {
-
- source::sptr
- alsa_source_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block)
- {
- return source::sptr
- (new alsa_source(sampling_rate, device_name, ok_to_block));
- }
-
- static bool CHATTY_DEBUG = false;
-
- static snd_pcm_format_t acceptable_formats[] = {
- // these are in our preferred order...
- SND_PCM_FORMAT_S32,
- SND_PCM_FORMAT_S16
- };
-
-#define NELEMS(x) (sizeof(x)/sizeof(x[0]))
-
- static std::string
- default_device_name()
- {
- return prefs::singleton()->get_string("audio_alsa",
- "default_input_device",
- "default");
- }
-
- static double
- default_period_time()
- {
- return std::max(0.001,
- prefs::singleton()->get_double("audio_alsa", "period_time", 0.010));
- }
-
- static int
- default_nperiods()
- {
- return std::max(2L,
- prefs::singleton()->get_long("audio_alsa", "nperiods", 4));
- }
-
- // ----------------------------------------------------------------
-
- alsa_source::alsa_source(int sampling_rate,
- const std::string device_name,
- bool ok_to_block)
- : sync_block("audio_alsa_source",
- io_signature::make(0, 0, 0),
- io_signature::make(0, 0, 0)),
- d_sampling_rate(sampling_rate),
- d_device_name(device_name.empty() ? default_device_name() : device_name),
- d_pcm_handle(0),
- d_hw_params((snd_pcm_hw_params_t*)(new char[snd_pcm_hw_params_sizeof()])),
- d_sw_params((snd_pcm_sw_params_t*)(new char[snd_pcm_sw_params_sizeof()])),
- d_nperiods(default_nperiods()),
- d_period_time_us((unsigned int)(default_period_time() * 1e6)),
- d_period_size(0),
- d_buffer_size_bytes(0), d_buffer(0),
- d_worker(0), d_hw_nchan(0),
- d_special_case_stereo_to_mono(false),
- d_noverruns(0), d_nsuspends(0)
- {
- CHATTY_DEBUG = prefs::singleton()->get_bool("audio_alsa", "verbose", false);
-
- int error;
- int dir;
-
- // open the device for capture
- error = snd_pcm_open(&d_pcm_handle, d_device_name.c_str(),
- SND_PCM_STREAM_CAPTURE, 0);
- if(error < 0){
- GR_LOG_ERROR(d_logger, boost::format("[%1%]: %2%") \
- % (d_device_name) % (snd_strerror(error)));
+namespace audio {
+
+source::sptr
+alsa_source_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block)
+{
+ return source::sptr(new alsa_source(sampling_rate, device_name, ok_to_block));
+}
+
+static bool CHATTY_DEBUG = false;
+
+static snd_pcm_format_t acceptable_formats[] = {
+ // these are in our preferred order...
+ SND_PCM_FORMAT_S32,
+ SND_PCM_FORMAT_S16
+};
+
+#define NELEMS(x) (sizeof(x) / sizeof(x[0]))
+
+static std::string default_device_name()
+{
+ return prefs::singleton()->get_string(
+ "audio_alsa", "default_input_device", "default");
+}
+
+static double default_period_time()
+{
+ return std::max(0.001,
+ prefs::singleton()->get_double("audio_alsa", "period_time", 0.010));
+}
+
+static int default_nperiods()
+{
+ return std::max(2L, prefs::singleton()->get_long("audio_alsa", "nperiods", 4));
+}
+
+// ----------------------------------------------------------------
+
+alsa_source::alsa_source(int sampling_rate,
+ const std::string device_name,
+ bool ok_to_block)
+ : sync_block(
+ "audio_alsa_source", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)),
+ d_sampling_rate(sampling_rate),
+ d_device_name(device_name.empty() ? default_device_name() : device_name),
+ d_pcm_handle(0),
+ d_hw_params((snd_pcm_hw_params_t*)(new char[snd_pcm_hw_params_sizeof()])),
+ d_sw_params((snd_pcm_sw_params_t*)(new char[snd_pcm_sw_params_sizeof()])),
+ d_nperiods(default_nperiods()),
+ d_period_time_us((unsigned int)(default_period_time() * 1e6)),
+ d_period_size(0),
+ d_buffer_size_bytes(0),
+ d_buffer(0),
+ d_worker(0),
+ d_hw_nchan(0),
+ d_special_case_stereo_to_mono(false),
+ d_noverruns(0),
+ d_nsuspends(0)
+{
+ CHATTY_DEBUG = prefs::singleton()->get_bool("audio_alsa", "verbose", false);
+
+ int error;
+ int dir;
+
+ // open the device for capture
+ error = snd_pcm_open(&d_pcm_handle, d_device_name.c_str(), SND_PCM_STREAM_CAPTURE, 0);
+ if (error < 0) {
+ GR_LOG_ERROR(d_logger,
+ boost::format("[%1%]: %2%") % (d_device_name) %
+ (snd_strerror(error)));
throw std::runtime_error("audio_alsa_source");
- }
+ }
- // Fill params with a full configuration space for a PCM.
- error = snd_pcm_hw_params_any(d_pcm_handle, d_hw_params);
- if(error < 0)
+ // Fill params with a full configuration space for a PCM.
+ error = snd_pcm_hw_params_any(d_pcm_handle, d_hw_params);
+ if (error < 0)
bail("broken configuration for playback", error);
- if(CHATTY_DEBUG)
+ if (CHATTY_DEBUG)
gri_alsa_dump_hw_params(d_pcm_handle, d_hw_params, stdout);
- // now that we know how many channels the h/w can handle, set output signature
- unsigned int umax_chan;
- unsigned int umin_chan;
- snd_pcm_hw_params_get_channels_min(d_hw_params, &umin_chan);
- snd_pcm_hw_params_get_channels_max(d_hw_params, &umax_chan);
- int min_chan = std::min(umin_chan, 1000U);
- int max_chan = std::min(umax_chan, 1000U);
-
- // As a special case, if the hw's min_chan is two, we'll accept
- // a single output and handle the demux ourselves.
- if(min_chan == 2) {
+ // now that we know how many channels the h/w can handle, set output signature
+ unsigned int umax_chan;
+ unsigned int umin_chan;
+ snd_pcm_hw_params_get_channels_min(d_hw_params, &umin_chan);
+ snd_pcm_hw_params_get_channels_max(d_hw_params, &umax_chan);
+ int min_chan = std::min(umin_chan, 1000U);
+ int max_chan = std::min(umax_chan, 1000U);
+
+ // As a special case, if the hw's min_chan is two, we'll accept
+ // a single output and handle the demux ourselves.
+ if (min_chan == 2) {
min_chan = 1;
d_special_case_stereo_to_mono = true;
- }
+ }
- set_output_signature(io_signature::make(min_chan, max_chan,
- sizeof(float)));
+ set_output_signature(io_signature::make(min_chan, max_chan, sizeof(float)));
- // fill in portions of the d_hw_params that we know now...
+ // fill in portions of the d_hw_params that we know now...
- // Specify the access methods we implement
- // For now, we only handle RW_INTERLEAVED...
- snd_pcm_access_mask_t *access_mask;
- snd_pcm_access_mask_t **access_mask_ptr = &access_mask; // FIXME: workaround for compiler warning
- snd_pcm_access_mask_alloca(access_mask_ptr);
- snd_pcm_access_mask_none(access_mask);
- snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
- // snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED);
+ // Specify the access methods we implement
+ // For now, we only handle RW_INTERLEAVED...
+ snd_pcm_access_mask_t* access_mask;
+ snd_pcm_access_mask_t** access_mask_ptr =
+ &access_mask; // FIXME: workaround for compiler warning
+ snd_pcm_access_mask_alloca(access_mask_ptr);
+ snd_pcm_access_mask_none(access_mask);
+ snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
+ // snd_pcm_access_mask_set(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED);
- if((error = snd_pcm_hw_params_set_access_mask(d_pcm_handle,
- d_hw_params, access_mask)) < 0)
+ if ((error = snd_pcm_hw_params_set_access_mask(
+ d_pcm_handle, d_hw_params, access_mask)) < 0)
bail("failed to set access mask", error);
- // set sample format
- if(!gri_alsa_pick_acceptable_format(d_pcm_handle, d_hw_params,
- acceptable_formats,
- NELEMS(acceptable_formats),
- &d_format,
- "audio_alsa_source",
- CHATTY_DEBUG))
+ // set sample format
+ if (!gri_alsa_pick_acceptable_format(d_pcm_handle,
+ d_hw_params,
+ acceptable_formats,
+ NELEMS(acceptable_formats),
+ &d_format,
+ "audio_alsa_source",
+ CHATTY_DEBUG))
throw std::runtime_error("audio_alsa_source");
- // sampling rate
- unsigned int orig_sampling_rate = d_sampling_rate;
- if((error = snd_pcm_hw_params_set_rate_near(d_pcm_handle, d_hw_params,
- &d_sampling_rate, 0)) < 0)
+ // sampling rate
+ unsigned int orig_sampling_rate = d_sampling_rate;
+ if ((error = snd_pcm_hw_params_set_rate_near(
+ d_pcm_handle, d_hw_params, &d_sampling_rate, 0)) < 0)
bail("failed to set rate near", error);
- if(orig_sampling_rate != d_sampling_rate){
- GR_LOG_INFO(d_logger, boost::format("[%1%]: unable to support sampling rate %2%\n\tCard requested %3% instead.") \
- % snd_pcm_name(d_pcm_handle) % orig_sampling_rate \
- % d_sampling_rate);
- }
-
- /*
- * ALSA transfers data in units of "periods".
- * We indirectly determine the underlying buffersize by specifying
- * the number of periods we want (typically 4) and the length of each
- * period in units of time (typically 1ms).
- */
- unsigned int min_nperiods, max_nperiods;
- snd_pcm_hw_params_get_periods_min(d_hw_params, &min_nperiods, &dir);
- snd_pcm_hw_params_get_periods_max(d_hw_params, &max_nperiods, &dir);
-
- unsigned int orig_nperiods = d_nperiods;
- d_nperiods = std::min(std::max (min_nperiods, d_nperiods), max_nperiods);
-
- // adjust period time so that total buffering remains more-or-less constant
- d_period_time_us = (d_period_time_us * orig_nperiods) / d_nperiods;
-
- error = snd_pcm_hw_params_set_periods(d_pcm_handle, d_hw_params,
- d_nperiods, 0);
- if(error < 0)
+ if (orig_sampling_rate != d_sampling_rate) {
+ GR_LOG_INFO(d_logger,
+ boost::format("[%1%]: unable to support sampling rate %2%\n\tCard "
+ "requested %3% instead.") %
+ snd_pcm_name(d_pcm_handle) % orig_sampling_rate %
+ d_sampling_rate);
+ }
+
+ /*
+ * ALSA transfers data in units of "periods".
+ * We indirectly determine the underlying buffersize by specifying
+ * the number of periods we want (typically 4) and the length of each
+ * period in units of time (typically 1ms).
+ */
+ unsigned int min_nperiods, max_nperiods;
+ snd_pcm_hw_params_get_periods_min(d_hw_params, &min_nperiods, &dir);
+ snd_pcm_hw_params_get_periods_max(d_hw_params, &max_nperiods, &dir);
+
+ unsigned int orig_nperiods = d_nperiods;
+ d_nperiods = std::min(std::max(min_nperiods, d_nperiods), max_nperiods);
+
+ // adjust period time so that total buffering remains more-or-less constant
+ d_period_time_us = (d_period_time_us * orig_nperiods) / d_nperiods;
+
+ error = snd_pcm_hw_params_set_periods(d_pcm_handle, d_hw_params, d_nperiods, 0);
+ if (error < 0)
bail("set_periods failed", error);
- dir = 0;
- error = snd_pcm_hw_params_set_period_time_near(d_pcm_handle, d_hw_params,
- &d_period_time_us, &dir);
- if(error < 0)
+ dir = 0;
+ error = snd_pcm_hw_params_set_period_time_near(
+ d_pcm_handle, d_hw_params, &d_period_time_us, &dir);
+ if (error < 0)
bail("set_period_time_near failed", error);
- dir = 0;
- error = snd_pcm_hw_params_get_period_size(d_hw_params,
- &d_period_size, &dir);
- if(error < 0)
+ dir = 0;
+ error = snd_pcm_hw_params_get_period_size(d_hw_params, &d_period_size, &dir);
+ if (error < 0)
bail("get_period_size failed", error);
- set_output_multiple(d_period_size);
- }
-
- bool
- alsa_source::check_topology(int ninputs, int noutputs)
- {
- // noutputs is how many channels the user has connected.
- // Now we can finish up setting up the hw params...
-
- unsigned int nchan = noutputs;
- int err;
-
- // Check the state of the stream
- // Ensure that the pcm is in a state where we can still mess with the hw_params
- snd_pcm_state_t state;
- state=snd_pcm_state(d_pcm_handle);
- if(state== SND_PCM_STATE_RUNNING)
- return true; // If stream is running, don't change any parameters
- else if(state == SND_PCM_STATE_XRUN)
- snd_pcm_prepare(d_pcm_handle); // Prepare stream on underrun, and we can set parameters;
-
- bool special_case = nchan == 1 && d_special_case_stereo_to_mono;
- if(special_case)
+ set_output_multiple(d_period_size);
+}
+
+bool alsa_source::check_topology(int ninputs, int noutputs)
+{
+ // noutputs is how many channels the user has connected.
+ // Now we can finish up setting up the hw params...
+
+ unsigned int nchan = noutputs;
+ int err;
+
+ // Check the state of the stream
+ // Ensure that the pcm is in a state where we can still mess with the hw_params
+ snd_pcm_state_t state;
+ state = snd_pcm_state(d_pcm_handle);
+ if (state == SND_PCM_STATE_RUNNING)
+ return true; // If stream is running, don't change any parameters
+ else if (state == SND_PCM_STATE_XRUN)
+ snd_pcm_prepare(
+ d_pcm_handle); // Prepare stream on underrun, and we can set parameters;
+
+ bool special_case = nchan == 1 && d_special_case_stereo_to_mono;
+ if (special_case)
nchan = 2;
- d_hw_nchan = nchan;
- err = snd_pcm_hw_params_set_channels(d_pcm_handle, d_hw_params, d_hw_nchan);
- if(err < 0) {
+ d_hw_nchan = nchan;
+ err = snd_pcm_hw_params_set_channels(d_pcm_handle, d_hw_params, d_hw_nchan);
+ if (err < 0) {
output_error_msg("set_channels failed", err);
return false;
- }
+ }
- // set the parameters into the driver...
- err = snd_pcm_hw_params(d_pcm_handle, d_hw_params);
- if(err < 0) {
+ // set the parameters into the driver...
+ err = snd_pcm_hw_params(d_pcm_handle, d_hw_params);
+ if (err < 0) {
output_error_msg("snd_pcm_hw_params failed", err);
return false;
- }
+ }
- d_buffer_size_bytes =
- d_period_size * d_hw_nchan * snd_pcm_format_size(d_format, 1);
+ d_buffer_size_bytes = d_period_size * d_hw_nchan * snd_pcm_format_size(d_format, 1);
- d_buffer = new char[d_buffer_size_bytes];
+ d_buffer = new char[d_buffer_size_bytes];
- if(CHATTY_DEBUG) {
- GR_LOG_DEBUG(d_logger, boost::format("[%1%]: sample resolution = %2% bits") \
- % snd_pcm_name(d_pcm_handle) \
- % snd_pcm_hw_params_get_sbits(d_hw_params));
- }
+ if (CHATTY_DEBUG) {
+ GR_LOG_DEBUG(d_logger,
+ boost::format("[%1%]: sample resolution = %2% bits") %
+ snd_pcm_name(d_pcm_handle) %
+ snd_pcm_hw_params_get_sbits(d_hw_params));
+ }
- switch(d_format) {
- case SND_PCM_FORMAT_S16:
- if(special_case)
- d_worker = &alsa_source::work_s16_2x1;
+ switch (d_format) {
+ case SND_PCM_FORMAT_S16:
+ if (special_case)
+ d_worker = &alsa_source::work_s16_2x1;
else
- d_worker = &alsa_source::work_s16;
+ d_worker = &alsa_source::work_s16;
break;
- case SND_PCM_FORMAT_S32:
- if(special_case)
- d_worker = &alsa_source::work_s32_2x1;
+ case SND_PCM_FORMAT_S32:
+ if (special_case)
+ d_worker = &alsa_source::work_s32_2x1;
else
- d_worker = &alsa_source::work_s32;
+ d_worker = &alsa_source::work_s32;
break;
- default:
+ default:
assert(0);
- }
-
- return true;
}
- alsa_source::~alsa_source()
- {
- if(snd_pcm_state(d_pcm_handle) == SND_PCM_STATE_RUNNING)
+ return true;
+}
+
+alsa_source::~alsa_source()
+{
+ if (snd_pcm_state(d_pcm_handle) == SND_PCM_STATE_RUNNING)
snd_pcm_drop(d_pcm_handle);
- snd_pcm_close(d_pcm_handle);
- delete [] ((char*)d_hw_params);
- delete [] ((char*)d_sw_params);
- delete [] d_buffer;
- }
+ snd_pcm_close(d_pcm_handle);
+ delete[]((char*)d_hw_params);
+ delete[]((char*)d_sw_params);
+ delete[] d_buffer;
+}
- int
- alsa_source::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- assert((noutput_items % d_period_size) == 0);
- assert(noutput_items != 0);
+int alsa_source::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ assert((noutput_items % d_period_size) == 0);
+ assert(noutput_items != 0);
- // this is a call through a pointer to a method...
- return (this->*d_worker)(noutput_items, input_items, output_items);
- }
+ // this is a call through a pointer to a method...
+ return (this->*d_worker)(noutput_items, input_items, output_items);
+}
- /*
- * Work function that deals with float to S16 conversion
- */
- int
- alsa_source::work_s16(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- typedef int16_t sample_t; // the type of samples we're creating
- static const float scale_factor = 1.0 / std::pow(2.0f, 16-1);
-
- unsigned int nchan = output_items.size ();
- float **out = (float **)&output_items[0];
- sample_t *buf = (sample_t *)d_buffer;
- int bi;
-
- unsigned int sizeof_frame = d_hw_nchan * sizeof (sample_t);
- assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
-
- // To minimize latency, return at most a single period's worth of samples.
- // [We could also read the first one in a blocking mode and subsequent
- // ones in non-blocking mode, but we'll leave that for later (or never).]
-
- if(!read_buffer(buf, d_period_size, sizeof_frame))
- return -1; // No fixing this problem. Say we're done.
-
- // process one period of data
- bi = 0;
- for(unsigned int i = 0; i < d_period_size; i++) {
- for(unsigned int chan = 0; chan < nchan; chan++) {
- out[chan][i] = (float) buf[bi++] * scale_factor;
+/*
+ * Work function that deals with float to S16 conversion
+ */
+int alsa_source::work_s16(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ typedef int16_t sample_t; // the type of samples we're creating
+ static const float scale_factor = 1.0 / std::pow(2.0f, 16 - 1);
+
+ unsigned int nchan = output_items.size();
+ float** out = (float**)&output_items[0];
+ sample_t* buf = (sample_t*)d_buffer;
+ int bi;
+
+ unsigned int sizeof_frame = d_hw_nchan * sizeof(sample_t);
+ assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
+
+ // To minimize latency, return at most a single period's worth of samples.
+ // [We could also read the first one in a blocking mode and subsequent
+ // ones in non-blocking mode, but we'll leave that for later (or never).]
+
+ if (!read_buffer(buf, d_period_size, sizeof_frame))
+ return -1; // No fixing this problem. Say we're done.
+
+ // process one period of data
+ bi = 0;
+ for (unsigned int i = 0; i < d_period_size; i++) {
+ for (unsigned int chan = 0; chan < nchan; chan++) {
+ out[chan][i] = (float)buf[bi++] * scale_factor;
}
- }
-
- return d_period_size;
}
- /*
- * Work function that deals with float to S16 conversion
- * and stereo to mono kludge...
- */
- int
- alsa_source::work_s16_2x1(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- typedef int16_t sample_t; // the type of samples we're creating
- static const float scale_factor = 1.0 / std::pow(2.0f, 16-1);
-
- float **out = (float**)&output_items[0];
- sample_t *buf = (sample_t*)d_buffer;
- int bi;
-
- assert(output_items.size () == 1);
-
- unsigned int sizeof_frame = d_hw_nchan * sizeof(sample_t);
- assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
-
- // To minimize latency, return at most a single period's worth of samples.
- // [We could also read the first one in a blocking mode and subsequent
- // ones in non-blocking mode, but we'll leave that for later (or never).]
- if(!read_buffer (buf, d_period_size, sizeof_frame))
- return -1; // No fixing this problem. Say we're done.
-
- // process one period of data
- bi = 0;
- for(unsigned int i = 0; i < d_period_size; i++) {
- int t = (buf[bi] + buf[bi+1]) / 2;
- bi += 2;
- out[0][i] = (float) t * scale_factor;
- }
+ return d_period_size;
+}
- return d_period_size;
+/*
+ * Work function that deals with float to S16 conversion
+ * and stereo to mono kludge...
+ */
+int alsa_source::work_s16_2x1(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ typedef int16_t sample_t; // the type of samples we're creating
+ static const float scale_factor = 1.0 / std::pow(2.0f, 16 - 1);
+
+ float** out = (float**)&output_items[0];
+ sample_t* buf = (sample_t*)d_buffer;
+ int bi;
+
+ assert(output_items.size() == 1);
+
+ unsigned int sizeof_frame = d_hw_nchan * sizeof(sample_t);
+ assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
+
+ // To minimize latency, return at most a single period's worth of samples.
+ // [We could also read the first one in a blocking mode and subsequent
+ // ones in non-blocking mode, but we'll leave that for later (or never).]
+ if (!read_buffer(buf, d_period_size, sizeof_frame))
+ return -1; // No fixing this problem. Say we're done.
+
+ // process one period of data
+ bi = 0;
+ for (unsigned int i = 0; i < d_period_size; i++) {
+ int t = (buf[bi] + buf[bi + 1]) / 2;
+ bi += 2;
+ out[0][i] = (float)t * scale_factor;
}
- /*
- * Work function that deals with float to S32 conversion
- */
- int
- alsa_source::work_s32(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- typedef int32_t sample_t; // the type of samples we're creating
- static const float scale_factor = 1.0 / std::pow(2.0f, 32-1);
-
- unsigned int nchan = output_items.size ();
- float **out = (float**)&output_items[0];
- sample_t *buf = (sample_t*)d_buffer;
- int bi;
-
- unsigned int sizeof_frame = d_hw_nchan * sizeof(sample_t);
- assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
-
- // To minimize latency, return at most a single period's worth of samples.
- // [We could also read the first one in a blocking mode and subsequent
- // ones in non-blocking mode, but we'll leave that for later (or never).]
-
- if(!read_buffer(buf, d_period_size, sizeof_frame))
- return -1; // No fixing this problem. Say we're done.
-
- // process one period of data
- bi = 0;
- for(unsigned int i = 0; i < d_period_size; i++) {
- for(unsigned int chan = 0; chan < nchan; chan++) {
- out[chan][i] = (float) buf[bi++] * scale_factor;
- }
- }
+ return d_period_size;
+}
- return d_period_size;
+/*
+ * Work function that deals with float to S32 conversion
+ */
+int alsa_source::work_s32(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ typedef int32_t sample_t; // the type of samples we're creating
+ static const float scale_factor = 1.0 / std::pow(2.0f, 32 - 1);
+
+ unsigned int nchan = output_items.size();
+ float** out = (float**)&output_items[0];
+ sample_t* buf = (sample_t*)d_buffer;
+ int bi;
+
+ unsigned int sizeof_frame = d_hw_nchan * sizeof(sample_t);
+ assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
+
+ // To minimize latency, return at most a single period's worth of samples.
+ // [We could also read the first one in a blocking mode and subsequent
+ // ones in non-blocking mode, but we'll leave that for later (or never).]
+
+ if (!read_buffer(buf, d_period_size, sizeof_frame))
+ return -1; // No fixing this problem. Say we're done.
+
+ // process one period of data
+ bi = 0;
+ for (unsigned int i = 0; i < d_period_size; i++) {
+ for (unsigned int chan = 0; chan < nchan; chan++) {
+ out[chan][i] = (float)buf[bi++] * scale_factor;
+ }
}
- /*
- * Work function that deals with float to S32 conversion
- * and stereo to mono kludge...
- */
- int
- alsa_source::work_s32_2x1(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- typedef int32_t sample_t; // the type of samples we're creating
- static const float scale_factor = 1.0 / std::pow(2.0f, 32-1);
-
- float **out = (float**)&output_items[0];
- sample_t *buf = (sample_t*)d_buffer;
- int bi;
-
- assert(output_items.size () == 1);
-
- unsigned int sizeof_frame = d_hw_nchan * sizeof(sample_t);
- assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
-
- // To minimize latency, return at most a single period's worth of samples.
- // [We could also read the first one in a blocking mode and subsequent
- // ones in non-blocking mode, but we'll leave that for later (or never).]
-
- if(!read_buffer(buf, d_period_size, sizeof_frame))
- return -1; // No fixing this problem. Say we're done.
-
- // process one period of data
- bi = 0;
- for(unsigned int i = 0; i < d_period_size; i++) {
- int t = (buf[bi] + buf[bi+1]) / 2;
+ return d_period_size;
+}
+
+/*
+ * Work function that deals with float to S32 conversion
+ * and stereo to mono kludge...
+ */
+int alsa_source::work_s32_2x1(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ typedef int32_t sample_t; // the type of samples we're creating
+ static const float scale_factor = 1.0 / std::pow(2.0f, 32 - 1);
+
+ float** out = (float**)&output_items[0];
+ sample_t* buf = (sample_t*)d_buffer;
+ int bi;
+
+ assert(output_items.size() == 1);
+
+ unsigned int sizeof_frame = d_hw_nchan * sizeof(sample_t);
+ assert(d_buffer_size_bytes == d_period_size * sizeof_frame);
+
+ // To minimize latency, return at most a single period's worth of samples.
+ // [We could also read the first one in a blocking mode and subsequent
+ // ones in non-blocking mode, but we'll leave that for later (or never).]
+
+ if (!read_buffer(buf, d_period_size, sizeof_frame))
+ return -1; // No fixing this problem. Say we're done.
+
+ // process one period of data
+ bi = 0;
+ for (unsigned int i = 0; i < d_period_size; i++) {
+ int t = (buf[bi] + buf[bi + 1]) / 2;
bi += 2;
out[0][i] = (float)t * scale_factor;
- }
-
- return d_period_size;
}
- bool
- alsa_source::read_buffer(void *vbuffer, unsigned nframes, unsigned sizeof_frame)
- {
- unsigned char *buffer = (unsigned char*)vbuffer;
-
- while(nframes > 0) {
- int r = snd_pcm_readi (d_pcm_handle, buffer, nframes);
- if(r == -EAGAIN)
- continue; // try again
-
- else if(r == -EPIPE) { // overrun
- d_noverruns++;
- fputs("aO", stderr);
- if((r = snd_pcm_prepare (d_pcm_handle)) < 0) {
- output_error_msg("snd_pcm_prepare failed. Can't recover from overrun", r);
- return false;
- }
- continue; // try again
+ return d_period_size;
+}
+
+bool alsa_source::read_buffer(void* vbuffer, unsigned nframes, unsigned sizeof_frame)
+{
+ unsigned char* buffer = (unsigned char*)vbuffer;
+
+ while (nframes > 0) {
+ int r = snd_pcm_readi(d_pcm_handle, buffer, nframes);
+ if (r == -EAGAIN)
+ continue; // try again
+
+ else if (r == -EPIPE) { // overrun
+ d_noverruns++;
+ fputs("aO", stderr);
+ if ((r = snd_pcm_prepare(d_pcm_handle)) < 0) {
+ output_error_msg("snd_pcm_prepare failed. Can't recover from overrun", r);
+ return false;
+ }
+ continue; // try again
}
#ifdef ESTRPIPE
- else if(r == -ESTRPIPE) { // h/w is suspended (whatever that means)
- // This is apparently related to power management
- d_nsuspends++;
- if((r = snd_pcm_resume (d_pcm_handle)) < 0) {
- output_error_msg ("failed to resume from suspend", r);
- return false;
- }
- continue; // try again
+ else if (r == -ESTRPIPE) { // h/w is suspended (whatever that means)
+ // This is apparently related to power management
+ d_nsuspends++;
+ if ((r = snd_pcm_resume(d_pcm_handle)) < 0) {
+ output_error_msg("failed to resume from suspend", r);
+ return false;
+ }
+ continue; // try again
}
#endif
- else if(r < 0) {
- output_error_msg("snd_pcm_readi failed", r);
- return false;
+ else if (r < 0) {
+ output_error_msg("snd_pcm_readi failed", r);
+ return false;
}
nframes -= r;
buffer += r * sizeof_frame;
- }
-
- return true;
}
- void
- alsa_source::output_error_msg(const char *msg, int err)
- {
- GR_LOG_ERROR(d_logger, boost::format("[%1%]: %2%: %3%") \
- % snd_pcm_name(d_pcm_handle) % msg % snd_strerror(err));
- }
+ return true;
+}
- void
- alsa_source::bail(const char *msg, int err)
- {
- output_error_msg(msg, err);
- throw std::runtime_error("audio_alsa_source");
- }
+void alsa_source::output_error_msg(const char* msg, int err)
+{
+ GR_LOG_ERROR(d_logger,
+ boost::format("[%1%]: %2%: %3%") % snd_pcm_name(d_pcm_handle) % msg %
+ snd_strerror(err));
+}
+
+void alsa_source::bail(const char* msg, int err)
+{
+ output_error_msg(msg, err);
+ throw std::runtime_error("audio_alsa_source");
+}
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/alsa/alsa_source.h b/gr-audio/lib/alsa/alsa_source.h
index 61c50be754..66d349a840 100644
--- a/gr-audio/lib/alsa/alsa_source.h
+++ b/gr-audio/lib/alsa/alsa_source.h
@@ -33,82 +33,80 @@
#include <stdexcept>
namespace gr {
- namespace audio {
-
- class alsa_source;
- typedef boost::shared_ptr<alsa_source> alsa_source_sptr;
-
- /*!
- * \brief audio source using ALSA
- * \ingroup audio_blk
- *
- * The source has between 1 and N input streams of floats, where N is
- * depends on the hardware characteristics of the selected device.
- *
- * Output samples will be in the range [-1,1].
- */
- class alsa_source : public source
- {
- // typedef for pointer to class work method
- typedef int(alsa_source::*work_t)(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-
- unsigned int d_sampling_rate;
- std::string d_device_name;
- snd_pcm_t *d_pcm_handle;
- snd_pcm_hw_params_t *d_hw_params;
- snd_pcm_sw_params_t *d_sw_params;
- snd_pcm_format_t d_format;
- unsigned int d_nperiods;
- unsigned int d_period_time_us; // microseconds
- snd_pcm_uframes_t d_period_size; // in frames
- unsigned int d_buffer_size_bytes; // sizeof of d_buffer
- char *d_buffer;
- work_t d_worker; // the work method to use
- unsigned int d_hw_nchan; // # of configured h/w channels
- bool d_special_case_stereo_to_mono;
-
- // random stats
- int d_noverruns; // count of overruns
- int d_nsuspends; // count of suspends
-
- void output_error_msg(const char *msg, int err);
- void bail(const char *msg, int err);
-
- public:
- alsa_source(int sampling_rate,
- const std::string device_name,
- bool ok_to_block);
- ~alsa_source();
-
- bool check_topology(int ninputs, int noutputs);
-
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-
- protected:
- bool read_buffer(void *buffer, unsigned nframes, unsigned sizeof_frame);
-
- int work_s16(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-
- int work_s16_2x1(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-
- int work_s32(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
-
- int work_s32_2x1(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
-
- } /* namespace audio */
+namespace audio {
+
+class alsa_source;
+typedef boost::shared_ptr<alsa_source> alsa_source_sptr;
+
+/*!
+ * \brief audio source using ALSA
+ * \ingroup audio_blk
+ *
+ * The source has between 1 and N input streams of floats, where N is
+ * depends on the hardware characteristics of the selected device.
+ *
+ * Output samples will be in the range [-1,1].
+ */
+class alsa_source : public source
+{
+ // typedef for pointer to class work method
+ typedef int (alsa_source::*work_t)(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+
+ unsigned int d_sampling_rate;
+ std::string d_device_name;
+ snd_pcm_t* d_pcm_handle;
+ snd_pcm_hw_params_t* d_hw_params;
+ snd_pcm_sw_params_t* d_sw_params;
+ snd_pcm_format_t d_format;
+ unsigned int d_nperiods;
+ unsigned int d_period_time_us; // microseconds
+ snd_pcm_uframes_t d_period_size; // in frames
+ unsigned int d_buffer_size_bytes; // sizeof of d_buffer
+ char* d_buffer;
+ work_t d_worker; // the work method to use
+ unsigned int d_hw_nchan; // # of configured h/w channels
+ bool d_special_case_stereo_to_mono;
+
+ // random stats
+ int d_noverruns; // count of overruns
+ int d_nsuspends; // count of suspends
+
+ void output_error_msg(const char* msg, int err);
+ void bail(const char* msg, int err);
+
+public:
+ alsa_source(int sampling_rate, const std::string device_name, bool ok_to_block);
+ ~alsa_source();
+
+ bool check_topology(int ninputs, int noutputs);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+
+protected:
+ bool read_buffer(void* buffer, unsigned nframes, unsigned sizeof_frame);
+
+ int work_s16(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+
+ int work_s16_2x1(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+
+ int work_s32(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+
+ int work_s32_2x1(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
+
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_AUDIO_ALSA_SOURCE_H */
diff --git a/gr-audio/lib/audio_registry.cc b/gr-audio/lib/audio_registry.cc
index 421806558a..5c0c6317cb 100644
--- a/gr-audio/lib/audio_registry.cc
+++ b/gr-audio/lib/audio_registry.cc
@@ -28,19 +28,18 @@
#include <iostream>
namespace gr {
- namespace audio {
+namespace audio {
- /***********************************************************************
- * Create registries
- **********************************************************************/
+/***********************************************************************
+ * Create registries
+ **********************************************************************/
- static std::vector<source_entry_t> &
- get_source_registry(void)
- {
- static bool src_reg = false;
- static std::vector<source_entry_t> s_registry;
+static std::vector<source_entry_t>& get_source_registry(void)
+{
+ static bool src_reg = false;
+ static std::vector<source_entry_t> s_registry;
- if(!src_reg) {
+ if (!src_reg) {
#ifdef ALSA_FOUND
s_registry.push_back(register_source(REG_PRIO_HIGH, "alsa", alsa_source_fcn));
#endif /* ALSA_FOUND */
@@ -50,7 +49,8 @@ namespace gr {
#endif /* OSS_FOUND */
#ifdef PORTAUDIO_FOUND
- s_registry.push_back(register_source(REG_PRIO_MED, "portaudio", portaudio_source_fcn));
+ s_registry.push_back(
+ register_source(REG_PRIO_MED, "portaudio", portaudio_source_fcn));
#endif /* PORTAUDIO_FOUND */
#ifdef JACK_FOUND
@@ -62,23 +62,23 @@ namespace gr {
#endif /* OSX_FOUND */
#ifdef WIN32_FOUND
- s_registry.push_back(register_source(REG_PRIO_HIGH, "windows", windows_source_fcn));
+ s_registry.push_back(
+ register_source(REG_PRIO_HIGH, "windows", windows_source_fcn));
#endif /* WIN32_FOUND */
src_reg = true;
- }
+ }
- return s_registry;
- }
+ return s_registry;
+}
- static std::vector<sink_entry_t> &
- get_sink_registry(void)
- {
- static bool snk_reg = false;
- static std::vector<sink_entry_t> s_registry;
+static std::vector<sink_entry_t>& get_sink_registry(void)
+{
+ static bool snk_reg = false;
+ static std::vector<sink_entry_t> s_registry;
- if(!snk_reg) {
+ if (!snk_reg) {
#if ALSA_FOUND
s_registry.push_back(register_sink(REG_PRIO_HIGH, "alsa", alsa_sink_fcn));
#endif /* ALSA_FOUND */
@@ -88,7 +88,8 @@ namespace gr {
#endif /* OSS_FOUND */
#if PORTAUDIO_FOUND
- s_registry.push_back(register_sink(REG_PRIO_MED, "portaudio", portaudio_sink_fcn));
+ s_registry.push_back(
+ register_sink(REG_PRIO_MED, "portaudio", portaudio_sink_fcn));
#endif /* PORTAUDIO_FOUND */
#if JACK_FOUND
@@ -104,109 +105,100 @@ namespace gr {
#endif /* WIN32_FOUND */
snk_reg = true;
- }
-
- return s_registry;
- }
-
- /***********************************************************************
- * Register functions
- **********************************************************************/
- source_entry_t
- register_source(reg_prio_type prio,
- const std::string &arch,
- source_factory_t source)
- {
- source_entry_t entry;
- entry.prio = prio;
- entry.arch = arch;
- entry.source = source;
- return entry;
- }
-
- sink_entry_t
- register_sink(reg_prio_type prio,
- const std::string &arch,
- sink_factory_t sink)
- {
- sink_entry_t entry;
- entry.prio = prio;
- entry.arch = arch;
- entry.sink = sink;
- return entry;
- }
-
- /***********************************************************************
- * Factory functions
- **********************************************************************/
- static std::string default_arch_name(void)
- {
- return prefs::singleton()->get_string("audio", "audio_module", "auto");
}
- static void do_arch_warning(const std::string &arch)
- {
- if(arch == "auto")
- return; //no warning when arch not specified
- std::cerr << "Could not find audio architecture \"" << arch
- << "\" in registry." << std::endl;
- std::cerr << " Defaulting to the first available architecture..." << std::endl;
- }
-
- source::sptr
- source::make(int sampling_rate,
- const std::string device_name,
- bool ok_to_block)
- {
- gr::logger_ptr logger, debug_logger;
- configure_default_loggers(logger, debug_logger, "audio source");
-
- if(get_source_registry().empty()) {
+ return s_registry;
+}
+
+/***********************************************************************
+ * Register functions
+ **********************************************************************/
+source_entry_t
+register_source(reg_prio_type prio, const std::string& arch, source_factory_t source)
+{
+ source_entry_t entry;
+ entry.prio = prio;
+ entry.arch = arch;
+ entry.source = source;
+ return entry;
+}
+
+sink_entry_t
+register_sink(reg_prio_type prio, const std::string& arch, sink_factory_t sink)
+{
+ sink_entry_t entry;
+ entry.prio = prio;
+ entry.arch = arch;
+ entry.sink = sink;
+ return entry;
+}
+
+/***********************************************************************
+ * Factory functions
+ **********************************************************************/
+static std::string default_arch_name(void)
+{
+ return prefs::singleton()->get_string("audio", "audio_module", "auto");
+}
+
+static void do_arch_warning(const std::string& arch)
+{
+ if (arch == "auto")
+ return; // no warning when arch not specified
+ std::cerr << "Could not find audio architecture \"" << arch << "\" in registry."
+ << std::endl;
+ std::cerr << " Defaulting to the first available architecture..." << std::endl;
+}
+
+source::sptr
+source::make(int sampling_rate, const std::string device_name, bool ok_to_block)
+{
+ gr::logger_ptr logger, debug_logger;
+ configure_default_loggers(logger, debug_logger, "audio source");
+
+ if (get_source_registry().empty()) {
throw std::runtime_error("no available audio source factories");
- }
+ }
- std::string arch = default_arch_name();
- source_entry_t entry = get_source_registry().front();
+ std::string arch = default_arch_name();
+ source_entry_t entry = get_source_registry().front();
- BOOST_FOREACH(const source_entry_t &e, get_source_registry()) {
- if(e.prio > entry.prio)
- entry = e; //entry is highest prio
- if(arch != e.arch)
- continue; //continue when no match
+ BOOST_FOREACH (const source_entry_t& e, get_source_registry()) {
+ if (e.prio > entry.prio)
+ entry = e; // entry is highest prio
+ if (arch != e.arch)
+ continue; // continue when no match
return e.source(sampling_rate, device_name, ok_to_block);
- }
-
- GR_LOG_INFO(logger, boost::format("Audio source arch: %1%") % (entry.arch));
- return entry.source(sampling_rate, device_name, ok_to_block);
}
- sink::sptr
- sink::make(int sampling_rate,
- const std::string device_name,
- bool ok_to_block)
- {
- gr::logger_ptr logger, debug_logger;
- configure_default_loggers(logger, debug_logger, "audio source");
+ GR_LOG_INFO(logger, boost::format("Audio source arch: %1%") % (entry.arch));
+ return entry.source(sampling_rate, device_name, ok_to_block);
+}
- if(get_sink_registry().empty()) {
+sink::sptr sink::make(int sampling_rate, const std::string device_name, bool ok_to_block)
+{
+ gr::logger_ptr logger, debug_logger;
+ configure_default_loggers(logger, debug_logger, "audio source");
+
+ if (get_sink_registry().empty()) {
throw std::runtime_error("no available audio sink factories");
- }
+ }
- std::string arch = default_arch_name();
- sink_entry_t entry = get_sink_registry().front();
+ std::string arch = default_arch_name();
+ sink_entry_t entry = get_sink_registry().front();
- BOOST_FOREACH(const sink_entry_t &e, get_sink_registry()) {
- if(e.prio > entry.prio)
- entry = e; //entry is highest prio
- if(arch != e.arch)
- continue; //continue when no match
+ BOOST_FOREACH (const sink_entry_t& e, get_sink_registry()) {
+ if (e.prio > entry.prio)
+ entry = e; // entry is highest prio
+ if (arch != e.arch)
+ continue; // continue when no match
return e.sink(sampling_rate, device_name, ok_to_block);
- }
-
- do_arch_warning(arch);
- GR_LOG_INFO(logger, boost::format("Audio sink arch: %1%") % (entry.arch));
- return entry.sink(sampling_rate, device_name, ok_to_block);
}
- } /* namespace audio */
+ do_arch_warning(arch);
+ GR_LOG_INFO(logger, boost::format("Audio sink arch: %1%") % (entry.arch));
+ return entry.sink(sampling_rate, device_name, ok_to_block);
+}
+
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/audio_registry.h b/gr-audio/lib/audio_registry.h
index d18d5c5387..ad76106787 100644
--- a/gr-audio/lib/audio_registry.h
+++ b/gr-audio/lib/audio_registry.h
@@ -27,90 +27,73 @@
#include <string>
namespace gr {
- namespace audio {
-
- typedef source::sptr(*source_factory_t)(int, const std::string &, bool);
- typedef sink::sptr(*sink_factory_t)(int, const std::string &, bool);
-
- enum reg_prio_type {
- REG_PRIO_LOW = 100,
- REG_PRIO_MED = 200,
- REG_PRIO_HIGH = 300
- };
-
- struct source_entry_t {
- reg_prio_type prio;
- std::string arch;
- source_factory_t source;
- };
-
- struct sink_entry_t
- {
- reg_prio_type prio;
- std::string arch;
- sink_factory_t sink;
- };
-
- source_entry_t register_source(reg_prio_type prio, const std::string &arch,
- source_factory_t source);
- sink_entry_t register_sink(reg_prio_type prio, const std::string &arch,
- sink_factory_t sink);
+namespace audio {
+
+typedef source::sptr (*source_factory_t)(int, const std::string&, bool);
+typedef sink::sptr (*sink_factory_t)(int, const std::string&, bool);
+
+enum reg_prio_type { REG_PRIO_LOW = 100, REG_PRIO_MED = 200, REG_PRIO_HIGH = 300 };
+
+struct source_entry_t {
+ reg_prio_type prio;
+ std::string arch;
+ source_factory_t source;
+};
+
+struct sink_entry_t {
+ reg_prio_type prio;
+ std::string arch;
+ sink_factory_t sink;
+};
+
+source_entry_t
+register_source(reg_prio_type prio, const std::string& arch, source_factory_t source);
+sink_entry_t
+register_sink(reg_prio_type prio, const std::string& arch, sink_factory_t sink);
#ifdef ALSA_FOUND
- source::sptr alsa_source_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block);
- sink::sptr alsa_sink_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block);
+source::sptr
+alsa_source_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block);
+sink::sptr
+alsa_sink_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block);
#endif /* ALSA_FOUND */
#ifdef OSS_FOUND
- source::sptr oss_source_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block);
- sink::sptr oss_sink_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block);
+source::sptr
+oss_source_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block);
+sink::sptr
+oss_sink_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block);
#endif /* OSS_FOUND */
#ifdef PORTAUDIO_FOUND
- source::sptr portaudio_source_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block);
- sink::sptr portaudio_sink_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block);
+source::sptr
+portaudio_source_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block);
+sink::sptr
+portaudio_sink_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block);
#endif /* PORTAUDIO_FOUND */
#ifdef JACK_FOUND
- source::sptr jack_source_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block);
- sink::sptr jack_sink_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block);
+source::sptr
+jack_source_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block);
+sink::sptr
+jack_sink_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block);
#endif /* JACK_FOUND */
#ifdef OSX_FOUND
- source::sptr osx_source_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block);
- sink::sptr osx_sink_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block);
+source::sptr
+osx_source_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block);
+sink::sptr
+osx_sink_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block);
#endif /* OSX_FOUND */
#ifdef WIN32_FOUND
- source::sptr windows_source_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block);
- sink::sptr windows_sink_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block);
+source::sptr
+windows_source_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block);
+sink::sptr
+windows_sink_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block);
#endif /* WIN32_FOUND */
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_GR_AUDIO_REGISTRY_H */
diff --git a/gr-audio/lib/jack/jack_sink.cc b/gr-audio/lib/jack/jack_sink.cc
index c82c576174..7a7e14706d 100644
--- a/gr-audio/lib/jack/jack_sink.cc
+++ b/gr-audio/lib/jack/jack_sink.cc
@@ -38,229 +38,221 @@
#endif
namespace gr {
- namespace audio {
-
- sink::sptr
- jack_sink_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block)
- {
- return sink::sptr
- (new jack_sink(sampling_rate, device_name, ok_to_block));
- }
-
- typedef jack_default_audio_sample_t sample_t;
-
- // Number of jack buffers in the ringbuffer
- // TODO: make it to match at least the quantity of items passed by work()
- static const unsigned int N_BUFFERS = 16;
-
- static std::string
- default_device_name()
- {
- return prefs::singleton()->get_string
- ("audio_jack", "default_output_device", "gr_sink");
- }
-
- int
- jack_sink_process(jack_nframes_t nframes, void *arg)
- {
- jack_sink *self = (jack_sink *)arg;
- unsigned int read_size = nframes*sizeof(sample_t);
-
- for(int i = 0; i < self->d_portcount; i++) {
-
- if(jack_ringbuffer_read_space(self->d_ringbuffer[i]) < read_size) {
- self->d_nunderuns++;
- // FIXME: move this fputs out, we shouldn't use blocking calls in process()
- fputs("jU", stderr);
- return 0;
+namespace audio {
+
+sink::sptr
+jack_sink_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block)
+{
+ return sink::sptr(new jack_sink(sampling_rate, device_name, ok_to_block));
+}
+
+typedef jack_default_audio_sample_t sample_t;
+
+// Number of jack buffers in the ringbuffer
+// TODO: make it to match at least the quantity of items passed by work()
+static const unsigned int N_BUFFERS = 16;
+
+static std::string default_device_name()
+{
+ return prefs::singleton()->get_string(
+ "audio_jack", "default_output_device", "gr_sink");
+}
+
+int jack_sink_process(jack_nframes_t nframes, void* arg)
+{
+ jack_sink* self = (jack_sink*)arg;
+ unsigned int read_size = nframes * sizeof(sample_t);
+
+ for (int i = 0; i < self->d_portcount; i++) {
+
+ if (jack_ringbuffer_read_space(self->d_ringbuffer[i]) < read_size) {
+ self->d_nunderuns++;
+ // FIXME: move this fputs out, we shouldn't use blocking calls in process()
+ fputs("jU", stderr);
+ return 0;
}
- char *buffer = (char *)jack_port_get_buffer(self->d_jack_output_port[i], nframes);
+ char* buffer = (char*)jack_port_get_buffer(self->d_jack_output_port[i], nframes);
jack_ringbuffer_read(self->d_ringbuffer[i], buffer, read_size);
- }
+ }
#ifndef NO_PTHREAD
- // Tell the sink thread there is room in the ringbuffer.
- // If it is already running, the lock will not be available.
- // We can't wait here in the process() thread, but we don't
- // need to signal in that case, because the sink thread will
- // check for room availability.
- if(pthread_mutex_trylock (&self->d_jack_process_lock) == 0) {
+ // Tell the sink thread there is room in the ringbuffer.
+ // If it is already running, the lock will not be available.
+ // We can't wait here in the process() thread, but we don't
+ // need to signal in that case, because the sink thread will
+ // check for room availability.
+ if (pthread_mutex_trylock(&self->d_jack_process_lock) == 0) {
pthread_cond_signal(&self->d_ringbuffer_ready);
pthread_mutex_unlock(&self->d_jack_process_lock);
- }
-#endif
-
- return 0;
}
+#endif
- // ----------------------------------------------------------------
-
- jack_sink::jack_sink(int sampling_rate,
- const std::string device_name,
- bool ok_to_block)
- : sync_block("audio_jack_sink",
- io_signature::make(0, 0, 0),
- io_signature::make(0, 0, 0)),
- d_sampling_rate(sampling_rate),
- d_device_name(device_name.empty() ? default_device_name() : device_name),
- d_ok_to_block(ok_to_block),
- d_jack_client(0),
- d_portcount(0),
- d_jack_output_port(),
- d_ringbuffer(),
- d_nunderuns(0)
- {
+ return 0;
+}
+
+// ----------------------------------------------------------------
+
+jack_sink::jack_sink(int sampling_rate, const std::string device_name, bool ok_to_block)
+ : sync_block(
+ "audio_jack_sink", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)),
+ d_sampling_rate(sampling_rate),
+ d_device_name(device_name.empty() ? default_device_name() : device_name),
+ d_ok_to_block(ok_to_block),
+ d_jack_client(0),
+ d_portcount(0),
+ d_jack_output_port(),
+ d_ringbuffer(),
+ d_nunderuns(0)
+{
#ifndef NO_PTHREAD
- pthread_cond_init(&d_ringbuffer_ready, NULL);;
- pthread_mutex_init(&d_jack_process_lock, NULL);
+ pthread_cond_init(&d_ringbuffer_ready, NULL);
+ ;
+ pthread_mutex_init(&d_jack_process_lock, NULL);
#endif
- // try to become a client of the JACK server
- jack_options_t options = JackNullOption;
- jack_status_t status;
- const char *server_name = NULL;
- if((d_jack_client = jack_client_open(d_device_name.c_str(),
- options, &status,
- server_name)) == NULL) {
- GR_LOG_ERROR(d_logger, boost::format("[%1%]: jack server not running?") \
- % d_device_name);
+ // try to become a client of the JACK server
+ jack_options_t options = JackNullOption;
+ jack_status_t status;
+ const char* server_name = NULL;
+ if ((d_jack_client = jack_client_open(
+ d_device_name.c_str(), options, &status, server_name)) == NULL) {
+ GR_LOG_ERROR(d_logger,
+ boost::format("[%1%]: jack server not running?") % d_device_name);
throw std::runtime_error("audio_jack_sink");
- }
+ }
- // tell the JACK server to call `jack_sink_process()' whenever
- // there is work to be done.
- jack_set_process_callback(d_jack_client, &jack_sink_process, (void*)this);
+ // tell the JACK server to call `jack_sink_process()' whenever
+ // there is work to be done.
+ jack_set_process_callback(d_jack_client, &jack_sink_process, (void*)this);
- // tell the JACK server to call `jack_shutdown()' if
- // it ever shuts down, either entirely, or if it
- // just decides to stop calling us.
+ // tell the JACK server to call `jack_shutdown()' if
+ // it ever shuts down, either entirely, or if it
+ // just decides to stop calling us.
- //jack_on_shutdown (d_jack_client, &jack_shutdown, (void*)this);
+ // jack_on_shutdown (d_jack_client, &jack_shutdown, (void*)this);
- d_jack_buffer_size = jack_get_buffer_size(d_jack_client);
+ d_jack_buffer_size = jack_get_buffer_size(d_jack_client);
- set_output_multiple(d_jack_buffer_size);
+ set_output_multiple(d_jack_buffer_size);
- assert(sizeof(float)==sizeof(sample_t));
- // Real number of outputs is set in check_topology
- set_input_signature(io_signature::make(1, MAX_PORTS, sizeof(sample_t)));
+ assert(sizeof(float) == sizeof(sample_t));
+ // Real number of outputs is set in check_topology
+ set_input_signature(io_signature::make(1, MAX_PORTS, sizeof(sample_t)));
- jack_nframes_t sample_rate = jack_get_sample_rate(d_jack_client);
+ jack_nframes_t sample_rate = jack_get_sample_rate(d_jack_client);
- if((jack_nframes_t)sampling_rate != sample_rate) {
- GR_LOG_INFO(d_logger, boost::format("[%1%]: unable to support sampling rate %2%\n\tCard requested %3% instead.") \
- % d_device_name % sampling_rate % d_sampling_rate);
- }
+ if ((jack_nframes_t)sampling_rate != sample_rate) {
+ GR_LOG_INFO(d_logger,
+ boost::format("[%1%]: unable to support sampling rate %2%\n\tCard "
+ "requested %3% instead.") %
+ d_device_name % sampling_rate % d_sampling_rate);
}
+}
- bool
- jack_sink::check_topology (int ninputs, int noutputs)
- {
- if(ninputs > MAX_PORTS)
+bool jack_sink::check_topology(int ninputs, int noutputs)
+{
+ if (ninputs > MAX_PORTS)
return false;
- d_portcount = ninputs; // # of channels we're really using
+ d_portcount = ninputs; // # of channels we're really using
- // Create ports and ringbuffers
- for(int i = 0; i < d_portcount; i++) {
+ // Create ports and ringbuffers
+ for (int i = 0; i < d_portcount; i++) {
std::string portname("out" + boost::to_string(i));
- d_jack_output_port[i] =
- jack_port_register(d_jack_client, portname.c_str(),
- JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+ d_jack_output_port[i] = jack_port_register(d_jack_client,
+ portname.c_str(),
+ JACK_DEFAULT_AUDIO_TYPE,
+ JackPortIsOutput,
+ 0);
d_ringbuffer[i] =
- jack_ringbuffer_create(N_BUFFERS*d_jack_buffer_size*sizeof(sample_t));
- if(d_ringbuffer[i] == NULL)
- bail("jack_ringbuffer_create failed", 0);
- }
+ jack_ringbuffer_create(N_BUFFERS * d_jack_buffer_size * sizeof(sample_t));
+ if (d_ringbuffer[i] == NULL)
+ bail("jack_ringbuffer_create failed", 0);
+ }
- // tell the JACK server that we are ready to roll
- if(jack_activate (d_jack_client))
+ // tell the JACK server that we are ready to roll
+ if (jack_activate(d_jack_client))
throw std::runtime_error("audio_jack_sink");
- return true;
- }
+ return true;
+}
- jack_sink::~jack_sink()
- {
- jack_client_close(d_jack_client);
+jack_sink::~jack_sink()
+{
+ jack_client_close(d_jack_client);
- for(int i = 0; i < d_portcount; i++)
+ for (int i = 0; i < d_portcount; i++)
jack_ringbuffer_free(d_ringbuffer[i]);
- }
+}
- int
- jack_sink::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
+int jack_sink::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
- const float **in = (const float **)&input_items[0];
+ const float** in = (const float**)&input_items[0];
- for(int i = 0; i < d_portcount; i++) {
+ for (int i = 0; i < d_portcount; i++) {
int k = 0;
// write_size and work_size are in bytes
- int work_size = noutput_items*sizeof(sample_t);
+ int work_size = noutput_items * sizeof(sample_t);
unsigned int write_size;
- while(work_size > 0) {
- unsigned int write_space; // bytes
+ while (work_size > 0) {
+ unsigned int write_space; // bytes
#ifdef NO_PTHREAD
- while((write_space=jack_ringbuffer_write_space(d_ringbuffer[i])) <
- d_jack_buffer_size*sizeof(sample_t)) {
- usleep(1000000*((d_jack_buffer_size-write_space/sizeof(sample_t))/d_sampling_rate));
- }
+ while ((write_space = jack_ringbuffer_write_space(d_ringbuffer[i])) <
+ d_jack_buffer_size * sizeof(sample_t)) {
+ usleep(1000000 * ((d_jack_buffer_size - write_space / sizeof(sample_t)) /
+ d_sampling_rate));
+ }
#else
- // JACK actually requires POSIX
+ // JACK actually requires POSIX
- pthread_mutex_lock(&d_jack_process_lock);
- while((write_space = jack_ringbuffer_write_space(d_ringbuffer[i])) <
- d_jack_buffer_size*sizeof(sample_t)) {
+ pthread_mutex_lock(&d_jack_process_lock);
+ while ((write_space = jack_ringbuffer_write_space(d_ringbuffer[i])) <
+ d_jack_buffer_size * sizeof(sample_t)) {
- // wait until jack_sink_process() signals more room
- pthread_cond_wait(&d_ringbuffer_ready, &d_jack_process_lock);
- }
- pthread_mutex_unlock(&d_jack_process_lock);
+ // wait until jack_sink_process() signals more room
+ pthread_cond_wait(&d_ringbuffer_ready, &d_jack_process_lock);
+ }
+ pthread_mutex_unlock(&d_jack_process_lock);
#endif
- write_space -= write_space%(d_jack_buffer_size*sizeof(sample_t));
- write_size = std::min(write_space, (unsigned int)work_size);
+ write_space -= write_space % (d_jack_buffer_size * sizeof(sample_t));
+ write_size = std::min(write_space, (unsigned int)work_size);
- if(jack_ringbuffer_write(d_ringbuffer[i], (char *) &(in[i][k]),
- write_size) < write_size) {
- bail("jack_ringbuffer_write failed", 0);
- }
- work_size -= write_size;
- k += write_size/sizeof(sample_t);
+ if (jack_ringbuffer_write(d_ringbuffer[i], (char*)&(in[i][k]), write_size) <
+ write_size) {
+ bail("jack_ringbuffer_write failed", 0);
+ }
+ work_size -= write_size;
+ k += write_size / sizeof(sample_t);
}
- }
-
- return noutput_items;
}
- void
- jack_sink::output_error_msg(const char *msg, int err)
- {
- GR_LOG_ERROR(d_logger, boost::format("[%1%]: %2%: %3%") \
- % d_device_name % msg % err);
- }
+ return noutput_items;
+}
- void
- jack_sink::bail(const char *msg, int err)
- {
- output_error_msg(msg, err);
- throw std::runtime_error("audio_jack_sink");
- }
+void jack_sink::output_error_msg(const char* msg, int err)
+{
+ GR_LOG_ERROR(d_logger, boost::format("[%1%]: %2%: %3%") % d_device_name % msg % err);
+}
+
+void jack_sink::bail(const char* msg, int err)
+{
+ output_error_msg(msg, err);
+ throw std::runtime_error("audio_jack_sink");
+}
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/jack/jack_sink.h b/gr-audio/lib/jack/jack_sink.h
index 23f5d298e5..80fc7312d1 100644
--- a/gr-audio/lib/jack/jack_sink.h
+++ b/gr-audio/lib/jack/jack_sink.h
@@ -29,60 +29,58 @@
#include <stdexcept>
namespace gr {
- namespace audio {
+namespace audio {
- int sink_process(jack_nframes_t nframes, void *arg);
+int sink_process(jack_nframes_t nframes, void* arg);
- /*!
- * \brief audio sink using JACK
- * \ingroup audio_blk
- *
- * The sink has one input stream of floats.
- *
- * Input samples must be in the range [-1,1].
- */
- class jack_sink : public sink
- {
- friend int jack_sink_process(jack_nframes_t nframes, void *arg);
+/*!
+ * \brief audio sink using JACK
+ * \ingroup audio_blk
+ *
+ * The sink has one input stream of floats.
+ *
+ * Input samples must be in the range [-1,1].
+ */
+class jack_sink : public sink
+{
+ friend int jack_sink_process(jack_nframes_t nframes, void* arg);
- // typedef for pointer to class work method
- typedef int (jack_sink::*work_t)(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
+ // typedef for pointer to class work method
+ typedef int (jack_sink::*work_t)(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
- unsigned int d_sampling_rate;
- std::string d_device_name;
- bool d_ok_to_block;
+ unsigned int d_sampling_rate;
+ std::string d_device_name;
+ bool d_ok_to_block;
- jack_client_t *d_jack_client;
- static const int MAX_PORTS = 10;
- int d_portcount;
- jack_port_t *d_jack_output_port[MAX_PORTS];
- jack_ringbuffer_t *d_ringbuffer[MAX_PORTS];
- jack_nframes_t d_jack_buffer_size;
- pthread_cond_t d_ringbuffer_ready;
- pthread_mutex_t d_jack_process_lock;
+ jack_client_t* d_jack_client;
+ static const int MAX_PORTS = 10;
+ int d_portcount;
+ jack_port_t* d_jack_output_port[MAX_PORTS];
+ jack_ringbuffer_t* d_ringbuffer[MAX_PORTS];
+ jack_nframes_t d_jack_buffer_size;
+ pthread_cond_t d_ringbuffer_ready;
+ pthread_mutex_t d_jack_process_lock;
- // random stats
- int d_nunderuns; // count of underruns
+ // random stats
+ int d_nunderuns; // count of underruns
- void output_error_msg(const char *msg, int err);
- void bail(const char *msg, int err);
+ void output_error_msg(const char* msg, int err);
+ void bail(const char* msg, int err);
- public:
- jack_sink(int sampling_rate,
- const std::string device_name,
- bool ok_to_block);
- ~jack_sink();
+public:
+ jack_sink(int sampling_rate, const std::string device_name, bool ok_to_block);
+ ~jack_sink();
- bool check_topology(int ninputs, int noutputs);
+ bool check_topology(int ninputs, int noutputs);
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_AUDIO_JACK_SINK_H */
diff --git a/gr-audio/lib/jack/jack_source.cc b/gr-audio/lib/jack/jack_source.cc
index 6ca93989c4..e24e1af637 100644
--- a/gr-audio/lib/jack/jack_source.cc
+++ b/gr-audio/lib/jack/jack_source.cc
@@ -38,229 +38,222 @@
#endif
namespace gr {
- namespace audio {
-
- source::sptr
- jack_source_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block)
- {
- return source::sptr
- (new jack_source(sampling_rate, device_name, ok_to_block));
- }
-
- typedef jack_default_audio_sample_t sample_t;
-
- // Number of jack buffers in the ringbuffer
- // TODO: make it to match at least the quantity of items passed to work()
- static const unsigned int N_BUFFERS = 16;
-
- static std::string
- default_device_name()
- {
- return prefs::singleton()->get_string
- ("audio_jack", "default_input_device", "gr_source");
- }
-
- int
- jack_source_process(jack_nframes_t nframes, void *arg)
- {
- jack_source *self = (jack_source *)arg;
- unsigned int write_size = nframes*sizeof(sample_t);
-
- for(int i = 0; i < self->d_portcount; i++) {
- if(jack_ringbuffer_write_space (self->d_ringbuffer[i]) < write_size) {
- self->d_noverruns++;
- // FIXME: move this fputs out, we shouldn't use blocking calls in process()
- fputs ("jO", stderr);
- return 0;
+namespace audio {
+
+source::sptr
+jack_source_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block)
+{
+ return source::sptr(new jack_source(sampling_rate, device_name, ok_to_block));
+}
+
+typedef jack_default_audio_sample_t sample_t;
+
+// Number of jack buffers in the ringbuffer
+// TODO: make it to match at least the quantity of items passed to work()
+static const unsigned int N_BUFFERS = 16;
+
+static std::string default_device_name()
+{
+ return prefs::singleton()->get_string(
+ "audio_jack", "default_input_device", "gr_source");
+}
+
+int jack_source_process(jack_nframes_t nframes, void* arg)
+{
+ jack_source* self = (jack_source*)arg;
+ unsigned int write_size = nframes * sizeof(sample_t);
+
+ for (int i = 0; i < self->d_portcount; i++) {
+ if (jack_ringbuffer_write_space(self->d_ringbuffer[i]) < write_size) {
+ self->d_noverruns++;
+ // FIXME: move this fputs out, we shouldn't use blocking calls in process()
+ fputs("jO", stderr);
+ return 0;
}
- char *buffer = (char *)jack_port_get_buffer(self->d_jack_input_port[i], nframes);
+ char* buffer = (char*)jack_port_get_buffer(self->d_jack_input_port[i], nframes);
- jack_ringbuffer_write (self->d_ringbuffer[i], buffer, write_size);
- }
+ jack_ringbuffer_write(self->d_ringbuffer[i], buffer, write_size);
+ }
#ifndef NO_PTHREAD
- // Tell the source thread there is data in the ringbuffer.
- // If it is already running, the lock will not be available.
- // We can't wait here in the process() thread, but we don't
- // need to signal in that case, because the source thread will
- // check for data availability.
+ // Tell the source thread there is data in the ringbuffer.
+ // If it is already running, the lock will not be available.
+ // We can't wait here in the process() thread, but we don't
+ // need to signal in that case, because the source thread will
+ // check for data availability.
- if(pthread_mutex_trylock(&self->d_jack_process_lock) == 0) {
+ if (pthread_mutex_trylock(&self->d_jack_process_lock) == 0) {
pthread_cond_signal(&self->d_ringbuffer_ready);
pthread_mutex_unlock(&self->d_jack_process_lock);
- }
-#endif
-
- return 0;
}
+#endif
- // ----------------------------------------------------------------
-
- jack_source::jack_source(int sampling_rate,
- const std::string device_name,
- bool ok_to_block)
- : sync_block("audio_jack_source",
- io_signature::make(0, 0, 0),
- io_signature::make(0, 0, 0)),
- d_sampling_rate(sampling_rate),
- d_device_name(device_name.empty() ? default_device_name() : device_name),
- d_ok_to_block(ok_to_block),
- d_jack_client(0),
- d_portcount(0),
- d_jack_input_port(),
- d_ringbuffer(),
- d_noverruns(0)
- {
+ return 0;
+}
+
+// ----------------------------------------------------------------
+
+jack_source::jack_source(int sampling_rate,
+ const std::string device_name,
+ bool ok_to_block)
+ : sync_block(
+ "audio_jack_source", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)),
+ d_sampling_rate(sampling_rate),
+ d_device_name(device_name.empty() ? default_device_name() : device_name),
+ d_ok_to_block(ok_to_block),
+ d_jack_client(0),
+ d_portcount(0),
+ d_jack_input_port(),
+ d_ringbuffer(),
+ d_noverruns(0)
+{
#ifndef NO_PTHREAD
- pthread_cond_init(&d_ringbuffer_ready, NULL);;
- pthread_mutex_init(&d_jack_process_lock, NULL);
+ pthread_cond_init(&d_ringbuffer_ready, NULL);
+ ;
+ pthread_mutex_init(&d_jack_process_lock, NULL);
#endif
- // try to become a client of the JACK server
- jack_options_t options = JackNullOption;
- jack_status_t status;
- const char *server_name = NULL;
- if((d_jack_client = jack_client_open(d_device_name.c_str(),
- options, &status,
- server_name)) == NULL) {
- GR_LOG_ERROR(d_logger, boost::format("[%1%]: jack server not running?") \
- % d_device_name);
+ // try to become a client of the JACK server
+ jack_options_t options = JackNullOption;
+ jack_status_t status;
+ const char* server_name = NULL;
+ if ((d_jack_client = jack_client_open(
+ d_device_name.c_str(), options, &status, server_name)) == NULL) {
+ GR_LOG_ERROR(d_logger,
+ boost::format("[%1%]: jack server not running?") % d_device_name);
throw std::runtime_error("audio_jack_source");
- }
+ }
- // tell the JACK server to call `jack_source_process()' whenever
- // there is work to be done.
- jack_set_process_callback(d_jack_client, &jack_source_process, (void*)this);
+ // tell the JACK server to call `jack_source_process()' whenever
+ // there is work to be done.
+ jack_set_process_callback(d_jack_client, &jack_source_process, (void*)this);
- // tell the JACK server to call `jack_shutdown()' if
- // it ever shuts down, either entirely, or if it
- // just decides to stop calling us.
+ // tell the JACK server to call `jack_shutdown()' if
+ // it ever shuts down, either entirely, or if it
+ // just decides to stop calling us.
- //jack_on_shutdown (d_jack_client, &jack_shutdown, (void*)this);
+ // jack_on_shutdown (d_jack_client, &jack_shutdown, (void*)this);
- d_jack_buffer_size = jack_get_buffer_size(d_jack_client);
+ d_jack_buffer_size = jack_get_buffer_size(d_jack_client);
- set_output_multiple(d_jack_buffer_size);
+ set_output_multiple(d_jack_buffer_size);
- assert(sizeof(float)==sizeof(sample_t));
- set_output_signature(io_signature::make(1, MAX_PORTS, sizeof(sample_t)));
+ assert(sizeof(float) == sizeof(sample_t));
+ set_output_signature(io_signature::make(1, MAX_PORTS, sizeof(sample_t)));
- jack_nframes_t sample_rate = jack_get_sample_rate(d_jack_client);
+ jack_nframes_t sample_rate = jack_get_sample_rate(d_jack_client);
- if((jack_nframes_t)sampling_rate != sample_rate) {
- GR_LOG_INFO(d_logger, boost::format("[%1%]: unable to support sampling rate %2%\n\tCard requested %3% instead.") \
- % d_device_name % sampling_rate % d_sampling_rate);
- }
+ if ((jack_nframes_t)sampling_rate != sample_rate) {
+ GR_LOG_INFO(d_logger,
+ boost::format("[%1%]: unable to support sampling rate %2%\n\tCard "
+ "requested %3% instead.") %
+ d_device_name % sampling_rate % d_sampling_rate);
}
+}
- bool
- jack_source::check_topology(int ninputs, int noutputs)
- {
+bool jack_source::check_topology(int ninputs, int noutputs)
+{
- if(noutputs > MAX_PORTS)
+ if (noutputs > MAX_PORTS)
return false;
- d_portcount = noutputs; // # of channels we're really using
+ d_portcount = noutputs; // # of channels we're really using
- // Create ports and ringbuffers
- for(int i = 0; i < d_portcount; i++) {
+ // Create ports and ringbuffers
+ for (int i = 0; i < d_portcount; i++) {
std::string portname("in" + boost::to_string(i));
- d_jack_input_port[i] = jack_port_register(d_jack_client, portname.c_str(),
- JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+ d_jack_input_port[i] = jack_port_register(
+ d_jack_client, portname.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
- d_ringbuffer[i] = jack_ringbuffer_create(N_BUFFERS*d_jack_buffer_size*sizeof(sample_t));
- if(d_ringbuffer[i] == NULL)
- bail("jack_ringbuffer_create failed", 0);
- }
+ d_ringbuffer[i] =
+ jack_ringbuffer_create(N_BUFFERS * d_jack_buffer_size * sizeof(sample_t));
+ if (d_ringbuffer[i] == NULL)
+ bail("jack_ringbuffer_create failed", 0);
+ }
- // tell the JACK server that we are ready to roll
- if(jack_activate (d_jack_client))
+ // tell the JACK server that we are ready to roll
+ if (jack_activate(d_jack_client))
throw std::runtime_error("audio_jack_source");
- return true;
- }
+ return true;
+}
- jack_source::~jack_source()
- {
- jack_client_close(d_jack_client);
+jack_source::~jack_source()
+{
+ jack_client_close(d_jack_client);
- for(int i = 0; i < d_portcount; i++)
+ for (int i = 0; i < d_portcount; i++)
jack_ringbuffer_free(d_ringbuffer[i]);
- }
+}
- int
- jack_source::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
+int jack_source::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
- const float **out = (const float **)&output_items[0];
+ const float** out = (const float**)&output_items[0];
- // Minimize latency
- noutput_items = std::min (noutput_items, (int)d_jack_buffer_size);
+ // Minimize latency
+ noutput_items = std::min(noutput_items, (int)d_jack_buffer_size);
- for(int i = 0; i < d_portcount; i++) {
+ for (int i = 0; i < d_portcount; i++) {
int k = 0;
// read_size and work_size are in bytes
unsigned int read_size;
- int work_size = noutput_items*sizeof(sample_t);
+ int work_size = noutput_items * sizeof(sample_t);
- while(work_size > 0) {
- unsigned int read_space; // bytes
+ while (work_size > 0) {
+ unsigned int read_space; // bytes
#ifdef NO_PTHREAD
- while((read_space=jack_ringbuffer_read_space (d_ringbuffer[i])) <
- d_jack_buffer_size*sizeof(sample_t)) {
- usleep(1000000*((d_jack_buffer_size-read_space/sizeof(sample_t))/d_sampling_rate));
- }
+ while ((read_space = jack_ringbuffer_read_space(d_ringbuffer[i])) <
+ d_jack_buffer_size * sizeof(sample_t)) {
+ usleep(1000000 * ((d_jack_buffer_size - read_space / sizeof(sample_t)) /
+ d_sampling_rate));
+ }
#else
- // JACK actually requires POSIX
- pthread_mutex_lock(&d_jack_process_lock);
- while((read_space = jack_ringbuffer_read_space(d_ringbuffer[i])) <
- d_jack_buffer_size*sizeof(sample_t)) {
- // wait until jack_source_process() signals more data
- pthread_cond_wait(&d_ringbuffer_ready, &d_jack_process_lock);
- }
- pthread_mutex_unlock(&d_jack_process_lock);
+ // JACK actually requires POSIX
+ pthread_mutex_lock(&d_jack_process_lock);
+ while ((read_space = jack_ringbuffer_read_space(d_ringbuffer[i])) <
+ d_jack_buffer_size * sizeof(sample_t)) {
+ // wait until jack_source_process() signals more data
+ pthread_cond_wait(&d_ringbuffer_ready, &d_jack_process_lock);
+ }
+ pthread_mutex_unlock(&d_jack_process_lock);
#endif
- read_space -= read_space%(d_jack_buffer_size*sizeof(sample_t));
- read_size = std::min(read_space, (unsigned int)work_size);
+ read_space -= read_space % (d_jack_buffer_size * sizeof(sample_t));
+ read_size = std::min(read_space, (unsigned int)work_size);
- if(jack_ringbuffer_read(d_ringbuffer[i], (char *) &(out[i][k]),
- read_size) < read_size) {
- bail("jack_ringbuffer_read failed", 0);
- }
- work_size -= read_size;
- k += read_size/sizeof(sample_t);
+ if (jack_ringbuffer_read(d_ringbuffer[i], (char*)&(out[i][k]), read_size) <
+ read_size) {
+ bail("jack_ringbuffer_read failed", 0);
+ }
+ work_size -= read_size;
+ k += read_size / sizeof(sample_t);
}
- }
-
- return noutput_items;
}
- void
- jack_source::output_error_msg(const char *msg, int err)
- {
- GR_LOG_ERROR(d_logger, boost::format("[%1%]: %2%: %3%") \
- % d_device_name % msg % err);
- }
+ return noutput_items;
+}
- void
- jack_source::bail(const char *msg, int err)
- {
- output_error_msg(msg, err);
- throw std::runtime_error("audio_jack_source");
- }
+void jack_source::output_error_msg(const char* msg, int err)
+{
+ GR_LOG_ERROR(d_logger, boost::format("[%1%]: %2%: %3%") % d_device_name % msg % err);
+}
+
+void jack_source::bail(const char* msg, int err)
+{
+ output_error_msg(msg, err);
+ throw std::runtime_error("audio_jack_source");
+}
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/jack/jack_source.h b/gr-audio/lib/jack/jack_source.h
index f40e46d4f0..f91b2fad5a 100644
--- a/gr-audio/lib/jack/jack_source.h
+++ b/gr-audio/lib/jack/jack_source.h
@@ -29,60 +29,58 @@
#include <stdexcept>
namespace gr {
- namespace audio {
+namespace audio {
- int jack_source_process(jack_nframes_t nframes, void *arg);
+int jack_source_process(jack_nframes_t nframes, void* arg);
- /*!
- * \brief audio source using JACK
- * \ingroup audio_blk
- *
- * The source has one input stream of floats.
- *
- * Output samples will be in the range [-1,1].
- */
- class jack_source : public source
- {
- friend int jack_source_process(jack_nframes_t nframes, void *arg);
+/*!
+ * \brief audio source using JACK
+ * \ingroup audio_blk
+ *
+ * The source has one input stream of floats.
+ *
+ * Output samples will be in the range [-1,1].
+ */
+class jack_source : public source
+{
+ friend int jack_source_process(jack_nframes_t nframes, void* arg);
- // typedef for pointer to class work method
- typedef int(jack_source::*work_t)(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
+ // typedef for pointer to class work method
+ typedef int (jack_source::*work_t)(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
- unsigned int d_sampling_rate;
- std::string d_device_name;
- bool d_ok_to_block;
+ unsigned int d_sampling_rate;
+ std::string d_device_name;
+ bool d_ok_to_block;
- jack_client_t *d_jack_client;
- static const int MAX_PORTS = 10;
- int d_portcount;
- jack_port_t *d_jack_input_port[MAX_PORTS];
- jack_ringbuffer_t *d_ringbuffer[MAX_PORTS];
- jack_nframes_t d_jack_buffer_size;
- pthread_cond_t d_ringbuffer_ready;
- pthread_mutex_t d_jack_process_lock;
+ jack_client_t* d_jack_client;
+ static const int MAX_PORTS = 10;
+ int d_portcount;
+ jack_port_t* d_jack_input_port[MAX_PORTS];
+ jack_ringbuffer_t* d_ringbuffer[MAX_PORTS];
+ jack_nframes_t d_jack_buffer_size;
+ pthread_cond_t d_ringbuffer_ready;
+ pthread_mutex_t d_jack_process_lock;
- // random stats
- int d_noverruns; // count of overruns
+ // random stats
+ int d_noverruns; // count of overruns
- void output_error_msg(const char *msg, int err);
- void bail(const char *msg, int err);
+ void output_error_msg(const char* msg, int err);
+ void bail(const char* msg, int err);
- public:
- jack_source(int sampling_rate,
- const std::string device_name,
- bool ok_to_block);
- ~jack_source();
+public:
+ jack_source(int sampling_rate, const std::string device_name, bool ok_to_block);
+ ~jack_source();
- bool check_topology(int ninputs, int noutputs);
+ bool check_topology(int ninputs, int noutputs);
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_AUDIO_JACK_SOURCE_H */
diff --git a/gr-audio/lib/oss/oss_sink.cc b/gr-audio/lib/oss/oss_sink.cc
index 36aca18e7a..972271d6d1 100644
--- a/gr-audio/lib/oss/oss_sink.cc
+++ b/gr-audio/lib/oss/oss_sink.cc
@@ -39,130 +39,123 @@
#include <stdexcept>
namespace gr {
- namespace audio {
-
- sink::sptr
- oss_sink_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block)
- {
- return sink::sptr
- (new oss_sink(sampling_rate, device_name, ok_to_block));
- }
-
- static std::string
- default_device_name()
- {
- return prefs::singleton()->get_string
- ("audio_oss", "default_output_device", "/dev/dsp");
- }
-
- oss_sink::oss_sink(int sampling_rate,
- const std::string device_name,
- bool ok_to_block)
- : sync_block("audio_oss_sink",
- io_signature::make(1, 2, sizeof(float)),
- io_signature::make(0, 0, 0)),
- d_sampling_rate(sampling_rate),
- d_device_name(device_name.empty() ? default_device_name() : device_name),
- d_fd(-1), d_buffer(0), d_chunk_size(0)
- {
- if((d_fd = open(d_device_name.c_str(), O_WRONLY)) < 0) {
+namespace audio {
+
+sink::sptr
+oss_sink_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block)
+{
+ return sink::sptr(new oss_sink(sampling_rate, device_name, ok_to_block));
+}
+
+static std::string default_device_name()
+{
+ return prefs::singleton()->get_string(
+ "audio_oss", "default_output_device", "/dev/dsp");
+}
+
+oss_sink::oss_sink(int sampling_rate, const std::string device_name, bool ok_to_block)
+ : sync_block("audio_oss_sink",
+ io_signature::make(1, 2, sizeof(float)),
+ io_signature::make(0, 0, 0)),
+ d_sampling_rate(sampling_rate),
+ d_device_name(device_name.empty() ? default_device_name() : device_name),
+ d_fd(-1),
+ d_buffer(0),
+ d_chunk_size(0)
+{
+ if ((d_fd = open(d_device_name.c_str(), O_WRONLY)) < 0) {
fprintf(stderr, "audio_oss_sink: ");
perror(d_device_name.c_str());
throw std::runtime_error("audio_oss_sink");
- }
+ }
- double CHUNK_TIME =
- std::max(0.001,
- prefs::singleton()->get_double("audio_oss", "latency", 0.005));
+ double CHUNK_TIME =
+ std::max(0.001, prefs::singleton()->get_double("audio_oss", "latency", 0.005));
- d_chunk_size = (int)(d_sampling_rate * CHUNK_TIME);
- set_output_multiple(d_chunk_size);
+ d_chunk_size = (int)(d_sampling_rate * CHUNK_TIME);
+ set_output_multiple(d_chunk_size);
- d_buffer = new short[d_chunk_size * 2];
+ d_buffer = new short[d_chunk_size * 2];
- int format = AFMT_S16_NE;
- int orig_format = format;
- if(ioctl(d_fd, SNDCTL_DSP_SETFMT, &format) < 0) {
+ int format = AFMT_S16_NE;
+ int orig_format = format;
+ if (ioctl(d_fd, SNDCTL_DSP_SETFMT, &format) < 0) {
std::cerr << "audio_oss_sink: " << d_device_name << " ioctl failed\n";
- perror(d_device_name.c_str ());
+ perror(d_device_name.c_str());
throw std::runtime_error("audio_oss_sink");
- }
+ }
- if(format != orig_format) {
+ if (format != orig_format) {
fprintf(stderr, "audio_oss_sink: unable to support format %d\n", orig_format);
fprintf(stderr, " card requested %d instead.\n", format);
- }
+ }
- // set to stereo no matter what. Some hardware only does stereo
- int channels = 2;
- if(ioctl(d_fd, SNDCTL_DSP_CHANNELS, &channels) < 0 || channels != 2) {
+ // set to stereo no matter what. Some hardware only does stereo
+ int channels = 2;
+ if (ioctl(d_fd, SNDCTL_DSP_CHANNELS, &channels) < 0 || channels != 2) {
perror("audio_oss_sink: could not set STEREO mode");
throw std::runtime_error("audio_oss_sink");
- }
+ }
- // set sampling freq
- int sf = sampling_rate;
- if(ioctl(d_fd, SNDCTL_DSP_SPEED, &sf) < 0) {
- std::cerr << "audio_oss_sink: "
- << d_device_name << ": invalid sampling_rate "
+ // set sampling freq
+ int sf = sampling_rate;
+ if (ioctl(d_fd, SNDCTL_DSP_SPEED, &sf) < 0) {
+ std::cerr << "audio_oss_sink: " << d_device_name << ": invalid sampling_rate "
<< sampling_rate << "\n";
sampling_rate = 8000;
- if(ioctl(d_fd, SNDCTL_DSP_SPEED, &sf) < 0) {
- std::cerr << "audio_oss_sink: failed to set sampling_rate to 8000\n";
- throw std::runtime_error("audio_oss_sink");
+ if (ioctl(d_fd, SNDCTL_DSP_SPEED, &sf) < 0) {
+ std::cerr << "audio_oss_sink: failed to set sampling_rate to 8000\n";
+ throw std::runtime_error("audio_oss_sink");
}
- }
- }
-
- oss_sink::~oss_sink()
- {
- close(d_fd);
- delete [] d_buffer;
}
-
- int
- oss_sink::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- const float *f0, *f1;
-
- switch(input_items.size()) {
- case 1: // mono input
- f0 = (const float *)input_items[0];
-
- for(int i = 0; i < noutput_items; i += d_chunk_size) {
- for(int j = 0; j < d_chunk_size; j++) {
- d_buffer[2*j+0] = (short) (f0[j] * 32767);
- d_buffer[2*j+1] = (short) (f0[j] * 32767);
- }
- f0 += d_chunk_size;
- if(write(d_fd, d_buffer, 2 * d_chunk_size * sizeof (short)) < 0)
- perror("audio_oss_sink: write");
+}
+
+oss_sink::~oss_sink()
+{
+ close(d_fd);
+ delete[] d_buffer;
+}
+
+int oss_sink::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ const float *f0, *f1;
+
+ switch (input_items.size()) {
+ case 1: // mono input
+ f0 = (const float*)input_items[0];
+
+ for (int i = 0; i < noutput_items; i += d_chunk_size) {
+ for (int j = 0; j < d_chunk_size; j++) {
+ d_buffer[2 * j + 0] = (short)(f0[j] * 32767);
+ d_buffer[2 * j + 1] = (short)(f0[j] * 32767);
+ }
+ f0 += d_chunk_size;
+ if (write(d_fd, d_buffer, 2 * d_chunk_size * sizeof(short)) < 0)
+ perror("audio_oss_sink: write");
}
break;
- case 2: // stereo input
- f0 = (const float *) input_items[0];
- f1 = (const float *) input_items[1];
-
- for(int i = 0; i < noutput_items; i += d_chunk_size) {
- for(int j = 0; j < d_chunk_size; j++) {
- d_buffer[2*j+0] = (short)(f0[j] * 32767);
- d_buffer[2*j+1] = (short)(f1[j] * 32767);
- }
- f0 += d_chunk_size;
- f1 += d_chunk_size;
- if(write(d_fd, d_buffer, 2 * d_chunk_size * sizeof (short)) < 0)
- perror("audio_oss_sink: write");
+ case 2: // stereo input
+ f0 = (const float*)input_items[0];
+ f1 = (const float*)input_items[1];
+
+ for (int i = 0; i < noutput_items; i += d_chunk_size) {
+ for (int j = 0; j < d_chunk_size; j++) {
+ d_buffer[2 * j + 0] = (short)(f0[j] * 32767);
+ d_buffer[2 * j + 1] = (short)(f1[j] * 32767);
+ }
+ f0 += d_chunk_size;
+ f1 += d_chunk_size;
+ if (write(d_fd, d_buffer, 2 * d_chunk_size * sizeof(short)) < 0)
+ perror("audio_oss_sink: write");
}
break;
- }
-
- return noutput_items;
}
- } /* namespace audio */
+ return noutput_items;
+}
+
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/oss/oss_sink.h b/gr-audio/lib/oss/oss_sink.h
index 3b17348c41..2e4d90cfea 100644
--- a/gr-audio/lib/oss/oss_sink.h
+++ b/gr-audio/lib/oss/oss_sink.h
@@ -27,35 +27,35 @@
#include <string>
namespace gr {
- namespace audio {
-
- /*!
- * \brief audio sink using OSS
- * \ingroup audio_blk
- *
- * input signature is one or two streams of floats.
- * Input samples must be in the range [-1,1].
- */
- class oss_sink : public sink
- {
- int d_sampling_rate;
- std::string d_device_name;
- int d_fd;
- short *d_buffer;
- int d_chunk_size;
-
- public:
- oss_sink(int sampling_rate,
- const std::string device_name = "",
- bool ok_to_block = true);
- ~oss_sink();
-
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
-
- } /* namespace audio */
+namespace audio {
+
+/*!
+ * \brief audio sink using OSS
+ * \ingroup audio_blk
+ *
+ * input signature is one or two streams of floats.
+ * Input samples must be in the range [-1,1].
+ */
+class oss_sink : public sink
+{
+ int d_sampling_rate;
+ std::string d_device_name;
+ int d_fd;
+ short* d_buffer;
+ int d_chunk_size;
+
+public:
+ oss_sink(int sampling_rate,
+ const std::string device_name = "",
+ bool ok_to_block = true);
+ ~oss_sink();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
+
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_AUDIO_OSS_SINK_H */
diff --git a/gr-audio/lib/oss/oss_source.cc b/gr-audio/lib/oss/oss_source.cc
index 4c6365d057..14b8a0c969 100644
--- a/gr-audio/lib/oss/oss_source.cc
+++ b/gr-audio/lib/oss/oss_source.cc
@@ -39,149 +39,143 @@
#include <stdexcept>
namespace gr {
- namespace audio {
-
- source::sptr
- oss_source_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block)
- {
- return source::sptr
- (new oss_source(sampling_rate, device_name, ok_to_block));
- }
-
- static std::string
- default_device_name()
- {
- return prefs::singleton()->get_string
- ("audio_oss", "default_input_device", "/dev/dsp");
- }
-
- oss_source::oss_source(int sampling_rate,
- const std::string device_name,
- bool ok_to_block)
- : sync_block("audio_oss_source",
- io_signature::make(0, 0, 0),
- io_signature::make(1, 2, sizeof(float))),
- d_sampling_rate(sampling_rate),
- d_device_name(device_name.empty() ? default_device_name() : device_name),
- d_fd(-1), d_buffer(0), d_chunk_size(0)
- {
- if((d_fd = open(d_device_name.c_str(), O_RDONLY)) < 0) {
+namespace audio {
+
+source::sptr
+oss_source_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block)
+{
+ return source::sptr(new oss_source(sampling_rate, device_name, ok_to_block));
+}
+
+static std::string default_device_name()
+{
+ return prefs::singleton()->get_string(
+ "audio_oss", "default_input_device", "/dev/dsp");
+}
+
+oss_source::oss_source(int sampling_rate, const std::string device_name, bool ok_to_block)
+ : sync_block("audio_oss_source",
+ io_signature::make(0, 0, 0),
+ io_signature::make(1, 2, sizeof(float))),
+ d_sampling_rate(sampling_rate),
+ d_device_name(device_name.empty() ? default_device_name() : device_name),
+ d_fd(-1),
+ d_buffer(0),
+ d_chunk_size(0)
+{
+ if ((d_fd = open(d_device_name.c_str(), O_RDONLY)) < 0) {
fprintf(stderr, "audio_oss_source: ");
perror(d_device_name.c_str());
throw std::runtime_error("audio_oss_source");
- }
+ }
- double CHUNK_TIME =
+ double CHUNK_TIME =
std::max(0.001, prefs::singleton()->get_double("audio_oss", "latency", 0.005));
- d_chunk_size = (int)(d_sampling_rate * CHUNK_TIME);
- set_output_multiple(d_chunk_size);
+ d_chunk_size = (int)(d_sampling_rate * CHUNK_TIME);
+ set_output_multiple(d_chunk_size);
- d_buffer = new short[d_chunk_size * 2];
+ d_buffer = new short[d_chunk_size * 2];
- int format = AFMT_S16_NE;
- int orig_format = format;
- if(ioctl(d_fd, SNDCTL_DSP_SETFMT, &format) < 0) {
+ int format = AFMT_S16_NE;
+ int orig_format = format;
+ if (ioctl(d_fd, SNDCTL_DSP_SETFMT, &format) < 0) {
std::cerr << "audio_oss_source: " << d_device_name << " ioctl failed\n";
- perror(d_device_name.c_str ());
+ perror(d_device_name.c_str());
throw std::runtime_error("audio_oss_source");
- }
+ }
- if(format != orig_format) {
+ if (format != orig_format) {
fprintf(stderr, "audio_oss_source: unable to support format %d\n", orig_format);
fprintf(stderr, " card requested %d instead.\n", format);
- }
+ }
- // set to stereo no matter what. Some hardware only does stereo
- int channels = 2;
- if(ioctl(d_fd, SNDCTL_DSP_CHANNELS, &channels) < 0 || channels != 2) {
+ // set to stereo no matter what. Some hardware only does stereo
+ int channels = 2;
+ if (ioctl(d_fd, SNDCTL_DSP_CHANNELS, &channels) < 0 || channels != 2) {
perror("audio_oss_source: could not set STEREO mode");
throw std::runtime_error("audio_oss_source");
- }
+ }
- // set sampling freq
- int sf = sampling_rate;
- if(ioctl(d_fd, SNDCTL_DSP_SPEED, &sf) < 0) {
- std::cerr << "audio_oss_source: "
- << d_device_name << ": invalid sampling_rate "
+ // set sampling freq
+ int sf = sampling_rate;
+ if (ioctl(d_fd, SNDCTL_DSP_SPEED, &sf) < 0) {
+ std::cerr << "audio_oss_source: " << d_device_name << ": invalid sampling_rate "
<< sampling_rate << "\n";
sampling_rate = 8000;
- if(ioctl(d_fd, SNDCTL_DSP_SPEED, &sf) < 0) {
- std::cerr << "audio_oss_source: failed to set sampling_rate to 8000\n";
- throw std::runtime_error ("audio_oss_source");
+ if (ioctl(d_fd, SNDCTL_DSP_SPEED, &sf) < 0) {
+ std::cerr << "audio_oss_source: failed to set sampling_rate to 8000\n";
+ throw std::runtime_error("audio_oss_source");
}
- }
}
+}
- oss_source::~oss_source()
- {
- close(d_fd);
- delete [] d_buffer;
- }
+oss_source::~oss_source()
+{
+ close(d_fd);
+ delete[] d_buffer;
+}
- int
- oss_source::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- float *f0 = (float *)output_items[0];
- float *f1 = (float *)output_items[1]; // will be invalid if this is mono output
+int oss_source::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ float* f0 = (float*)output_items[0];
+ float* f1 = (float*)output_items[1]; // will be invalid if this is mono output
- const int shorts_per_item = 2; // L + R
- const int bytes_per_item = shorts_per_item * sizeof(short);
+ const int shorts_per_item = 2; // L + R
+ const int bytes_per_item = shorts_per_item * sizeof(short);
- // To minimize latency, never return more than CHUNK_TIME
- // worth of samples per call to work.
+ // To minimize latency, never return more than CHUNK_TIME
+ // worth of samples per call to work.
- noutput_items = std::min(noutput_items, d_chunk_size);
+ noutput_items = std::min(noutput_items, d_chunk_size);
- int base = 0;
- int ntogo = noutput_items;
+ int base = 0;
+ int ntogo = noutput_items;
- while(ntogo > 0) {
+ while (ntogo > 0) {
int nbytes = std::min(ntogo, d_chunk_size) * bytes_per_item;
int result_nbytes = read(d_fd, d_buffer, nbytes);
- if(result_nbytes < 0) {
- perror("audio_oss_source");
- return -1; // say we're done
+ if (result_nbytes < 0) {
+ perror("audio_oss_source");
+ return -1; // say we're done
}
- if((result_nbytes & (bytes_per_item - 1)) != 0) {
- fprintf(stderr, "audio_oss_source: internal error.\n");
- throw std::runtime_error("internal error");
+ if ((result_nbytes & (bytes_per_item - 1)) != 0) {
+ fprintf(stderr, "audio_oss_source: internal error.\n");
+ throw std::runtime_error("internal error");
}
int result_nitems = result_nbytes / bytes_per_item;
// now unpack samples into output streams
- switch(output_items.size()) {
- case 1: // mono output
- for(int i = 0; i < result_nitems; i++) {
- f0[base+i] = d_buffer[2*i+0] * (1.0 / 32767);
- }
- break;
+ switch (output_items.size()) {
+ case 1: // mono output
+ for (int i = 0; i < result_nitems; i++) {
+ f0[base + i] = d_buffer[2 * i + 0] * (1.0 / 32767);
+ }
+ break;
- case 2: // stereo output
- for(int i = 0; i < result_nitems; i++) {
- f0[base+i] = d_buffer[2*i+0] * (1.0 / 32767);
- f1[base+i] = d_buffer[2*i+1] * (1.0 / 32767);
- }
- break;
+ case 2: // stereo output
+ for (int i = 0; i < result_nitems; i++) {
+ f0[base + i] = d_buffer[2 * i + 0] * (1.0 / 32767);
+ f1[base + i] = d_buffer[2 * i + 1] * (1.0 / 32767);
+ }
+ break;
default:
- assert(0);
+ assert(0);
}
ntogo -= result_nitems;
base += result_nitems;
- }
-
- return noutput_items - ntogo;
}
- } /* namespace audio */
+ return noutput_items - ntogo;
+}
+
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/oss/oss_source.h b/gr-audio/lib/oss/oss_source.h
index 1180a7b35a..ec9972bd43 100644
--- a/gr-audio/lib/oss/oss_source.h
+++ b/gr-audio/lib/oss/oss_source.h
@@ -27,36 +27,36 @@
#include <string>
namespace gr {
- namespace audio {
-
- /*!
- * \brief audio source using OSS
- * \ingroup audio_blk
- *
- * Output signature is one or two streams of floats.
- * Output samples will be in the range [-1,1].
- */
- class oss_source : public source
- {
- int d_sampling_rate;
- std::string d_device_name;
- int d_fd;
- short *d_buffer;
- int d_chunk_size;
-
- public:
- oss_source(int sampling_rate,
- const std::string device_name = "",
- bool ok_to_block = true);
-
- ~oss_source();
-
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
-
- } /* namespace audio */
+namespace audio {
+
+/*!
+ * \brief audio source using OSS
+ * \ingroup audio_blk
+ *
+ * Output signature is one or two streams of floats.
+ * Output samples will be in the range [-1,1].
+ */
+class oss_source : public source
+{
+ int d_sampling_rate;
+ std::string d_device_name;
+ int d_fd;
+ short* d_buffer;
+ int d_chunk_size;
+
+public:
+ oss_source(int sampling_rate,
+ const std::string device_name = "",
+ bool ok_to_block = true);
+
+ ~oss_source();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
+
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_AUDIO_OSS_SOURCE_H */
diff --git a/gr-audio/lib/osx/circular_buffer.h b/gr-audio/lib/osx/circular_buffer.h
index 5193a982d3..c18f2464cb 100644
--- a/gr-audio/lib/osx/circular_buffer.h
+++ b/gr-audio/lib/osx/circular_buffer.h
@@ -32,291 +32,302 @@
#endif
#if DO_DEBUG
-#define DEBUG(X) do{X} while(0);
+#define DEBUG(X) \
+ do { \
+ X \
+ } while (0);
#else
-#define DEBUG(X) do{} while(0);
+#define DEBUG(X) \
+ do { \
+ } while (0);
#endif
template <class T>
class circular_buffer
{
private:
-// the buffer to use
- T* d_buffer;
+ // the buffer to use
+ T* d_buffer;
-// the following are in Items (type T)
- size_t d_bufLen_I, d_readNdx_I, d_writeNdx_I;
- size_t d_n_avail_write_I, d_n_avail_read_I;
+ // the following are in Items (type T)
+ size_t d_bufLen_I, d_readNdx_I, d_writeNdx_I;
+ size_t d_n_avail_write_I, d_n_avail_read_I;
-// stuff to control access to class internals
- gr::thread::mutex* d_internal;
- gr::thread::condition_variable* d_readBlock;
- gr::thread::condition_variable* d_writeBlock;
+ // stuff to control access to class internals
+ gr::thread::mutex* d_internal;
+ gr::thread::condition_variable* d_readBlock;
+ gr::thread::condition_variable* d_writeBlock;
-// booleans to decide how to control reading, writing, and aborting
- bool d_doWriteBlock, d_doFullRead, d_doAbort;
+ // booleans to decide how to control reading, writing, and aborting
+ bool d_doWriteBlock, d_doFullRead, d_doAbort;
- void delete_mutex_cond () {
- if (d_internal) {
- delete d_internal;
- d_internal = NULL;
- }
- if (d_readBlock) {
- delete d_readBlock;
- d_readBlock = NULL;
- }
- if (d_writeBlock) {
- delete d_writeBlock;
- d_writeBlock = NULL;
- }
- };
+ void delete_mutex_cond()
+ {
+ if (d_internal) {
+ delete d_internal;
+ d_internal = NULL;
+ }
+ if (d_readBlock) {
+ delete d_readBlock;
+ d_readBlock = NULL;
+ }
+ if (d_writeBlock) {
+ delete d_writeBlock;
+ d_writeBlock = NULL;
+ }
+ };
public:
- circular_buffer (size_t bufLen_I,
- bool doWriteBlock = true, bool doFullRead = false) {
- if (bufLen_I == 0)
- throw std::runtime_error ("circular_buffer(): "
- "Number of items to buffer must be > 0.\n");
- d_bufLen_I = bufLen_I;
- d_buffer = (T*) new T[d_bufLen_I];
- d_doWriteBlock = doWriteBlock;
- d_doFullRead = doFullRead;
- d_internal = NULL;
- d_readBlock = d_writeBlock = NULL;
- reset ();
- DEBUG (std::cerr << "c_b(): buf len (items) = " << d_bufLen_
- << ", doWriteBlock = " << (d_doWriteBlock ? "true" : "false")
- << ", doFullRead = " << (d_doFullRead ? "true" : "false")
- << std::endl);
- };
+ circular_buffer(size_t bufLen_I, bool doWriteBlock = true, bool doFullRead = false)
+ {
+ if (bufLen_I == 0)
+ throw std::runtime_error("circular_buffer(): "
+ "Number of items to buffer must be > 0.\n");
+ d_bufLen_I = bufLen_I;
+ d_buffer = (T*)new T[d_bufLen_I];
+ d_doWriteBlock = doWriteBlock;
+ d_doFullRead = doFullRead;
+ d_internal = NULL;
+ d_readBlock = d_writeBlock = NULL;
+ reset();
+ DEBUG(std::cerr << "c_b(): buf len (items) = " << d_bufLen_
+ << ", doWriteBlock = " << (d_doWriteBlock ? "true" : "false")
+ << ", doFullRead = " << (d_doFullRead ? "true" : "false")
+ << std::endl);
+ };
- ~circular_buffer () {
- delete_mutex_cond ();
- delete [] d_buffer;
- };
+ ~circular_buffer()
+ {
+ delete_mutex_cond();
+ delete[] d_buffer;
+ };
- inline size_t n_avail_write_items () {
- gr::thread::scoped_lock l (*d_internal);
- size_t retVal = d_n_avail_write_I;
- return (retVal);
- };
+ inline size_t n_avail_write_items()
+ {
+ gr::thread::scoped_lock l(*d_internal);
+ size_t retVal = d_n_avail_write_I;
+ return (retVal);
+ };
- inline size_t n_avail_read_items () {
- gr::thread::scoped_lock l (*d_internal);
- size_t retVal = d_n_avail_read_I;
- return (retVal);
- };
+ inline size_t n_avail_read_items()
+ {
+ gr::thread::scoped_lock l(*d_internal);
+ size_t retVal = d_n_avail_read_I;
+ return (retVal);
+ };
- inline size_t buffer_length_items () {return (d_bufLen_I);};
- inline bool do_write_block () {return (d_doWriteBlock);};
- inline bool do_full_read () {return (d_doFullRead);};
+ inline size_t buffer_length_items() { return (d_bufLen_I); };
+ inline bool do_write_block() { return (d_doWriteBlock); };
+ inline bool do_full_read() { return (d_doFullRead); };
- void reset () {
- d_doAbort = false;
- bzero (d_buffer, d_bufLen_I * sizeof (T));
- d_readNdx_I = d_writeNdx_I = d_n_avail_read_I = 0;
- d_n_avail_write_I = d_bufLen_I;
- delete_mutex_cond ();
- // create a mutex to handle contention of shared resources;
- // any routine needed access to shared resources uses lock()
- // before doing anything, then unlock() when finished.
- d_internal = new gr::thread::mutex ();
- // link the internal mutex to the read and write conditions;
- // when wait() is called, the internal mutex will automatically
- // be unlock()'ed. Upon return (from a notify_one() to the condition),
- // the internal mutex will be lock()'ed.
- d_readBlock = new gr::thread::condition_variable ();
- d_writeBlock = new gr::thread::condition_variable ();
- };
+ void reset()
+ {
+ d_doAbort = false;
+ bzero(d_buffer, d_bufLen_I * sizeof(T));
+ d_readNdx_I = d_writeNdx_I = d_n_avail_read_I = 0;
+ d_n_avail_write_I = d_bufLen_I;
+ delete_mutex_cond();
+ // create a mutex to handle contention of shared resources;
+ // any routine needed access to shared resources uses lock()
+ // before doing anything, then unlock() when finished.
+ d_internal = new gr::thread::mutex();
+ // link the internal mutex to the read and write conditions;
+ // when wait() is called, the internal mutex will automatically
+ // be unlock()'ed. Upon return (from a notify_one() to the condition),
+ // the internal mutex will be lock()'ed.
+ d_readBlock = new gr::thread::condition_variable();
+ d_writeBlock = new gr::thread::condition_variable();
+ };
-/*
- * enqueue: add the given buffer of item-length to the queue,
- * first-in-first-out (FIFO).
- *
- * inputs:
- * buf: a pointer to the buffer holding the data
- *
- * bufLen_I: the buffer length in items (of the instantiated type)
- *
- * returns:
- * -1: on overflow (write is not blocking, and data is being
- * written faster than it is being read)
- * 0: if nothing to do (0 length buffer)
- * 1: if success
- * 2: in the process of aborting, do doing nothing
- *
- * will throw runtime errors if inputs are improper:
- * buffer pointer is NULL
- * buffer length is larger than the instantiated buffer length
- */
+ /*
+ * enqueue: add the given buffer of item-length to the queue,
+ * first-in-first-out (FIFO).
+ *
+ * inputs:
+ * buf: a pointer to the buffer holding the data
+ *
+ * bufLen_I: the buffer length in items (of the instantiated type)
+ *
+ * returns:
+ * -1: on overflow (write is not blocking, and data is being
+ * written faster than it is being read)
+ * 0: if nothing to do (0 length buffer)
+ * 1: if success
+ * 2: in the process of aborting, do doing nothing
+ *
+ * will throw runtime errors if inputs are improper:
+ * buffer pointer is NULL
+ * buffer length is larger than the instantiated buffer length
+ */
- int enqueue (T* buf, size_t bufLen_I) {
- DEBUG (std::cerr << "enqueue: buf = " << (void*) buf
- << ", bufLen = " << bufLen_I
- << ", #av_wr = " << d_n_avail_write_I
- << ", #av_rd = " << d_n_avail_read_I << std::endl);
- if (bufLen_I > d_bufLen_I) {
- std::cerr << "ERROR: cannot add buffer longer ("
- << bufLen_I << ") than instantiated length ("
- << d_bufLen_I << ")." << std::endl;
- throw std::runtime_error ("circular_buffer::enqueue()");
- }
+ int enqueue(T* buf, size_t bufLen_I)
+ {
+ DEBUG(std::cerr << "enqueue: buf = " << (void*)buf << ", bufLen = " << bufLen_I
+ << ", #av_wr = " << d_n_avail_write_I
+ << ", #av_rd = " << d_n_avail_read_I << std::endl);
+ if (bufLen_I > d_bufLen_I) {
+ std::cerr << "ERROR: cannot add buffer longer (" << bufLen_I
+ << ") than instantiated length (" << d_bufLen_I << ")."
+ << std::endl;
+ throw std::runtime_error("circular_buffer::enqueue()");
+ }
- if (bufLen_I == 0)
- return (0);
- if (!buf)
- throw std::runtime_error ("circular_buffer::enqueue(): "
- "input buffer is NULL.\n");
- gr::thread::scoped_lock l (*d_internal);
- if (d_doAbort) {
- return (2);
- }
- // set the return value to 1: success; change if needed
- int retval = 1;
- if (bufLen_I > d_n_avail_write_I) {
- if (d_doWriteBlock) {
- while (bufLen_I > d_n_avail_write_I) {
- DEBUG (std::cerr << "enqueue: #len > #a, waiting." << std::endl);
- // wait; will automatically unlock() the internal mutex via
- // the scoped lock
- d_writeBlock->wait (l);
- // and auto re-lock() it here.
- if (d_doAbort) {
- DEBUG (std::cerr << "enqueue: #len > #a, aborting." << std::endl);
- return (2);
- }
- DEBUG (std::cerr << "enqueue: #len > #a, done waiting." << std::endl);
- }
- } else {
- d_n_avail_read_I = d_bufLen_I - bufLen_I;
- d_n_avail_write_I = bufLen_I;
- DEBUG (std::cerr << "circular_buffer::enqueue: overflow" << std::endl);
- retval = -1;
- }
- }
- size_t n_now_I = d_bufLen_I - d_writeNdx_I, n_start_I = 0;
- if (n_now_I > bufLen_I)
- n_now_I = bufLen_I;
- else if (n_now_I < bufLen_I)
- n_start_I = bufLen_I - n_now_I;
- memcpy (&(d_buffer[d_writeNdx_I]), buf, n_now_I * sizeof (T));
- if (n_start_I) {
- memcpy (d_buffer, &(buf[n_now_I]), n_start_I * sizeof (T));
- d_writeNdx_I = n_start_I;
- } else
- d_writeNdx_I += n_now_I;
- d_n_avail_read_I += bufLen_I;
- d_n_avail_write_I -= bufLen_I;
- d_readBlock->notify_one ();
- return (retval);
- };
+ if (bufLen_I == 0)
+ return (0);
+ if (!buf)
+ throw std::runtime_error("circular_buffer::enqueue(): "
+ "input buffer is NULL.\n");
+ gr::thread::scoped_lock l(*d_internal);
+ if (d_doAbort) {
+ return (2);
+ }
+ // set the return value to 1: success; change if needed
+ int retval = 1;
+ if (bufLen_I > d_n_avail_write_I) {
+ if (d_doWriteBlock) {
+ while (bufLen_I > d_n_avail_write_I) {
+ DEBUG(std::cerr << "enqueue: #len > #a, waiting." << std::endl);
+ // wait; will automatically unlock() the internal mutex via
+ // the scoped lock
+ d_writeBlock->wait(l);
+ // and auto re-lock() it here.
+ if (d_doAbort) {
+ DEBUG(std::cerr << "enqueue: #len > #a, aborting." << std::endl);
+ return (2);
+ }
+ DEBUG(std::cerr << "enqueue: #len > #a, done waiting." << std::endl);
+ }
+ } else {
+ d_n_avail_read_I = d_bufLen_I - bufLen_I;
+ d_n_avail_write_I = bufLen_I;
+ DEBUG(std::cerr << "circular_buffer::enqueue: overflow" << std::endl);
+ retval = -1;
+ }
+ }
+ size_t n_now_I = d_bufLen_I - d_writeNdx_I, n_start_I = 0;
+ if (n_now_I > bufLen_I)
+ n_now_I = bufLen_I;
+ else if (n_now_I < bufLen_I)
+ n_start_I = bufLen_I - n_now_I;
+ memcpy(&(d_buffer[d_writeNdx_I]), buf, n_now_I * sizeof(T));
+ if (n_start_I) {
+ memcpy(d_buffer, &(buf[n_now_I]), n_start_I * sizeof(T));
+ d_writeNdx_I = n_start_I;
+ } else
+ d_writeNdx_I += n_now_I;
+ d_n_avail_read_I += bufLen_I;
+ d_n_avail_write_I -= bufLen_I;
+ d_readBlock->notify_one();
+ return (retval);
+ };
-/*
- * dequeue: removes from the queue the number of items requested, or
- * available, into the given buffer on a FIFO basis.
- *
- * inputs:
- * buf: a pointer to the buffer into which to copy the data
- *
- * bufLen_I: pointer to the requested number of items to remove
- *
- * outputs:
- * bufLen_I: pointer to the actual number of items removed
- *
- * returns:
- * 0: if nothing to do (0 length buffer)
- * 1: if success
- * 2: in the process of aborting, do doing nothing
- * 3: if the number of requested items to remove is not the same
- * as the actual number of items removed.
- *
- * will throw runtime errors if inputs are improper:
- * buffer pointer is NULL
- * buffer length pointer is NULL
- * buffer length is larger than the instantiated buffer length
- */
+ /*
+ * dequeue: removes from the queue the number of items requested, or
+ * available, into the given buffer on a FIFO basis.
+ *
+ * inputs:
+ * buf: a pointer to the buffer into which to copy the data
+ *
+ * bufLen_I: pointer to the requested number of items to remove
+ *
+ * outputs:
+ * bufLen_I: pointer to the actual number of items removed
+ *
+ * returns:
+ * 0: if nothing to do (0 length buffer)
+ * 1: if success
+ * 2: in the process of aborting, do doing nothing
+ * 3: if the number of requested items to remove is not the same
+ * as the actual number of items removed.
+ *
+ * will throw runtime errors if inputs are improper:
+ * buffer pointer is NULL
+ * buffer length pointer is NULL
+ * buffer length is larger than the instantiated buffer length
+ */
- int dequeue (T* buf, size_t* bufLen_I) {
- DEBUG (std::cerr << "dequeue: buf = " << ((void*) buf)
- << ", *bufLen = " << (*bufLen_I)
- << ", #av_wr = " << d_n_avail_write_I
- << ", #av_rd = " << d_n_avail_read_I << std::endl);
- if (!bufLen_I)
- throw std::runtime_error ("circular_buffer::dequeue(): "
- "input bufLen pointer is NULL.\n");
- if (!buf)
- throw std::runtime_error ("circular_buffer::dequeue(): "
- "input buffer pointer is NULL.\n");
- size_t l_bufLen_I = *bufLen_I;
- if (l_bufLen_I == 0)
- return (0);
- if (l_bufLen_I > d_bufLen_I) {
- std::cerr << "ERROR: cannot remove buffer longer ("
- << l_bufLen_I << ") than instantiated length ("
- << d_bufLen_I << ")." << std::endl;
- throw std::runtime_error ("circular_buffer::dequeue()");
- }
+ int dequeue(T* buf, size_t* bufLen_I)
+ {
+ DEBUG(std::cerr << "dequeue: buf = " << ((void*)buf) << ", *bufLen = "
+ << (*bufLen_I) << ", #av_wr = " << d_n_avail_write_I
+ << ", #av_rd = " << d_n_avail_read_I << std::endl);
+ if (!bufLen_I)
+ throw std::runtime_error("circular_buffer::dequeue(): "
+ "input bufLen pointer is NULL.\n");
+ if (!buf)
+ throw std::runtime_error("circular_buffer::dequeue(): "
+ "input buffer pointer is NULL.\n");
+ size_t l_bufLen_I = *bufLen_I;
+ if (l_bufLen_I == 0)
+ return (0);
+ if (l_bufLen_I > d_bufLen_I) {
+ std::cerr << "ERROR: cannot remove buffer longer (" << l_bufLen_I
+ << ") than instantiated length (" << d_bufLen_I << ")."
+ << std::endl;
+ throw std::runtime_error("circular_buffer::dequeue()");
+ }
- gr::thread::scoped_lock l (*d_internal);
- if (d_doAbort) {
- return (2);
- }
- if (d_doFullRead) {
- while (d_n_avail_read_I < l_bufLen_I) {
- DEBUG (std::cerr << "dequeue: #a < #len, waiting." << std::endl);
- // wait; will automatically unlock() the internal mutex via
- // the scoped lock
- d_readBlock->wait (l);
- // and re-lock() it here.
- if (d_doAbort) {
- DEBUG (std::cerr << "dequeue: #a < #len, aborting." << std::endl);
- return (2);
- }
- DEBUG (std::cerr << "dequeue: #a < #len, done waiting." << std::endl);
- }
- } else {
- while (d_n_avail_read_I == 0) {
- DEBUG (std::cerr << "dequeue: #a == 0, waiting." << std::endl);
- // wait; will automatically unlock() the internal mutex via
- // the scoped lock
- d_readBlock->wait (l);
- // and re-lock() it here.
- if (d_doAbort) {
- DEBUG (std::cerr << "dequeue: #a == 0, aborting." << std::endl);
- return (2);
- }
- DEBUG (std::cerr << "dequeue: #a == 0, done waiting." << std::endl);
- }
- }
- if (l_bufLen_I > d_n_avail_read_I)
- l_bufLen_I = d_n_avail_read_I;
- size_t n_now_I = d_bufLen_I - d_readNdx_I, n_start_I = 0;
- if (n_now_I > l_bufLen_I)
- n_now_I = l_bufLen_I;
- else if (n_now_I < l_bufLen_I)
- n_start_I = l_bufLen_I - n_now_I;
- memcpy (buf, &(d_buffer[d_readNdx_I]), n_now_I * sizeof (T));
- if (n_start_I) {
- memcpy (&(buf[n_now_I]), d_buffer, n_start_I * sizeof (T));
- d_readNdx_I = n_start_I;
- } else
- d_readNdx_I += n_now_I;
- int rv = 1;
- if (*bufLen_I != l_bufLen_I)
- rv = 3;
- *bufLen_I = l_bufLen_I;
- d_n_avail_read_I -= l_bufLen_I;
- d_n_avail_write_I += l_bufLen_I;
- d_writeBlock->notify_one ();
- return (rv);
- };
+ gr::thread::scoped_lock l(*d_internal);
+ if (d_doAbort) {
+ return (2);
+ }
+ if (d_doFullRead) {
+ while (d_n_avail_read_I < l_bufLen_I) {
+ DEBUG(std::cerr << "dequeue: #a < #len, waiting." << std::endl);
+ // wait; will automatically unlock() the internal mutex via
+ // the scoped lock
+ d_readBlock->wait(l);
+ // and re-lock() it here.
+ if (d_doAbort) {
+ DEBUG(std::cerr << "dequeue: #a < #len, aborting." << std::endl);
+ return (2);
+ }
+ DEBUG(std::cerr << "dequeue: #a < #len, done waiting." << std::endl);
+ }
+ } else {
+ while (d_n_avail_read_I == 0) {
+ DEBUG(std::cerr << "dequeue: #a == 0, waiting." << std::endl);
+ // wait; will automatically unlock() the internal mutex via
+ // the scoped lock
+ d_readBlock->wait(l);
+ // and re-lock() it here.
+ if (d_doAbort) {
+ DEBUG(std::cerr << "dequeue: #a == 0, aborting." << std::endl);
+ return (2);
+ }
+ DEBUG(std::cerr << "dequeue: #a == 0, done waiting." << std::endl);
+ }
+ }
+ if (l_bufLen_I > d_n_avail_read_I)
+ l_bufLen_I = d_n_avail_read_I;
+ size_t n_now_I = d_bufLen_I - d_readNdx_I, n_start_I = 0;
+ if (n_now_I > l_bufLen_I)
+ n_now_I = l_bufLen_I;
+ else if (n_now_I < l_bufLen_I)
+ n_start_I = l_bufLen_I - n_now_I;
+ memcpy(buf, &(d_buffer[d_readNdx_I]), n_now_I * sizeof(T));
+ if (n_start_I) {
+ memcpy(&(buf[n_now_I]), d_buffer, n_start_I * sizeof(T));
+ d_readNdx_I = n_start_I;
+ } else
+ d_readNdx_I += n_now_I;
+ int rv = 1;
+ if (*bufLen_I != l_bufLen_I)
+ rv = 3;
+ *bufLen_I = l_bufLen_I;
+ d_n_avail_read_I -= l_bufLen_I;
+ d_n_avail_write_I += l_bufLen_I;
+ d_writeBlock->notify_one();
+ return (rv);
+ };
- void abort () {
- gr::thread::scoped_lock l (*d_internal);
- d_doAbort = true;
- d_writeBlock->notify_one ();
- d_readBlock->notify_one ();
- };
+ void abort()
+ {
+ gr::thread::scoped_lock l(*d_internal);
+ d_doAbort = true;
+ d_writeBlock->notify_one();
+ d_readBlock->notify_one();
+ };
};
#endif /* _CIRCULAR_BUFFER_H_ */
diff --git a/gr-audio/lib/osx/osx_common.h b/gr-audio/lib/osx/osx_common.h
index 5d8a3800a5..3a578a4719 100644
--- a/gr-audio/lib/osx/osx_common.h
+++ b/gr-audio/lib/osx/osx_common.h
@@ -37,32 +37,28 @@ namespace osx {
#define _OSX_AU_DEBUG_RENDER_ 0
#endif
-#define check_error_and_throw(err,what,throw_str) \
- if(err) { \
- OSStatus error = static_cast<OSStatus>(err); \
- char err_str[sizeof(OSStatus)+1]; \
- memcpy((void*)(&err_str), (void*)(&error), sizeof(OSStatus)); \
- err_str[sizeof(OSStatus)] = 0; \
- GR_LOG_FATAL(d_logger, boost::format(what)); \
- GR_LOG_FATAL(d_logger, boost::format(" Error# %u ('%s')") \
- % error % err_str); \
- GR_LOG_FATAL(d_logger, boost::format(" %s:%d") \
- % __FILE__ %__LINE__); \
- throw std::runtime_error(throw_str); \
- }
+#define check_error_and_throw(err, what, throw_str) \
+ if (err) { \
+ OSStatus error = static_cast<OSStatus>(err); \
+ char err_str[sizeof(OSStatus) + 1]; \
+ memcpy((void*)(&err_str), (void*)(&error), sizeof(OSStatus)); \
+ err_str[sizeof(OSStatus)] = 0; \
+ GR_LOG_FATAL(d_logger, boost::format(what)); \
+ GR_LOG_FATAL(d_logger, boost::format(" Error# %u ('%s')") % error % err_str); \
+ GR_LOG_FATAL(d_logger, boost::format(" %s:%d") % __FILE__ % __LINE__); \
+ throw std::runtime_error(throw_str); \
+ }
-#define check_error(err,what) \
- if(err) { \
- OSStatus error = static_cast<OSStatus>(err); \
- char err_str[sizeof(OSStatus)+1]; \
- memcpy((void*)(&err_str), (void*)(&error), sizeof(OSStatus)); \
- err_str[sizeof(OSStatus)] = 0; \
- GR_LOG_WARN(d_logger, boost::format(what)); \
- GR_LOG_WARN(d_logger, boost::format(" Error# %u ('%s')") \
- % error % err_str); \
- GR_LOG_WARN(d_logger, boost::format(" %s:%d") \
- % __FILE__ %__LINE__); \
- }
+#define check_error(err, what) \
+ if (err) { \
+ OSStatus error = static_cast<OSStatus>(err); \
+ char err_str[sizeof(OSStatus) + 1]; \
+ memcpy((void*)(&err_str), (void*)(&error), sizeof(OSStatus)); \
+ err_str[sizeof(OSStatus)] = 0; \
+ GR_LOG_WARN(d_logger, boost::format(what)); \
+ GR_LOG_WARN(d_logger, boost::format(" Error# %u ('%s')") % error % err_str); \
+ GR_LOG_WARN(d_logger, boost::format(" %s:%d") % __FILE__ % __LINE__); \
+ }
#include <boost/detail/endian.hpp> //BOOST_BIG_ENDIAN
#ifdef BOOST_BIG_ENDIAN
diff --git a/gr-audio/lib/osx/osx_impl.cc b/gr-audio/lib/osx/osx_impl.cc
index 2a73375114..c3ef76ba8f 100644
--- a/gr-audio/lib/osx/osx_impl.cc
+++ b/gr-audio/lib/osx/osx_impl.cc
@@ -33,275 +33,253 @@
#include <locale>
#include <stdexcept>
-std::ostream&
-operator<<
-(std::ostream& s,
- const AudioStreamBasicDescription& asbd)
+std::ostream& operator<<(std::ostream& s, const AudioStreamBasicDescription& asbd)
{
- char format_id[sizeof(asbd.mFormatID)+1];
- memcpy(format_id, (void*)(&asbd.mFormatID), sizeof(asbd.mFormatID));
- format_id[sizeof(asbd.mFormatID)] = 0;
- s << " Sample Rate : " << asbd.mSampleRate << std::endl;
- s << " Format ID : " << format_id << std::endl;
- s << " Format Flags : " << asbd.mFormatFlags << std::endl;
- s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
- << " : Is Float" << std::endl;
- s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0)
- << " : Is Big Endian" << std::endl;
- s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
- << " : Is Signed Integer" << std::endl;
- s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsPacked) != 0)
- << " : Is Packed" << std::endl;
- s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0)
- << " : Is Aligned High" << std::endl;
- s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsNonInterleaved) != 0)
- << " : Is Non-Interleaved" << std::endl;
- s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsNonMixable) != 0)
- << " : Is Non-Mixable" << std::endl;
- s << " Bytes / Packet : " << asbd.mBytesPerPacket << std::endl;
- s << " Frames / Packet : " << asbd.mFramesPerPacket << std::endl;
- s << " Bytes / Frame : " << asbd.mBytesPerFrame << std::endl;
- s << " Channels / Frame : " << asbd.mChannelsPerFrame << std::endl;
- s << " Bits / Channel : " << asbd.mBitsPerChannel;
- return(s);
+ char format_id[sizeof(asbd.mFormatID) + 1];
+ memcpy(format_id, (void*)(&asbd.mFormatID), sizeof(asbd.mFormatID));
+ format_id[sizeof(asbd.mFormatID)] = 0;
+ s << " Sample Rate : " << asbd.mSampleRate << std::endl;
+ s << " Format ID : " << format_id << std::endl;
+ s << " Format Flags : " << asbd.mFormatFlags << std::endl;
+ s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsFloat) != 0) << " : Is Float"
+ << std::endl;
+ s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0)
+ << " : Is Big Endian" << std::endl;
+ s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
+ << " : Is Signed Integer" << std::endl;
+ s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsPacked) != 0) << " : Is Packed"
+ << std::endl;
+ s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsAlignedHigh) != 0)
+ << " : Is Aligned High" << std::endl;
+ s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsNonInterleaved) != 0)
+ << " : Is Non-Interleaved" << std::endl;
+ s << " " << ((asbd.mFormatFlags & kAudioFormatFlagIsNonMixable) != 0)
+ << " : Is Non-Mixable" << std::endl;
+ s << " Bytes / Packet : " << asbd.mBytesPerPacket << std::endl;
+ s << " Frames / Packet : " << asbd.mFramesPerPacket << std::endl;
+ s << " Bytes / Frame : " << asbd.mBytesPerFrame << std::endl;
+ s << " Channels / Frame : " << asbd.mChannelsPerFrame << std::endl;
+ s << " Bits / Channel : " << asbd.mBitsPerChannel;
+ return (s);
};
namespace gr {
namespace audio {
namespace osx {
-static UInt32
-_get_num_channels
-(AudioDeviceID ad_id,
- AudioObjectPropertyScope scope)
+static UInt32 _get_num_channels(AudioDeviceID ad_id, AudioObjectPropertyScope scope)
{
- // retrieve the AudioBufferList associated with this ID using
- // the provided scope
-
- UInt32 num_channels = 0;
- UInt32 prop_size = 0;
- AudioObjectPropertyAddress ao_address = {
- kAudioDevicePropertyStreamConfiguration, scope, 0
- };
- OSStatus err = noErr;
- if ((err = AudioObjectGetPropertyDataSize
- (ad_id, &ao_address, 0, NULL,
- &prop_size)) == noErr) {
- boost::scoped_array<AudioBufferList> buf_list
- (reinterpret_cast<AudioBufferList*>
- (new char[prop_size]));
- if ((err = AudioObjectGetPropertyData
- (ad_id, &ao_address, 0, NULL,
- &prop_size, buf_list.get())) == noErr) {
- for (UInt32 mm = 0; mm < buf_list.get()->mNumberBuffers; ++mm) {
- num_channels += buf_list.get()->mBuffers[mm].mNumberChannels;
- }
- }
- else {
- // assume 2 channels
- num_channels = 2;
+ // retrieve the AudioBufferList associated with this ID using
+ // the provided scope
+
+ UInt32 num_channels = 0;
+ UInt32 prop_size = 0;
+ AudioObjectPropertyAddress ao_address = { kAudioDevicePropertyStreamConfiguration,
+ scope,
+ 0 };
+ OSStatus err = noErr;
+ if ((err = AudioObjectGetPropertyDataSize(ad_id, &ao_address, 0, NULL, &prop_size)) ==
+ noErr) {
+ boost::scoped_array<AudioBufferList> buf_list(
+ reinterpret_cast<AudioBufferList*>(new char[prop_size]));
+ if ((err = AudioObjectGetPropertyData(
+ ad_id, &ao_address, 0, NULL, &prop_size, buf_list.get())) == noErr) {
+ for (UInt32 mm = 0; mm < buf_list.get()->mNumberBuffers; ++mm) {
+ num_channels += buf_list.get()->mBuffers[mm].mNumberChannels;
+ }
+ } else {
+ // assume 2 channels
+ num_channels = 2;
+ }
+ } else {
+ // assume 2 channels
+ num_channels = 2;
}
- }
- else {
- // assume 2 channels
- num_channels = 2;
- }
- return(num_channels);
+ return (num_channels);
}
// works with both char and wchar_t
-template<typename charT>
+template <typename charT>
struct ci_equal {
- ci_equal( const std::locale& loc ) : loc_(loc) {}
- bool operator()(charT ch1, charT ch2) {
- return std::tolower(ch1, loc_) == std::tolower(ch2, loc_);
- }
+ ci_equal(const std::locale& loc) : loc_(loc) {}
+ bool operator()(charT ch1, charT ch2)
+ {
+ return std::tolower(ch1, loc_) == std::tolower(ch2, loc_);
+ }
+
private:
- const std::locale& loc_;
+ const std::locale& loc_;
};
// find substring (case insensitive)
-static std::string::size_type ci_find_substr
-(const std::string& str1, const std::string& str2,
- const std::locale& loc = std::locale())
+static std::string::size_type ci_find_substr(const std::string& str1,
+ const std::string& str2,
+ const std::locale& loc = std::locale())
{
- std::string::const_iterator it = std::search
- (str1.begin(), str1.end(),
- str2.begin(), str2.end(),
- ci_equal<std::string::value_type>(loc));
- if (it != str1.end()) {
- return(it - str1.begin());
- }
- // not found
- return(std::string::npos);
+ std::string::const_iterator it = std::search(str1.begin(),
+ str1.end(),
+ str2.begin(),
+ str2.end(),
+ ci_equal<std::string::value_type>(loc));
+ if (it != str1.end()) {
+ return (it - str1.begin());
+ }
+ // not found
+ return (std::string::npos);
}
-void
-get_num_channels_for_audio_device_id
-(AudioDeviceID ad_id,
- UInt32* n_input,
- UInt32* n_output)
+void get_num_channels_for_audio_device_id(AudioDeviceID ad_id,
+ UInt32* n_input,
+ UInt32* n_output)
{
- if (n_input) {
- *n_input = _get_num_channels
- (ad_id, kAudioDevicePropertyScopeInput);
- }
- if (n_output) {
- *n_output = _get_num_channels
- (ad_id, kAudioDevicePropertyScopeOutput);
- }
+ if (n_input) {
+ *n_input = _get_num_channels(ad_id, kAudioDevicePropertyScopeInput);
+ }
+ if (n_output) {
+ *n_output = _get_num_channels(ad_id, kAudioDevicePropertyScopeOutput);
+ }
}
-void
-find_audio_devices
-(const std::string& device_name,
- bool is_input,
- std::vector < AudioDeviceID >* all_ad_ids,
- std::vector < std::string >* all_names)
+void find_audio_devices(const std::string& device_name,
+ bool is_input,
+ std::vector<AudioDeviceID>* all_ad_ids,
+ std::vector<std::string>* all_names)
{
- if ((!all_ad_ids) && (!all_names)) {
- // if nothing is requested, no point in doing anything!
- return;
- }
+ if ((!all_ad_ids) && (!all_names)) {
+ // if nothing is requested, no point in doing anything!
+ return;
+ }
- OSStatus err = noErr;
+ OSStatus err = noErr;
- // retrieve the size of the array of known audio device IDs
+ // retrieve the size of the array of known audio device IDs
- UInt32 prop_size = 0;
+ UInt32 prop_size = 0;
- AudioObjectPropertyAddress ao_address = {
- kAudioHardwarePropertyDevices,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
+ AudioObjectPropertyAddress ao_address = { kAudioHardwarePropertyDevices,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster };
- if ((err = AudioObjectGetPropertyDataSize
- (kAudioObjectSystemObject, &ao_address,
- 0, NULL, &prop_size)) != noErr) {
+ if ((err = AudioObjectGetPropertyDataSize(
+ kAudioObjectSystemObject, &ao_address, 0, NULL, &prop_size)) != noErr) {
#if _OSX_AU_DEBUG_
- std::cerr << "audio_osx::find_audio_devices: "
- << "Unable to retrieve number of audio objects: "
- << err << std::endl;
+ std::cerr << "audio_osx::find_audio_devices: "
+ << "Unable to retrieve number of audio objects: " << err << std::endl;
#endif
- return;
- }
+ return;
+ }
- // get the total number of audio devices (input and output)
+ // get the total number of audio devices (input and output)
- UInt32 num_devices = prop_size / sizeof(AudioDeviceID);
+ UInt32 num_devices = prop_size / sizeof(AudioDeviceID);
- // retrieve all audio device ids
+ // retrieve all audio device ids
- boost::scoped_array < AudioDeviceID > all_dev_ids
- (new AudioDeviceID[num_devices]);
+ boost::scoped_array<AudioDeviceID> all_dev_ids(new AudioDeviceID[num_devices]);
- if ((err = AudioObjectGetPropertyData
- (kAudioObjectSystemObject, &ao_address,
- 0, NULL, &prop_size, all_dev_ids.get())) != noErr) {
+ if ((err = AudioObjectGetPropertyData(kAudioObjectSystemObject,
+ &ao_address,
+ 0,
+ NULL,
+ &prop_size,
+ all_dev_ids.get())) != noErr) {
#if _OSX_AU_DEBUG_
- std::cerr << "audio_osx::find_audio_devices: "
- << "Unable to retrieve audio object ids: "
- << err << std::endl;
+ std::cerr << "audio_osx::find_audio_devices: "
+ << "Unable to retrieve audio object ids: " << err << std::endl;
#endif
- return;
- }
-
- // success; loop over all retrieved output device ids, retrieving
- // the name for each and comparing with the desired name.
-
- std::vector< std::string > valid_names(num_devices);
- std::vector< UInt32 > valid_indices(num_devices);
- UInt32 num_found_devices = 0;
- AudioObjectPropertyScope scope = is_input ?
- kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;
-
- for (UInt32 nn = 0; nn < num_devices; ++nn) {
-
- // make sure this device has input / output channels (it might
- // also have output / input channels, too, but we do not care
- // about that here)
-
- AudioDeviceID t_id = all_dev_ids[nn];
-
- if (is_input) {
- UInt32 n_input_channels = 0;
- get_num_channels_for_audio_device_id
- (t_id, &n_input_channels, NULL);
- if (n_input_channels == 0) {
- // no input channels; must be output device; just continue
- // to the next audio device.
- continue;
- }
- } else {
- UInt32 n_output_channels = 0;
- get_num_channels_for_audio_device_id
- (t_id, NULL, &n_output_channels);
- if (n_output_channels == 0) {
- // no output channels; must be input device; just continue
- // to the next audio device.
- continue;
- }
+ return;
}
- // retrieve the device name; max name length is 64 characters.
-
- prop_size = 65;
- char c_name_buf[prop_size];
- bzero((void*)c_name_buf, prop_size);
- --prop_size;
-
- AudioObjectPropertyAddress ao_address = {
- kAudioDevicePropertyDeviceName, scope, 0
- };
-
- if ((err = AudioObjectGetPropertyData
- (t_id, &ao_address, 0, NULL,
- &prop_size, (void*)c_name_buf)) != noErr) {
+ // success; loop over all retrieved output device ids, retrieving
+ // the name for each and comparing with the desired name.
+
+ std::vector<std::string> valid_names(num_devices);
+ std::vector<UInt32> valid_indices(num_devices);
+ UInt32 num_found_devices = 0;
+ AudioObjectPropertyScope scope =
+ is_input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;
+
+ for (UInt32 nn = 0; nn < num_devices; ++nn) {
+
+ // make sure this device has input / output channels (it might
+ // also have output / input channels, too, but we do not care
+ // about that here)
+
+ AudioDeviceID t_id = all_dev_ids[nn];
+
+ if (is_input) {
+ UInt32 n_input_channels = 0;
+ get_num_channels_for_audio_device_id(t_id, &n_input_channels, NULL);
+ if (n_input_channels == 0) {
+ // no input channels; must be output device; just continue
+ // to the next audio device.
+ continue;
+ }
+ } else {
+ UInt32 n_output_channels = 0;
+ get_num_channels_for_audio_device_id(t_id, NULL, &n_output_channels);
+ if (n_output_channels == 0) {
+ // no output channels; must be input device; just continue
+ // to the next audio device.
+ continue;
+ }
+ }
+
+ // retrieve the device name; max name length is 64 characters.
+
+ prop_size = 65;
+ char c_name_buf[prop_size];
+ bzero((void*)c_name_buf, prop_size);
+ --prop_size;
+
+ AudioObjectPropertyAddress ao_address = { kAudioDevicePropertyDeviceName,
+ scope,
+ 0 };
+
+ if ((err = AudioObjectGetPropertyData(
+ t_id, &ao_address, 0, NULL, &prop_size, (void*)c_name_buf)) != noErr) {
#if _OSX_AU_DEBUG_
- std::cerr << "audio_osx::find_audio_devices: "
- << "Unable to retrieve audio device name #"
- << (nn+1) << ": " << err << std::endl;
+ std::cerr << "audio_osx::find_audio_devices: "
+ << "Unable to retrieve audio device name #" << (nn + 1) << ": "
+ << err << std::endl;
#endif
- continue;
- }
- std::string name_buf(c_name_buf);
-
- // compare the retrieved name with the desired one, if
- // provided; case insensitive.
+ continue;
+ }
+ std::string name_buf(c_name_buf);
- if (device_name.length() > 0) {
+ // compare the retrieved name with the desired one, if
+ // provided; case insensitive.
- std::string::size_type found =
- ci_find_substr(name_buf, device_name);
- if (found == std::string::npos) {
- // not found; continue to the next ID
- continue;
- }
- }
+ if (device_name.length() > 0) {
- // store this info
+ std::string::size_type found = ci_find_substr(name_buf, device_name);
+ if (found == std::string::npos) {
+ // not found; continue to the next ID
+ continue;
+ }
+ }
- valid_names[nn] = name_buf;
- valid_indices[num_found_devices++] = nn;
+ // store this info
- }
+ valid_names[nn] = name_buf;
+ valid_indices[num_found_devices++] = nn;
+ }
- // resize valid function arguments, then copy found values
+ // resize valid function arguments, then copy found values
- if (all_ad_ids) {
- all_ad_ids->resize(num_found_devices);
- for (UInt32 nn = 0; nn < num_found_devices; ++nn) {
- (*all_ad_ids)[nn] = all_dev_ids[valid_indices[nn]];
+ if (all_ad_ids) {
+ all_ad_ids->resize(num_found_devices);
+ for (UInt32 nn = 0; nn < num_found_devices; ++nn) {
+ (*all_ad_ids)[nn] = all_dev_ids[valid_indices[nn]];
+ }
}
- }
- if (all_names) {
- all_names->resize(num_found_devices);
- for (UInt32 nn = 0; nn < num_found_devices; ++nn) {
- (*all_names)[nn] = valid_names[valid_indices[nn]];
+ if (all_names) {
+ all_names->resize(num_found_devices);
+ for (UInt32 nn = 0; nn < num_found_devices; ++nn) {
+ (*all_names)[nn] = valid_names[valid_indices[nn]];
+ }
}
- }
}
} /* namespace osx */
diff --git a/gr-audio/lib/osx/osx_sink.cc b/gr-audio/lib/osx/osx_sink.cc
index 80dc5fe5fa..88e6d72fc6 100644
--- a/gr-audio/lib/osx/osx_sink.cc
+++ b/gr-audio/lib/osx/osx_sink.cc
@@ -32,637 +32,595 @@
#include <stdexcept>
namespace gr {
- namespace audio {
-
- sink::sptr
- osx_sink_fcn(int sampling_rate,
- const std::string& device_name,
- bool ok_to_block)
- {
- return sink::sptr
- (new osx_sink(sampling_rate, device_name, ok_to_block));
- }
-
- static std::string
- default_device_name()
- {
- return prefs::singleton()->get_string
- ("audio_osx", "default_output_device", "built-in");
- }
-
- osx_sink::osx_sink(int sample_rate,
- const std::string& device_name,
- bool ok_to_block)
- : sync_block("audio_osx_sink",
- io_signature::make(0, 0, 0),
- io_signature::make(0, 0, 0)),
- d_input_sample_rate(0.0), d_n_user_channels(0),
- d_n_dev_channels(0), d_queue_sample_count(0),
- d_buffer_size_samples(0), d_ok_to_block(ok_to_block),
- d_do_reset(false), d_hardware_changed(false),
- d_using_default_device(false), d_waiting_for_data(false),
- d_desired_name(device_name.empty() ? default_device_name()
- : device_name),
- d_output_au(0), d_output_ad_id(0)
- {
- if(sample_rate <= 0) {
- GR_LOG_ERROR(d_logger, boost::format
- ("Invalid Sample Rate: %d")
- % sample_rate);
+namespace audio {
+
+sink::sptr
+osx_sink_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block)
+{
+ return sink::sptr(new osx_sink(sampling_rate, device_name, ok_to_block));
+}
+
+static std::string default_device_name()
+{
+ return prefs::singleton()->get_string(
+ "audio_osx", "default_output_device", "built-in");
+}
+
+osx_sink::osx_sink(int sample_rate, const std::string& device_name, bool ok_to_block)
+ : sync_block(
+ "audio_osx_sink", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)),
+ d_input_sample_rate(0.0),
+ d_n_user_channels(0),
+ d_n_dev_channels(0),
+ d_queue_sample_count(0),
+ d_buffer_size_samples(0),
+ d_ok_to_block(ok_to_block),
+ d_do_reset(false),
+ d_hardware_changed(false),
+ d_using_default_device(false),
+ d_waiting_for_data(false),
+ d_desired_name(device_name.empty() ? default_device_name() : device_name),
+ d_output_au(0),
+ d_output_ad_id(0)
+{
+ if (sample_rate <= 0) {
+ GR_LOG_ERROR(d_logger, boost::format("Invalid Sample Rate: %d") % sample_rate);
throw std::invalid_argument("audio_osx_sink");
- }
- else {
+ } else {
d_input_sample_rate = (Float64)sample_rate;
- }
+ }
- // set up for audio output using the stored desired parameters
+ // set up for audio output using the stored desired parameters
- setup();
- }
+ setup();
+}
- void osx_sink::setup()
- {
- OSStatus err = noErr;
+void osx_sink::setup()
+{
+ OSStatus err = noErr;
- // set the default output audio device id to "unknown"
+ // set the default output audio device id to "unknown"
- d_output_ad_id = kAudioDeviceUnknown;
+ d_output_ad_id = kAudioDeviceUnknown;
- // try to find the output audio device, if specified
+ // try to find the output audio device, if specified
- std::vector < AudioDeviceID > all_ad_ids;
- std::vector < std::string > all_names;
+ std::vector<AudioDeviceID> all_ad_ids;
+ std::vector<std::string> all_names;
- osx::find_audio_devices
- (d_desired_name, false,
- &all_ad_ids, &all_names);
+ osx::find_audio_devices(d_desired_name, false, &all_ad_ids, &all_names);
- // check number of device(s) returned
+ // check number of device(s) returned
- if (d_desired_name.length() != 0) {
+ if (d_desired_name.length() != 0) {
if (all_ad_ids.size() == 1) {
- // exactly 1 match was found; see if it was partial
-
- if (all_names[0].compare(d_desired_name) != 0) {
+ // exactly 1 match was found; see if it was partial
- // yes: log the full device name
- GR_LOG_INFO(d_logger, boost::format
- ("Using output audio device '%s'.")
- % all_names[0]);
+ if (all_names[0].compare(d_desired_name) != 0) {
- }
+ // yes: log the full device name
+ GR_LOG_INFO(d_logger,
+ boost::format("Using output audio device '%s'.") %
+ all_names[0]);
+ }
- // store info on this device
+ // store info on this device
- d_output_ad_id = all_ad_ids[0];
- d_selected_name = all_names[0];
+ d_output_ad_id = all_ad_ids[0];
+ d_selected_name = all_names[0];
} else {
- // either 0 or more than 1 device was found; get all output
- // device names, print those, and error out.
-
- osx::find_audio_devices("", false, NULL, &all_names);
+ // either 0 or more than 1 device was found; get all output
+ // device names, print those, and error out.
- std::string err_str("\n\nA unique output audio device name "
- "matching the string '");
- err_str += d_desired_name;
- err_str += "' was not found.\n\n";
- err_str += "The current known output audio device name";
- err_str += ((all_names.size() > 1) ? "s are" : " is");
- err_str += ":\n";
- for (UInt32 nn = 0; nn < all_names.size(); ++nn) {
- err_str += " " + all_names[nn] + "\n";
- }
- GR_LOG_ERROR(d_logger, boost::format(err_str));
- throw std::runtime_error("audio_osx_sink::setup");
+ osx::find_audio_devices("", false, NULL, &all_names);
+ std::string err_str("\n\nA unique output audio device name "
+ "matching the string '");
+ err_str += d_desired_name;
+ err_str += "' was not found.\n\n";
+ err_str += "The current known output audio device name";
+ err_str += ((all_names.size() > 1) ? "s are" : " is");
+ err_str += ":\n";
+ for (UInt32 nn = 0; nn < all_names.size(); ++nn) {
+ err_str += " " + all_names[nn] + "\n";
+ }
+ GR_LOG_ERROR(d_logger, boost::format(err_str));
+ throw std::runtime_error("audio_osx_sink::setup");
}
- }
+ }
- // if no output audio device id was found, use the default
- // output audio device as set in System Preferences.
+ // if no output audio device id was found, use the default
+ // output audio device as set in System Preferences.
- if (d_output_ad_id == kAudioDeviceUnknown) {
+ if (d_output_ad_id == kAudioDeviceUnknown) {
UInt32 size = sizeof(AudioDeviceID);
AudioObjectPropertyAddress ao_address = {
- kAudioHardwarePropertyDefaultOutputDevice,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
+ kAudioHardwarePropertyDefaultOutputDevice,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster
};
- err = AudioObjectGetPropertyData
- (kAudioObjectSystemObject, &ao_address,
- 0, NULL, &size, &d_output_ad_id);
- check_error_and_throw
- (err, "Getting the default output audio device ID failed",
- "audio_osx_sink::setup");
+ err = AudioObjectGetPropertyData(
+ kAudioObjectSystemObject, &ao_address, 0, NULL, &size, &d_output_ad_id);
+ check_error_and_throw(err,
+ "Getting the default output audio device ID failed",
+ "audio_osx_sink::setup");
{
- // retrieve the device name; max name length is 64 characters.
-
- UInt32 prop_size = 65;
- char c_name_buf[prop_size];
- bzero((void*)c_name_buf, prop_size);
- --prop_size;
-
- AudioObjectPropertyAddress ao_address = {
- kAudioDevicePropertyDeviceName,
- kAudioDevicePropertyScopeOutput, 0
- };
-
- if ((err = AudioObjectGetPropertyData
- (d_output_ad_id, &ao_address, 0, NULL,
- &prop_size, (void*)c_name_buf)) != noErr) {
-
- check_error(err, "Unable to retrieve output audio device name");
-
- } else {
-
- GR_LOG_INFO(d_logger, boost::format
- ("\n\nUsing output audio device '%s'.\n ... "
- "which is the current default output audio"
- " device.\n Changing the default output"
- " audio device in the System Preferences"
- " will \n result in changing it here, too "
- "(with an internal reconfiguration).\n") %
- std::string(c_name_buf));
-
- }
-
- d_selected_name = c_name_buf;
+ // retrieve the device name; max name length is 64 characters.
+
+ UInt32 prop_size = 65;
+ char c_name_buf[prop_size];
+ bzero((void*)c_name_buf, prop_size);
+ --prop_size;
+
+ AudioObjectPropertyAddress ao_address = { kAudioDevicePropertyDeviceName,
+ kAudioDevicePropertyScopeOutput,
+ 0 };
+
+ if ((err = AudioObjectGetPropertyData(d_output_ad_id,
+ &ao_address,
+ 0,
+ NULL,
+ &prop_size,
+ (void*)c_name_buf)) != noErr) {
+
+ check_error(err, "Unable to retrieve output audio device name");
+
+ } else {
+
+ GR_LOG_INFO(d_logger,
+ boost::format("\n\nUsing output audio device '%s'.\n ... "
+ "which is the current default output audio"
+ " device.\n Changing the default output"
+ " audio device in the System Preferences"
+ " will \n result in changing it here, too "
+ "(with an internal reconfiguration).\n") %
+ std::string(c_name_buf));
+ }
+ d_selected_name = c_name_buf;
}
d_using_default_device = true;
+ }
- }
-
- // retrieve the total number of channels for the selected audio
- // output device
+ // retrieve the total number of channels for the selected audio
+ // output device
- osx::get_num_channels_for_audio_device_id
- (d_output_ad_id, NULL, &d_n_dev_channels);
+ osx::get_num_channels_for_audio_device_id(d_output_ad_id, NULL, &d_n_dev_channels);
- // set the block input signature, if not already set
- // (d_n_user_channels is set in check_topology, which is called
- // before the flow-graph is running)
+ // set the block input signature, if not already set
+ // (d_n_user_channels is set in check_topology, which is called
+ // before the flow-graph is running)
- if (d_n_user_channels == 0) {
- set_input_signature(io_signature::make
- (1, d_n_dev_channels, sizeof(float)));
- }
+ if (d_n_user_channels == 0) {
+ set_input_signature(io_signature::make(1, d_n_dev_channels, sizeof(float)));
+ }
- // set the interim buffer size; to work with the GR scheduler,
- // must be at least 16kB. Pick 50 kS since that's plenty yet
- // not very much.
+ // set the interim buffer size; to work with the GR scheduler,
+ // must be at least 16kB. Pick 50 kS since that's plenty yet
+ // not very much.
- d_buffer_size_samples = (d_input_sample_rate < 50000.0 ?
- 50000 : (UInt32)d_input_sample_rate);
+ d_buffer_size_samples =
+ (d_input_sample_rate < 50000.0 ? 50000 : (UInt32)d_input_sample_rate);
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink: max # samples = "
- << d_buffer_size_samples << std::endl;
+ std::cerr << ((void*)(pthread_self()))
+ << " : audio_osx_sink: max # samples = " << d_buffer_size_samples
+ << std::endl;
#endif
- // create the default AudioUnit for output:
+ // create the default AudioUnit for output:
- // Open the default output unit
+ // Open the default output unit
#ifndef GR_USE_OLD_AUDIO_UNIT
- AudioComponentDescription desc;
+ AudioComponentDescription desc;
#else
- ComponentDescription desc;
+ ComponentDescription desc;
#endif
- desc.componentType = kAudioUnitType_Output;
- desc.componentSubType = kAudioUnitSubType_DefaultOutput;
- desc.componentManufacturer = kAudioUnitManufacturer_Apple;
- desc.componentFlags = 0;
- desc.componentFlagsMask = 0;
+ desc.componentType = kAudioUnitType_Output;
+ desc.componentSubType = kAudioUnitSubType_DefaultOutput;
+ desc.componentManufacturer = kAudioUnitManufacturer_Apple;
+ desc.componentFlags = 0;
+ desc.componentFlagsMask = 0;
#ifndef GR_USE_OLD_AUDIO_UNIT
- AudioComponent comp = AudioComponentFindNext(NULL, &desc);
- if(!comp) {
- GR_LOG_FATAL(d_logger, boost::format
- ("AudioComponentFindNext Failed"));
+ AudioComponent comp = AudioComponentFindNext(NULL, &desc);
+ if (!comp) {
+ GR_LOG_FATAL(d_logger, boost::format("AudioComponentFindNext Failed"));
throw std::runtime_error("audio_osx_sink::setup");
- }
- err = AudioComponentInstanceNew(comp, &d_output_au);
- check_error_and_throw(err, "AudioComponentInstanceNew Failed",
- "audio_osx_sink::setup");
+ }
+ err = AudioComponentInstanceNew(comp, &d_output_au);
+ check_error_and_throw(
+ err, "AudioComponentInstanceNew Failed", "audio_osx_sink::setup");
#else
- Component comp = FindNextComponent(NULL, &desc);
- if(comp == NULL) {
- GR_LOG_FATAL(d_logger, boost::format
- ("FindNextComponent Failed"));
+ Component comp = FindNextComponent(NULL, &desc);
+ if (comp == NULL) {
+ GR_LOG_FATAL(d_logger, boost::format("FindNextComponent Failed"));
throw std::runtime_error("audio_osx_sink::setup");
- }
- err = OpenAComponent(comp, &d_output_au);
- check_error_and_throw(err, "OpenAComponent Failed",
- "audio_osx_sink::setup");
-
-#endif
+ }
+ err = OpenAComponent(comp, &d_output_au);
+ check_error_and_throw(err, "OpenAComponent Failed", "audio_osx_sink::setup");
+
+#endif
+
+ // set the selected device ID as the current output device
+
+ err = AudioUnitSetProperty(d_output_au,
+ kAudioOutputUnitProperty_CurrentDevice,
+ kAudioUnitScope_Global,
+ 0,
+ &d_output_ad_id,
+ sizeof(d_output_ad_id));
+ check_error_and_throw(
+ err, "Setting selected output device as current failed", "audio_osx_sink::setup");
+
+ // Set up a callback function to generate output to the output unit
+
+ AURenderCallbackStruct au_callback = { reinterpret_cast<AURenderCallback>(
+ &osx_sink::au_output_callback),
+ reinterpret_cast<void*>(this) };
+ UInt32 prop_size = (UInt32)sizeof(au_callback);
+
+ err = AudioUnitSetProperty(d_output_au,
+ kAudioUnitProperty_SetRenderCallback,
+ kAudioUnitScope_Input,
+ 0,
+ &au_callback,
+ prop_size);
+ check_error_and_throw(err, "Set Render Callback", "audio_osx_sink::setup");
+
+ // create the stream format for the output unit, so that it
+ // handles any format conversions. Set number of channels in
+ // ::start, once the actual number of channels is known.
+
+ memset((void*)(&d_stream_format), 0, sizeof(d_stream_format));
+ d_stream_format.mSampleRate = d_input_sample_rate;
+ d_stream_format.mFormatID = kAudioFormatLinearPCM;
+ d_stream_format.mFormatFlags =
+ (kLinearPCMFormatFlagIsFloat | GR_PCM_ENDIANNESS | kLinearPCMFormatFlagIsPacked |
+ kAudioFormatFlagIsNonInterleaved);
+ d_stream_format.mBytesPerPacket = sizeof(float);
+ d_stream_format.mFramesPerPacket = 1;
+ d_stream_format.mBytesPerFrame = sizeof(float);
+ d_stream_format.mBitsPerChannel = 8 * sizeof(float);
+
+ // set the render quality to maximum
+
+ UInt32 render_quality = kRenderQuality_Max;
+ prop_size = (UInt32)sizeof(render_quality);
+ err = AudioUnitSetProperty(d_output_au,
+ kAudioUnitProperty_RenderQuality,
+ kAudioUnitScope_Global,
+ 0,
+ &render_quality,
+ prop_size);
+ check_error(err, "Setting render quality failed");
+
+ // clear the RunLoop (whatever that is); needed, for some
+ // reason, before a listener will work.
- // set the selected device ID as the current output device
-
- err = AudioUnitSetProperty
- (d_output_au, kAudioOutputUnitProperty_CurrentDevice,
- kAudioUnitScope_Global, 0,
- &d_output_ad_id, sizeof(d_output_ad_id));
- check_error_and_throw
- (err, "Setting selected output device as current failed",
- "audio_osx_sink::setup");
-
- // Set up a callback function to generate output to the output unit
-
- AURenderCallbackStruct au_callback = {
- reinterpret_cast<AURenderCallback>
- (&osx_sink::au_output_callback),
- reinterpret_cast<void*>(this)
- };
- UInt32 prop_size = (UInt32)sizeof(au_callback);
-
- err = AudioUnitSetProperty
- (d_output_au,
- kAudioUnitProperty_SetRenderCallback,
- kAudioUnitScope_Input, 0,
- &au_callback, prop_size);
- check_error_and_throw
- (err, "Set Render Callback",
- "audio_osx_sink::setup");
-
- // create the stream format for the output unit, so that it
- // handles any format conversions. Set number of channels in
- // ::start, once the actual number of channels is known.
-
- memset((void*)(&d_stream_format), 0, sizeof(d_stream_format));
- d_stream_format.mSampleRate = d_input_sample_rate;
- d_stream_format.mFormatID = kAudioFormatLinearPCM;
- d_stream_format.mFormatFlags = (kLinearPCMFormatFlagIsFloat |
- GR_PCM_ENDIANNESS |
- kLinearPCMFormatFlagIsPacked |
- kAudioFormatFlagIsNonInterleaved);
- d_stream_format.mBytesPerPacket = sizeof(float);
- d_stream_format.mFramesPerPacket = 1;
- d_stream_format.mBytesPerFrame = sizeof(float);
- d_stream_format.mBitsPerChannel = 8*sizeof(float);
-
- // set the render quality to maximum
-
- UInt32 render_quality = kRenderQuality_Max;
- prop_size = (UInt32)sizeof(render_quality);
- err = AudioUnitSetProperty
- (d_output_au,
- kAudioUnitProperty_RenderQuality,
- kAudioUnitScope_Global, 0,
- &render_quality, prop_size);
- check_error(err, "Setting render quality failed");
-
- // clear the RunLoop (whatever that is); needed, for some
- // reason, before a listener will work.
-
- {
+ {
CFRunLoopRef the_run_loop = NULL;
- AudioObjectPropertyAddress property = {
- kAudioHardwarePropertyRunLoop,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
+ AudioObjectPropertyAddress property = { kAudioHardwarePropertyRunLoop,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster };
prop_size = (UInt32)sizeof(the_run_loop);
- err = AudioObjectSetPropertyData
- (kAudioObjectSystemObject, &property, 0, NULL,
- prop_size, &the_run_loop);
- check_error(err, "Clearing RunLoop failed; "
+ err = AudioObjectSetPropertyData(
+ kAudioObjectSystemObject, &property, 0, NULL, prop_size, &the_run_loop);
+ check_error(err,
+ "Clearing RunLoop failed; "
"Audio Output Device Listener might not work.");
- }
+ }
- // set up listeners
+ // set up listeners
#ifndef GR_USE_OLD_AUDIO_UNIT
- // 10.4 and newer
+ // 10.4 and newer
- {
+ {
// set up a listener if hardware changes (at all)
- AudioObjectPropertyAddress property = {
- kAudioHardwarePropertyDevices,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
+ AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster };
- err = AudioObjectAddPropertyListener
- (kAudioObjectSystemObject, &property,
- reinterpret_cast<AudioObjectPropertyListenerProc>
- (&osx_sink::hardware_listener),
- reinterpret_cast<void*>(this));
+ err = AudioObjectAddPropertyListener(
+ kAudioObjectSystemObject,
+ &property,
+ reinterpret_cast<AudioObjectPropertyListenerProc>(
+ &osx_sink::hardware_listener),
+ reinterpret_cast<void*>(this));
check_error(err, "Adding Audio Hardware Listener failed");
- }
+ }
- if (d_using_default_device) {
+ if (d_using_default_device) {
// set up a listener for the default output device so that if
// the device changes, this routine will be called and we can
// internally handle this change (if/as necessary)
{
- AudioObjectPropertyAddress property = {
- kAudioHardwarePropertyDefaultOutputDevice,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
- err = AudioObjectAddPropertyListener
- (kAudioObjectSystemObject, &property,
- reinterpret_cast<AudioObjectPropertyListenerProc>
- (&osx_sink::hardware_listener),
- reinterpret_cast<void*>(this));
- check_error(err, "Adding Default Output Audio Listener failed");
+ AudioObjectPropertyAddress property = {
+ kAudioHardwarePropertyDefaultOutputDevice,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster
+ };
+ err = AudioObjectAddPropertyListener(
+ kAudioObjectSystemObject,
+ &property,
+ reinterpret_cast<AudioObjectPropertyListenerProc>(
+ &osx_sink::hardware_listener),
+ reinterpret_cast<void*>(this));
+ check_error(err, "Adding Default Output Audio Listener failed");
}
- }
+ }
#else
- // 10.5 and older
+ // 10.5 and older
- err = AudioHardwareAddPropertyListener
- (kAudioHardwarePropertyDevices,
- reinterpret_cast<AudioHardwarePropertyListenerProc>
- (&osx_sink::hardware_listener),
- reinterpret_cast<void*>(this));
- check_error(err, "Adding Audio Hardware Listener failed");
+ err = AudioHardwareAddPropertyListener(
+ kAudioHardwarePropertyDevices,
+ reinterpret_cast<AudioHardwarePropertyListenerProc>(&osx_sink::hardware_listener),
+ reinterpret_cast<void*>(this));
+ check_error(err, "Adding Audio Hardware Listener failed");
- if (d_using_default_device) {
+ if (d_using_default_device) {
- err = AudioHardwareAddPropertyListener
- (kAudioHardwarePropertyDefaultOutputDevice,
- reinterpret_cast<AudioHardwarePropertyListenerProc>
- (&osx_sink::default_listener),
- reinterpret_cast<void*>(this));
+ err = AudioHardwareAddPropertyListener(
+ kAudioHardwarePropertyDefaultOutputDevice,
+ reinterpret_cast<AudioHardwarePropertyListenerProc>(
+ &osx_sink::default_listener),
+ reinterpret_cast<void*>(this));
check_error(err, "Adding Default Output Audio Listener failed");
-
- }
+ }
#endif
- // initialize the AU for output, so that it is ready to be used
+ // initialize the AU for output, so that it is ready to be used
- err = AudioUnitInitialize(d_output_au);
- check_error_and_throw
- (err, "AudioUnit Initialize Failed",
- "audio_osx_sink::setup");
+ err = AudioUnitInitialize(d_output_au);
+ check_error_and_throw(err, "AudioUnit Initialize Failed", "audio_osx_sink::setup");
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink Parameters:" << std::endl
- << " Sample Rate is " << d_input_sample_rate << std::endl
- << " Max # samples to store per channel is "
- << d_buffer_size_samples << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink Parameters:" << std::endl
+ << " Sample Rate is " << d_input_sample_rate << std::endl
+ << " Max # samples to store per channel is " << d_buffer_size_samples
+ << std::endl;
#endif
- }
+}
- void osx_sink::teardown()
- {
+void osx_sink::teardown()
+{
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::teardown: starting"
- << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::teardown: starting"
+ << std::endl;
#endif
- OSStatus err = noErr;
+ OSStatus err = noErr;
- // stop the AudioUnit
+ // stop the AudioUnit
- stop();
+ stop();
- if (d_using_default_device) {
+ if (d_using_default_device) {
// remove the listener
OSStatus err = noErr;
- AudioObjectPropertyAddress property = {
- kAudioHardwarePropertyDefaultOutputDevice,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
- err = AudioObjectRemovePropertyListener
- (kAudioObjectSystemObject, &property,
- reinterpret_cast<AudioObjectPropertyListenerProc>
- (&osx_sink::hardware_listener),
- reinterpret_cast<void*>(this));
+ AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultOutputDevice,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster };
+ err = AudioObjectRemovePropertyListener(
+ kAudioObjectSystemObject,
+ &property,
+ reinterpret_cast<AudioObjectPropertyListenerProc>(
+ &osx_sink::hardware_listener),
+ reinterpret_cast<void*>(this));
#if _OSX_AU_DEBUG_
- check_error(err, "teardown: AudioObjectRemovePropertyListener "
+ check_error(err,
+ "teardown: AudioObjectRemovePropertyListener "
"hardware failed");
#endif
- }
+ }
- // uninitialize the AudioUnit
+ // uninitialize the AudioUnit
- err = AudioUnitUninitialize(d_output_au);
+ err = AudioUnitUninitialize(d_output_au);
#if _OSX_AU_DEBUG_
- check_error(err, "teardown: AudioUnitUninitialize failed");
+ check_error(err, "teardown: AudioUnitUninitialize failed");
#endif
- // dispose / close the AudioUnit
+ // dispose / close the AudioUnit
#ifndef GR_USE_OLD_AUDIO_UNIT
- err = AudioComponentInstanceDispose(d_output_au);
+ err = AudioComponentInstanceDispose(d_output_au);
#if _OSX_AU_DEBUG_
- check_error(err, "teardown: AudioComponentInstanceDispose failed");
+ check_error(err, "teardown: AudioComponentInstanceDispose failed");
#endif
#else
- CloseComponent(d_output_au);
+ CloseComponent(d_output_au);
#if _OSX_AU_DEBUG_
- check_error(err, "teardown: CloseComponent failed");
+ check_error(err, "teardown: CloseComponent failed");
#endif
#endif
- // delete buffers
+ // delete buffers
- for(UInt32 nn = 0; nn < d_buffers.size(); ++nn) {
+ for (UInt32 nn = 0; nn < d_buffers.size(); ++nn) {
delete d_buffers[nn];
d_buffers[nn] = 0;
- }
- d_buffers.resize(0);
+ }
+ d_buffers.resize(0);
- // clear important variables; not # user channels
+ // clear important variables; not # user channels
- d_n_dev_channels = d_n_buffer_channels =
- d_queue_sample_count = d_buffer_size_samples = 0;
- d_using_default_device = false;
- d_output_au = 0;
- d_output_ad_id = 0;
+ d_n_dev_channels = d_n_buffer_channels = d_queue_sample_count =
+ d_buffer_size_samples = 0;
+ d_using_default_device = false;
+ d_output_au = 0;
+ d_output_ad_id = 0;
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::teardown: finished"
- << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::teardown: finished"
+ << std::endl;
#endif
- }
+}
- bool
- osx_sink::is_running()
- {
- UInt32 au_running = 0;
+bool osx_sink::is_running()
+{
+ UInt32 au_running = 0;
- if (d_output_au) {
+ if (d_output_au) {
UInt32 prop_size = (UInt32)sizeof(UInt32);
- OSStatus err = AudioUnitGetProperty
- (d_output_au,
- kAudioOutputUnitProperty_IsRunning,
- kAudioUnitScope_Global, 0,
- &au_running, &prop_size);
- check_error_and_throw
- (err, "AudioUnitGetProperty IsRunning",
- "audio_osx_sink::is_running");
-
- }
-
- return(au_running != 0);
+ OSStatus err = AudioUnitGetProperty(d_output_au,
+ kAudioOutputUnitProperty_IsRunning,
+ kAudioUnitScope_Global,
+ 0,
+ &au_running,
+ &prop_size);
+ check_error_and_throw(
+ err, "AudioUnitGetProperty IsRunning", "audio_osx_sink::is_running");
}
- bool
- osx_sink::check_topology(int ninputs, int noutputs)
- {
- // check # output to make sure it's valid
- if(noutputs != 0) {
-
- GR_LOG_FATAL(d_logger, boost::format
- ("check_topology(): number of output "
- "streams provided (%d) should be 0.")
- % noutputs);
- throw std::runtime_error
- ("audio_osx_sink::check_topology");
-
- }
-
- // check # outputs to make sure it's valid
- if((ninputs < 1) | (ninputs > (int) d_n_dev_channels)) {
-
- GR_LOG_FATAL(d_logger, boost::format
- ("check_topology(): number of input "
- "streams provided (%d) should be in [1,%d] "
- "for the selected output audio device.")
- % ninputs % d_n_dev_channels);
+ return (au_running != 0);
+}
+
+bool osx_sink::check_topology(int ninputs, int noutputs)
+{
+ // check # output to make sure it's valid
+ if (noutputs != 0) {
+
+ GR_LOG_FATAL(d_logger,
+ boost::format("check_topology(): number of output "
+ "streams provided (%d) should be 0.") %
+ noutputs);
throw std::runtime_error("audio_osx_sink::check_topology");
+ }
+
+ // check # outputs to make sure it's valid
+ if ((ninputs < 1) | (ninputs > (int)d_n_dev_channels)) {
- }
+ GR_LOG_FATAL(d_logger,
+ boost::format("check_topology(): number of input "
+ "streams provided (%d) should be in [1,%d] "
+ "for the selected output audio device.") %
+ ninputs % d_n_dev_channels);
+ throw std::runtime_error("audio_osx_sink::check_topology");
+ }
- // save the actual number of input (user) channels
+ // save the actual number of input (user) channels
- d_n_user_channels = ninputs;
+ d_n_user_channels = ninputs;
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::check_topology: "
- << "Actual # user input channels = "
- << d_n_user_channels << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::check_topology: "
+ << "Actual # user input channels = " << d_n_user_channels << std::endl;
#endif
- return (true);
- }
+ return (true);
+}
- void
- osx_sink::check_channels(bool force_reset)
- {
- if (d_buffers.size() == 0) {
+void osx_sink::check_channels(bool force_reset)
+{
+ if (d_buffers.size() == 0) {
// allocate the output circular buffer(s), one per user channel
d_buffers.resize(d_n_user_channels);
- for(UInt32 nn = 0; nn < d_n_user_channels; ++nn) {
- d_buffers[nn] = new circular_buffer<float>
- (d_buffer_size_samples, false, false);
+ for (UInt32 nn = 0; nn < d_n_user_channels; ++nn) {
+ d_buffers[nn] =
+ new circular_buffer<float>(d_buffer_size_samples, false, false);
}
- }
- else {
- if(d_buffers.size() == d_n_user_channels) {
- if (force_reset) {
- for(UInt32 nn = 0; nn < d_buffers.size(); ++nn) {
- d_buffers[nn]->reset();
+ } else {
+ if (d_buffers.size() == d_n_user_channels) {
+ if (force_reset) {
+ for (UInt32 nn = 0; nn < d_buffers.size(); ++nn) {
+ d_buffers[nn]->reset();
+ }
}
- }
- return;
+ return;
}
// reallocate the output circular buffer(s)
if (d_n_user_channels < d_buffers.size()) {
- // too many buffers; delete some
+ // too many buffers; delete some
- for (UInt32 nn = d_n_user_channels; nn < d_buffers.size(); ++nn) {
- delete d_buffers[nn];
- d_buffers[nn] = 0;
- }
- d_buffers.resize(d_n_user_channels);
+ for (UInt32 nn = d_n_user_channels; nn < d_buffers.size(); ++nn) {
+ delete d_buffers[nn];
+ d_buffers[nn] = 0;
+ }
+ d_buffers.resize(d_n_user_channels);
- // reset remaining buffers
+ // reset remaining buffers
- for(UInt32 nn = 0; nn < d_buffers.size(); ++nn) {
- d_buffers[nn]->reset();
- }
- }
- else {
+ for (UInt32 nn = 0; nn < d_buffers.size(); ++nn) {
+ d_buffers[nn]->reset();
+ }
+ } else {
- // too few buffers; create some more
+ // too few buffers; create some more
- // reset old buffers first
+ // reset old buffers first
- for(UInt32 nn = 0; nn < d_buffers.size(); ++nn) {
- d_buffers[nn]->reset();
- }
+ for (UInt32 nn = 0; nn < d_buffers.size(); ++nn) {
+ d_buffers[nn]->reset();
+ }
- d_buffers.resize(d_n_user_channels);
- for (UInt32 nn = d_buffers.size(); nn < d_n_user_channels; ++nn) {
- d_buffers[nn] = new circular_buffer<float>
- (d_buffer_size_samples, false, false);
- }
+ d_buffers.resize(d_n_user_channels);
+ for (UInt32 nn = d_buffers.size(); nn < d_n_user_channels; ++nn) {
+ d_buffers[nn] =
+ new circular_buffer<float>(d_buffer_size_samples, false, false);
+ }
}
- }
+ }
- // reset the output audio unit for the correct number of channels
- // have to uninitialize, set, initialize.
+ // reset the output audio unit for the correct number of channels
+ // have to uninitialize, set, initialize.
- OSStatus err = AudioUnitUninitialize(d_output_au);
- check_error(err, "AudioUnitUninitialize");
+ OSStatus err = AudioUnitUninitialize(d_output_au);
+ check_error(err, "AudioUnitUninitialize");
- d_stream_format.mChannelsPerFrame = d_n_user_channels;
+ d_stream_format.mChannelsPerFrame = d_n_user_channels;
- err = AudioUnitSetProperty
- (d_output_au,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Input, 0,
- &d_stream_format, sizeof(d_stream_format));
- check_error_and_throw
- (err, "AudioUnitSetProperty StreamFormat",
- "audio_osx_sink::check_channels");
+ err = AudioUnitSetProperty(d_output_au,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input,
+ 0,
+ &d_stream_format,
+ sizeof(d_stream_format));
+ check_error_and_throw(
+ err, "AudioUnitSetProperty StreamFormat", "audio_osx_sink::check_channels");
- // initialize the AU for output, so that it is ready to be used
+ // initialize the AU for output, so that it is ready to be used
- err = AudioUnitInitialize(d_output_au);
- check_error_and_throw
- (err, "AudioUnitInitialize",
- "audio_osx_sink::check_channels");
- }
+ err = AudioUnitInitialize(d_output_au);
+ check_error_and_throw(err, "AudioUnitInitialize", "audio_osx_sink::check_channels");
+}
- bool
- osx_sink::start()
- {
- if(!is_running() && d_output_au) {
+bool osx_sink::start()
+{
+ if (!is_running() && d_output_au) {
#if _OSX_AU_DEBUG_
std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::start: starting Output AudioUnit."
- << std::endl;
+ << " : audio_osx_sink::start: starting Output AudioUnit." << std::endl;
#endif
// check channels, (re)allocate and reset buffers if/as necessary
@@ -672,302 +630,268 @@ namespace gr {
// start the audio unit (should never fail)
OSStatus err = AudioOutputUnitStart(d_output_au);
- check_error_and_throw
- (err, "AudioOutputUnitStart",
- "audio_osx_sink::start");
- }
+ check_error_and_throw(err, "AudioOutputUnitStart", "audio_osx_sink::start");
+ }
#if _OSX_AU_DEBUG_
- else {
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::start: "
+ else {
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::start: "
<< "already running." << std::endl;
- }
+ }
#endif
- return (true);
- }
+ return (true);
+}
- bool
- osx_sink::stop()
- {
- if(is_running()) {
+bool osx_sink::stop()
+{
+ if (is_running()) {
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::stop: "
- << "stopping Output AudioUnit."
- << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::stop: "
+ << "stopping Output AudioUnit." << std::endl;
#endif
// if waiting in ::work, signal to wake up
if (d_waiting_for_data) {
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::stop: "
- << "signaling waiting condition" << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::stop: "
+ << "signaling waiting condition" << std::endl;
#endif
- d_cond_data.notify_one();
+ d_cond_data.notify_one();
}
// stop the audio unit (should never fail)
OSStatus err = AudioOutputUnitStop(d_output_au);
- check_error_and_throw
- (err, "AudioOutputUnitStop",
- "audio_osx_sink::stop");
+ check_error_and_throw(err, "AudioOutputUnitStop", "audio_osx_sink::stop");
// abort and reset all buffers
- for(UInt32 nn = 0; nn < d_n_user_channels; ++nn) {
- d_buffers[nn]->abort();
- d_buffers[nn]->reset();
+ for (UInt32 nn = 0; nn < d_n_user_channels; ++nn) {
+ d_buffers[nn]->abort();
+ d_buffers[nn]->reset();
}
// reset local knowledge of amount of data in queues
d_queue_sample_count = 0;
- }
+ }
#if _OSX_AU_DEBUG_
- else {
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::stop: "
+ else {
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::stop: "
<< "already stopped." << std::endl;
- }
+ }
#endif
- return(true);
- }
+ return (true);
+}
- int
- osx_sink::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
+int osx_sink::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
#if _OSX_AU_DEBUG_RENDER_
- {
+ {
gr::thread::scoped_lock l(d_internal);
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::work: "
- << "Starting: #OI = "
- << noutput_items << ", reset = "
- << (d_do_reset ? "true" : "false") << std::endl;
- }
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: "
+ << "Starting: #OI = " << noutput_items
+ << ", reset = " << (d_do_reset ? "true" : "false") << std::endl;
+ }
#endif
- if (d_do_reset) {
+ if (d_do_reset) {
if (d_hardware_changed) {
- // see if the current AudioDeviceID is still available
-
- std::vector < AudioDeviceID > all_ad_ids;
- osx::find_audio_devices
- (d_desired_name, false,
- &all_ad_ids, NULL);
- bool found = false;
- for (UInt32 nn = 0; (nn < all_ad_ids.size()) && (!found);
- ++nn) {
- found = (all_ad_ids[nn] == d_output_ad_id);
- }
- if (!found) {
+ // see if the current AudioDeviceID is still available
- GR_LOG_FATAL(d_logger, boost::format
- ("The selected output audio device ('%s') "
- "is no longer available.\n")
- % d_selected_name);
- return(gr::block::WORK_DONE);
+ std::vector<AudioDeviceID> all_ad_ids;
+ osx::find_audio_devices(d_desired_name, false, &all_ad_ids, NULL);
+ bool found = false;
+ for (UInt32 nn = 0; (nn < all_ad_ids.size()) && (!found); ++nn) {
+ found = (all_ad_ids[nn] == d_output_ad_id);
+ }
+ if (!found) {
- }
+ GR_LOG_FATAL(d_logger,
+ boost::format("The selected output audio device ('%s') "
+ "is no longer available.\n") %
+ d_selected_name);
+ return (gr::block::WORK_DONE);
+ }
- d_do_reset = d_hardware_changed = false;
+ d_do_reset = d_hardware_changed = false;
- }
- else {
+ } else {
#if _OSX_AU_DEBUG_RENDER_
- {
- gr::thread::scoped_lock l(d_internal);
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::work: "
- << "doing reset." << std::endl;
- }
+ {
+ gr::thread::scoped_lock l(d_internal);
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: "
+ << "doing reset." << std::endl;
+ }
#endif
- GR_LOG_WARN(d_logger, boost::format
- ("\n\nThe default output audio device has "
- "changed; resetting audio.\nThere may "
- "be a sound glitch while resetting.\n"));
+ GR_LOG_WARN(d_logger,
+ boost::format("\n\nThe default output audio device has "
+ "changed; resetting audio.\nThere may "
+ "be a sound glitch while resetting.\n"));
- // for any changes, just tear down the current
- // configuration, then set it up again using the user's
- // parameters to try to make selections.
+ // for any changes, just tear down the current
+ // configuration, then set it up again using the user's
+ // parameters to try to make selections.
- teardown();
+ teardown();
- gr::thread::scoped_lock l(d_internal);
+ gr::thread::scoped_lock l(d_internal);
- setup();
- start();
+ setup();
+ start();
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink: "
- << "returning 0 after reset."
- << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink: "
+ << "returning 0 after reset." << std::endl;
#endif
- return(0);
+ return (0);
}
- }
+ }
- gr::thread::scoped_lock l(d_internal);
+ gr::thread::scoped_lock l(d_internal);
- // take the input data, copy it, and push it to the bottom of
- // the queue. mono input is pushed onto queue[0]; stereo input
- // is pushed onto queue[1]. If the number of user/graph
- // channels is less than the number of device channels, copy the
- // data from the last / highest number channel to remaining
- // device channels.
+ // take the input data, copy it, and push it to the bottom of
+ // the queue. mono input is pushed onto queue[0]; stereo input
+ // is pushed onto queue[1]. If the number of user/graph
+ // channels is less than the number of device channels, copy the
+ // data from the last / highest number channel to remaining
+ // device channels.
- // find the maximum amount of buffer space available right now
+ // find the maximum amount of buffer space available right now
- UInt32 l_max_count;
- int diff_count = ((int)d_buffer_size_samples) - noutput_items;
- if(diff_count < 0) {
+ UInt32 l_max_count;
+ int diff_count = ((int)d_buffer_size_samples) - noutput_items;
+ if (diff_count < 0) {
l_max_count = 0;
- }
- else {
+ } else {
l_max_count = (UInt32)diff_count;
- }
+ }
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::work: "
- << "qSC = " << d_queue_sample_count
- << ", lMC = "<< l_max_count
- << ", dBSC = " << d_buffer_size_samples
- << ", #OI = " << noutput_items << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: "
+ << "qSC = " << d_queue_sample_count << ", lMC = " << l_max_count
+ << ", dBSC = " << d_buffer_size_samples << ", #OI = " << noutput_items
+ << std::endl;
#endif
- if(d_queue_sample_count > l_max_count) {
+ if (d_queue_sample_count > l_max_count) {
// data coming in too fast; ok_to_block decides what to do: if
// ok to block, then wait until the render callback makes
// enough space. If not blocking, detect overflow via writing
// data to the circular buffer.
- if(d_ok_to_block == true) {
- // block until there is data to return, or on reset
- while(d_queue_sample_count > l_max_count) {
- // release control so-as to allow data to be retrieved;
- // block until there is data to return
+ if (d_ok_to_block == true) {
+ // block until there is data to return, or on reset
+ while (d_queue_sample_count > l_max_count) {
+ // release control so-as to allow data to be retrieved;
+ // block until there is data to return
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::work: "
- << "waiting." << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: "
+ << "waiting." << std::endl;
#endif
- d_waiting_for_data = true;
- d_cond_data.wait(l);
- d_waiting_for_data = false;
+ d_waiting_for_data = true;
+ d_cond_data.wait(l);
+ d_waiting_for_data = false;
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::work: "
- << "done waiting." << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: "
+ << "done waiting." << std::endl;
#endif
- // the condition's 'notify' was called; acquire control to
- // keep thread safe
+ // the condition's 'notify' was called; acquire control to
+ // keep thread safe
- // if doing a reset, just return here; reset will pick
- // up the next time this method is called.
- if (d_do_reset) {
+ // if doing a reset, just return here; reset will pick
+ // up the next time this method is called.
+ if (d_do_reset) {
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::work: "
- << "returning 0 for reset." << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: "
+ << "returning 0 for reset." << std::endl;
#endif
- return(0);
+ return (0);
+ }
}
- }
}
- }
+ }
- // not blocking and overflow is handled by the circular buffer,
- // or enough data space is available
+ // not blocking and overflow is handled by the circular buffer,
+ // or enough data space is available
- // add the input frames to the buffers' queue, checking for overflow
+ // add the input frames to the buffers' queue, checking for overflow
- UInt32 nn;
- int res = 0;
- float* inBuffer = (float*)input_items[0];
- const UInt32 l_size = input_items.size();
- for(nn = 0; nn < l_size; ++nn) {
+ UInt32 nn;
+ int res = 0;
+ float* inBuffer = (float*)input_items[0];
+ const UInt32 l_size = input_items.size();
+ for (nn = 0; nn < l_size; ++nn) {
inBuffer = (float*)input_items[nn];
int l_res = d_buffers[nn]->enqueue(inBuffer, noutput_items);
- if(l_res == -1) {
- res = -1;
+ if (l_res == -1) {
+ res = -1;
}
- }
- while(nn < d_n_user_channels) {
+ }
+ while (nn < d_n_user_channels) {
// for extra channels, copy the last input's data
int l_res = d_buffers[nn++]->enqueue(inBuffer, noutput_items);
- if(l_res == -1) {
- res = -1;
+ if (l_res == -1) {
+ res = -1;
}
- }
+ }
- // did overflow occur?
+ // did overflow occur?
- if(res == -1) {
+ if (res == -1) {
// yes: data coming in too fast; drop oldest data.
fputs("aO", stderr);
fflush(stderr);
// set the local number of samples available to the max
d_queue_sample_count = d_buffers[0]->buffer_length_items();
- }
- else {
+ } else {
// no: keep up the local sample count
d_queue_sample_count += noutput_items;
- }
+ }
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::work: "
- << "returning: #OI = "
- << noutput_items << ", qSC = "
- << d_queue_sample_count << ", bSS = "
- << d_buffer_size_samples << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::work: "
+ << "returning: #OI = " << noutput_items
+ << ", qSC = " << d_queue_sample_count << ", bSS = " << d_buffer_size_samples
+ << std::endl;
#endif
- return (noutput_items);
- }
+ return (noutput_items);
+}
- OSStatus
- osx_sink::au_output_callback
- (void* in_ref_con,
- AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* in_time_stamp,
- UInt32 in_bus_number,
- UInt32 in_number_frames,
- AudioBufferList* io_data)
- {
- // NOTE: This is a callback from the OS, so throwing here does
- // not work; return an error instead when something does not go
- // as planned.
+OSStatus osx_sink::au_output_callback(void* in_ref_con,
+ AudioUnitRenderActionFlags* io_action_flags,
+ const AudioTimeStamp* in_time_stamp,
+ UInt32 in_bus_number,
+ UInt32 in_number_frames,
+ AudioBufferList* io_data)
+{
+ // NOTE: This is a callback from the OS, so throwing here does
+ // not work; return an error instead when something does not go
+ // as planned.
- osx_sink* This = reinterpret_cast<osx_sink*>(in_ref_con);
- OSStatus err = noErr;
+ osx_sink* This = reinterpret_cast<osx_sink*>(in_ref_con);
+ OSStatus err = noErr;
- gr::thread::scoped_lock l(This->d_internal);
+ gr::thread::scoped_lock l(This->d_internal);
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::au_output_callback: "
- << "starting: qSC = "
- << This->d_queue_sample_count
- << ", in#F = " << in_number_frames
- << ", in#C = " << This->d_n_user_channels << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::au_output_callback: "
+ << "starting: qSC = " << This->d_queue_sample_count
+ << ", in#F = " << in_number_frames << ", in#C = " << This->d_n_user_channels
+ << std::endl;
#endif
- if(This->d_queue_sample_count < in_number_frames) {
+ if (This->d_queue_sample_count < in_number_frames) {
// not enough data to fill request; probably happened on
// start-up, where this callback was called before ::work was.
@@ -976,101 +900,85 @@ namespace gr {
fflush(stderr);
err = kAudioUnitErr_Initialized;
- }
- else {
+ } else {
// enough data; remove data from our buffers into the AU's buffers
int nn = This->d_n_user_channels;
- while(--nn >= 0) {
-
- size_t t_n_output_items = in_number_frames;
- float* out_buffer = (float*)(io_data->mBuffers[nn].mData);
- int rv = This->d_buffers[nn]->dequeue
- (out_buffer, &t_n_output_items);
+ while (--nn >= 0) {
- if((rv != 1) || (t_n_output_items != in_number_frames)) {
+ size_t t_n_output_items = in_number_frames;
+ float* out_buffer = (float*)(io_data->mBuffers[nn].mData);
+ int rv = This->d_buffers[nn]->dequeue(out_buffer, &t_n_output_items);
- std::cerr << "audio_osx_sink::au_output_callback: "
- << "number of available items changing "
- << "unexpectedly (should never happen): was "
- << in_number_frames << " now "
- << t_n_output_items<< std::endl;
- err = kAudioUnitErr_TooManyFramesToProcess;
+ if ((rv != 1) || (t_n_output_items != in_number_frames)) {
- }
+ std::cerr << "audio_osx_sink::au_output_callback: "
+ << "number of available items changing "
+ << "unexpectedly (should never happen): was "
+ << in_number_frames << " now " << t_n_output_items << std::endl;
+ err = kAudioUnitErr_TooManyFramesToProcess;
+ }
}
This->d_queue_sample_count -= in_number_frames;
- }
+ }
- // signal that data is available, if appropriate
+ // signal that data is available, if appropriate
- if (This->d_waiting_for_data) {
+ if (This->d_waiting_for_data) {
#if _OSX_AU_DEBUG_RENDER_
std::cerr << ((void*)(pthread_self()))
<< " : audio_osx_sink::au_output_callback: "
<< "signaling waiting condition" << std::endl;
#endif
This->d_cond_data.notify_one();
- }
+ }
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_sink::au_output_callback: "
- << "returning: qSC = "
- << This->d_queue_sample_count
- << ", err = " << err << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_sink::au_output_callback: "
+ << "returning: qSC = " << This->d_queue_sample_count << ", err = " << err
+ << std::endl;
#endif
- return (err);
- }
+ return (err);
+}
#ifndef GR_USE_OLD_AUDIO_UNIT
- OSStatus
- osx_sink::hardware_listener
- (AudioObjectID in_object_id,
- UInt32 in_num_addresses,
- const AudioObjectPropertyAddress in_addresses[],
- void* in_client_data)
+OSStatus osx_sink::hardware_listener(AudioObjectID in_object_id,
+ UInt32 in_num_addresses,
+ const AudioObjectPropertyAddress in_addresses[],
+ void* in_client_data)
#else
- OSStatus
- osx_sink::hardware_listener
- (AudioHardwarePropertyID in_property_id,
- void* in_client_data)
+OSStatus osx_sink::hardware_listener(AudioHardwarePropertyID in_property_id,
+ void* in_client_data)
#endif
- {
- osx_sink* This = static_cast
- <osx_sink*>(in_client_data);
- This->reset(true);
- return(noErr);
- }
+{
+ osx_sink* This = static_cast<osx_sink*>(in_client_data);
+ This->reset(true);
+ return (noErr);
+}
#ifndef GR_USE_OLD_AUDIO_UNIT
- OSStatus
- osx_sink::default_listener
- (AudioObjectID in_object_id,
- UInt32 in_num_addresses,
- const AudioObjectPropertyAddress in_addresses[],
- void* in_client_data)
+OSStatus osx_sink::default_listener(AudioObjectID in_object_id,
+ UInt32 in_num_addresses,
+ const AudioObjectPropertyAddress in_addresses[],
+ void* in_client_data)
#else
- OSStatus
- osx_sink::default_listener
- (AudioHardwarePropertyID in_property_id,
- void* in_client_data)
+OSStatus osx_sink::default_listener(AudioHardwarePropertyID in_property_id,
+ void* in_client_data)
#endif
- {
- osx_sink* This = reinterpret_cast
- <osx_sink*>(in_client_data);
- This->reset(false);
- return(noErr);
- }
+{
+ osx_sink* This = reinterpret_cast<osx_sink*>(in_client_data);
+ This->reset(false);
+ return (noErr);
+}
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/osx/osx_sink.h b/gr-audio/lib/osx/osx_sink.h
index 127f243495..db7763e188 100644
--- a/gr-audio/lib/osx/osx_sink.h
+++ b/gr-audio/lib/osx/osx_sink.h
@@ -29,109 +29,97 @@
#include "circular_buffer.h"
namespace gr {
- namespace audio {
+namespace audio {
- /*!
- * \brief audio sink using OSX
- * \ingroup audio_blk
- *
- * input signature is one or two streams of floats.
- * Input samples must be in the range [-1,1].
- */
-
- class osx_sink : public sink
- {
- protected:
-
- Float64 d_input_sample_rate;
- UInt32 d_n_user_channels, d_n_dev_channels, d_n_buffer_channels;
- UInt32 d_queue_sample_count, d_buffer_size_samples;
- bool d_ok_to_block, d_do_reset, d_hardware_changed;
- bool d_using_default_device, d_waiting_for_data;
- gr::thread::mutex d_internal;
- gr::thread::condition_variable d_cond_data;
- std::vector < circular_buffer < float > *> d_buffers;
- std::string d_desired_name, d_selected_name;
-
- // AudioUnits and Such
+/*!
+ * \brief audio sink using OSX
+ * \ingroup audio_blk
+ *
+ * input signature is one or two streams of floats.
+ * Input samples must be in the range [-1,1].
+ */
- AudioUnit d_output_au;
- AudioDeviceID d_output_ad_id;
- AudioStreamBasicDescription d_stream_format;
+class osx_sink : public sink
+{
+protected:
+ Float64 d_input_sample_rate;
+ UInt32 d_n_user_channels, d_n_dev_channels, d_n_buffer_channels;
+ UInt32 d_queue_sample_count, d_buffer_size_samples;
+ bool d_ok_to_block, d_do_reset, d_hardware_changed;
+ bool d_using_default_device, d_waiting_for_data;
+ gr::thread::mutex d_internal;
+ gr::thread::condition_variable d_cond_data;
+ std::vector<circular_buffer<float>*> d_buffers;
+ std::string d_desired_name, d_selected_name;
- public:
+ // AudioUnits and Such
- osx_sink(int sample_rate,
- const std::string& device_name,
- bool ok_to_block);
+ AudioUnit d_output_au;
+ AudioDeviceID d_output_ad_id;
+ AudioStreamBasicDescription d_stream_format;
- inline virtual ~osx_sink() {
- teardown();
- }
+public:
+ osx_sink(int sample_rate, const std::string& device_name, bool ok_to_block);
- virtual bool check_topology(int ninputs, int noutputs);
- virtual bool start();
- virtual bool stop();
+ inline virtual ~osx_sink() { teardown(); }
- virtual int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
+ virtual bool check_topology(int ninputs, int noutputs);
+ virtual bool start();
+ virtual bool stop();
- inline void reset(bool hardware_changed) {
- d_hardware_changed = hardware_changed;
- d_do_reset = true;
- }
+ virtual int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
- private:
+ inline void reset(bool hardware_changed)
+ {
+ d_hardware_changed = hardware_changed;
+ d_do_reset = true;
+ }
- bool is_running();
+private:
+ bool is_running();
- void setup();
+ void setup();
- void teardown();
+ void teardown();
- void check_channels(bool force_reset);
+ void check_channels(bool force_reset);
- static OSStatus au_output_callback
- (void* in_ref_con,
- AudioUnitRenderActionFlags* io_action_flags,
- const AudioTimeStamp* in_time_stamp,
- UInt32 in_bus_number,
- UInt32 in_number_frames,
- AudioBufferList* io_data);
+ static OSStatus au_output_callback(void* in_ref_con,
+ AudioUnitRenderActionFlags* io_action_flags,
+ const AudioTimeStamp* in_time_stamp,
+ UInt32 in_bus_number,
+ UInt32 in_number_frames,
+ AudioBufferList* io_data);
#ifndef GR_USE_OLD_AUDIO_UNIT
- // OSX 10.4 and newer
+ // OSX 10.4 and newer
- static OSStatus hardware_listener
- (AudioObjectID in_object_id,
- UInt32 in_num_addresses,
- const AudioObjectPropertyAddress in_addresses[],
- void* in_client_data);
+ static OSStatus hardware_listener(AudioObjectID in_object_id,
+ UInt32 in_num_addresses,
+ const AudioObjectPropertyAddress in_addresses[],
+ void* in_client_data);
- static OSStatus default_listener
- (AudioObjectID in_object_id,
- UInt32 in_num_addresses,
- const AudioObjectPropertyAddress in_addresses[],
- void* in_client_data);
+ static OSStatus default_listener(AudioObjectID in_object_id,
+ UInt32 in_num_addresses,
+ const AudioObjectPropertyAddress in_addresses[],
+ void* in_client_data);
#else
- // OSX 10.6 and older; removed as of 10.7
+ // OSX 10.6 and older; removed as of 10.7
- static OSStatus hardware_listener
- (AudioHardwarePropertyID in_property_id,
- void* in_client_data);
+ static OSStatus hardware_listener(AudioHardwarePropertyID in_property_id,
+ void* in_client_data);
- static OSStatus default_listener
- (AudioHardwarePropertyID in_property_id,
- void* in_client_data);
+ static OSStatus default_listener(AudioHardwarePropertyID in_property_id,
+ void* in_client_data);
#endif
-
- };
- } /* namespace audio */
+};
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_AUDIO_OSX_SINK_H */
diff --git a/gr-audio/lib/osx/osx_source.cc b/gr-audio/lib/osx/osx_source.cc
index 48001e2638..5dfd2b8390 100644
--- a/gr-audio/lib/osx/osx_source.cc
+++ b/gr-audio/lib/osx/osx_source.cc
@@ -32,477 +32,466 @@
#include <stdexcept>
namespace gr {
- namespace audio {
-
- source::sptr
- osx_source_fcn(int sampling_rate,
- const std::string& device_name,
- bool ok_to_block)
- {
- return source::sptr
- (new osx_source(sampling_rate, device_name, ok_to_block));
- }
-
- static std::string
- default_device_name()
- {
- return prefs::singleton()->get_string
- ("audio_osx", "default_input_device", "built-in");
- }
-
- osx_source::osx_source
- (int sample_rate,
- const std::string& device_name,
- bool ok_to_block)
- : sync_block("audio_osx_source",
- io_signature::make(0, 0, 0),
- io_signature::make(0, 0, 0)),
- d_device_sample_rate(0.0), d_output_sample_rate(0.0),
- d_input_buffer_size_frames(0), d_input_buffer_size_bytes(0),
- d_output_buffer_size_frames(0), d_output_buffer_size_bytes(0),
- d_device_buffer_size_frames(0), d_device_buffer_size_bytes(0),
- d_lead_size_frames(0), d_lead_size_bytes(0),
- d_trail_size_frames(0), d_trail_size_bytes(0),
- d_extra_buffer_size_frames(0), d_extra_buffer_size_bytes(0),
- d_queue_sample_count(0), d_buffer_sample_count(0),
- d_n_available_input_frames(0), d_n_actual_input_frames(0),
- d_n_user_channels(0), d_n_dev_channels(0),
- d_ok_to_block(ok_to_block), d_pass_through(false),
- d_waiting_for_data(false), d_do_reset(false),
- d_hardware_changed(false), d_using_default_device(false),
- d_desired_name(device_name.empty() ? default_device_name()
- : device_name),
- d_input_ad_id(0), d_input_au(0), d_input_buffer(0),
- d_output_buffer(0), d_audio_converter(0)
- {
- // set the desired output sample rate
-
- if(sample_rate <= 0) {
- GR_LOG_ERROR(d_logger, boost::format
- ("Invalid Sample Rate: %d")
- % sample_rate);
+namespace audio {
+
+source::sptr
+osx_source_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block)
+{
+ return source::sptr(new osx_source(sampling_rate, device_name, ok_to_block));
+}
+
+static std::string default_device_name()
+{
+ return prefs::singleton()->get_string(
+ "audio_osx", "default_input_device", "built-in");
+}
+
+osx_source::osx_source(int sample_rate, const std::string& device_name, bool ok_to_block)
+ : sync_block(
+ "audio_osx_source", io_signature::make(0, 0, 0), io_signature::make(0, 0, 0)),
+ d_device_sample_rate(0.0),
+ d_output_sample_rate(0.0),
+ d_input_buffer_size_frames(0),
+ d_input_buffer_size_bytes(0),
+ d_output_buffer_size_frames(0),
+ d_output_buffer_size_bytes(0),
+ d_device_buffer_size_frames(0),
+ d_device_buffer_size_bytes(0),
+ d_lead_size_frames(0),
+ d_lead_size_bytes(0),
+ d_trail_size_frames(0),
+ d_trail_size_bytes(0),
+ d_extra_buffer_size_frames(0),
+ d_extra_buffer_size_bytes(0),
+ d_queue_sample_count(0),
+ d_buffer_sample_count(0),
+ d_n_available_input_frames(0),
+ d_n_actual_input_frames(0),
+ d_n_user_channels(0),
+ d_n_dev_channels(0),
+ d_ok_to_block(ok_to_block),
+ d_pass_through(false),
+ d_waiting_for_data(false),
+ d_do_reset(false),
+ d_hardware_changed(false),
+ d_using_default_device(false),
+ d_desired_name(device_name.empty() ? default_device_name() : device_name),
+ d_input_ad_id(0),
+ d_input_au(0),
+ d_input_buffer(0),
+ d_output_buffer(0),
+ d_audio_converter(0)
+{
+ // set the desired output sample rate
+
+ if (sample_rate <= 0) {
+ GR_LOG_ERROR(d_logger, boost::format("Invalid Sample Rate: %d") % sample_rate);
throw std::invalid_argument("audio_osx_source");
- }
- else {
+ } else {
d_output_sample_rate = (Float64)sample_rate;
- }
-
- // set up for audio input using the stored desired parameters
-
- setup();
}
- void osx_source::setup()
- {
- OSStatus err = noErr;
+ // set up for audio input using the stored desired parameters
- // set the default input audio device id to "unknown"
+ setup();
+}
- d_input_ad_id = kAudioDeviceUnknown;
+void osx_source::setup()
+{
+ OSStatus err = noErr;
- // try to find the input audio device, if specified
+ // set the default input audio device id to "unknown"
- std::vector < AudioDeviceID > all_ad_ids;
- std::vector < std::string > all_names;
+ d_input_ad_id = kAudioDeviceUnknown;
- osx::find_audio_devices
- (d_desired_name, true,
- &all_ad_ids, &all_names);
+ // try to find the input audio device, if specified
- // check number of device(s) returned
+ std::vector<AudioDeviceID> all_ad_ids;
+ std::vector<std::string> all_names;
- if (d_desired_name.length() != 0) {
- if (all_ad_ids.size() == 1) {
+ osx::find_audio_devices(d_desired_name, true, &all_ad_ids, &all_names);
- // exactly 1 match was found; see if it was partial
+ // check number of device(s) returned
- if (all_names[0].compare(d_desired_name) != 0) {
+ if (d_desired_name.length() != 0) {
+ if (all_ad_ids.size() == 1) {
- // yes: log the full device name
- GR_LOG_INFO(d_logger, boost::format
- ("Using input audio device '%s'.")
- % all_names[0]);
+ // exactly 1 match was found; see if it was partial
- }
+ if (all_names[0].compare(d_desired_name) != 0) {
- // store info on this device
+ // yes: log the full device name
+ GR_LOG_INFO(d_logger,
+ boost::format("Using input audio device '%s'.") %
+ all_names[0]);
+ }
- d_input_ad_id = all_ad_ids[0];
- d_selected_name = all_names[0];
+ // store info on this device
- } else {
+ d_input_ad_id = all_ad_ids[0];
+ d_selected_name = all_names[0];
- // either 0 or more than 1 device was found; get all input
- // device names, print those, and error out.
+ } else {
- osx::find_audio_devices("", true, NULL, &all_names);
+ // either 0 or more than 1 device was found; get all input
+ // device names, print those, and error out.
- std::string err_str("\n\nA unique input audio device name "
- "matching the string '");
- err_str += d_desired_name;
- err_str += "' was not found.\n\n";
- err_str += "The current known input audio device name";
- err_str += ((all_names.size() > 1) ? "s are" : " is");
- err_str += ":\n";
- for (UInt32 nn = 0; nn < all_names.size(); ++nn) {
- err_str += " " + all_names[nn] + "\n";
- }
- GR_LOG_ERROR(d_logger, boost::format(err_str));
- throw std::runtime_error("audio_osx_source::setup");
+ osx::find_audio_devices("", true, NULL, &all_names);
- }
- }
+ std::string err_str("\n\nA unique input audio device name "
+ "matching the string '");
+ err_str += d_desired_name;
+ err_str += "' was not found.\n\n";
+ err_str += "The current known input audio device name";
+ err_str += ((all_names.size() > 1) ? "s are" : " is");
+ err_str += ":\n";
+ for (UInt32 nn = 0; nn < all_names.size(); ++nn) {
+ err_str += " " + all_names[nn] + "\n";
+ }
+ GR_LOG_ERROR(d_logger, boost::format(err_str));
+ throw std::runtime_error("audio_osx_source::setup");
+ }
+ }
- // if no input audio device id was found or no specific device
- // name was provided, use the default input audio device id as
- // set in System Preferences.
+ // if no input audio device id was found or no specific device
+ // name was provided, use the default input audio device id as
+ // set in System Preferences.
- if (d_input_ad_id == kAudioDeviceUnknown) {
+ if (d_input_ad_id == kAudioDeviceUnknown) {
UInt32 prop_size = (UInt32)sizeof(AudioDeviceID);
AudioObjectPropertyAddress ao_address = {
- kAudioHardwarePropertyDefaultInputDevice,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
+ kAudioHardwarePropertyDefaultInputDevice,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster
};
- err = AudioObjectGetPropertyData
- (kAudioObjectSystemObject, &ao_address,
- 0, NULL, &prop_size, &d_input_ad_id);
- check_error_and_throw
- (err, "Getting the default input audio device ID failed",
- "audio_osx_source::setup");
-
- {
- // retrieve the device name; max name length is 64 characters.
-
- UInt32 prop_size = 65;
- char c_name_buf[prop_size];
- memset((void*)c_name_buf, 0, (size_t)prop_size);
- --prop_size;
-
- AudioObjectPropertyAddress ao_address = {
- kAudioDevicePropertyDeviceName,
- kAudioDevicePropertyScopeInput, 0
- };
-
- if ((err = AudioObjectGetPropertyData
- (d_input_ad_id, &ao_address, 0, NULL,
- &prop_size, (void*)c_name_buf)) != noErr) {
-
- check_error(err, "Unable to retrieve input audio device name");
-
- } else {
-
- GR_LOG_INFO(d_logger, boost::format
- ("\n\nUsing input audio device '%s'.\n ... "
- "which is the current default input audio"
- " device.\n Changing the default input"
- " audio device in the System Preferences"
- " will \n result in changing it here, too "
- "(with an internal reconfiguration).\n") %
- std::string(c_name_buf));
-
- }
-
- d_selected_name = c_name_buf;
-
- }
+ err = AudioObjectGetPropertyData(
+ kAudioObjectSystemObject, &ao_address, 0, NULL, &prop_size, &d_input_ad_id);
+ check_error_and_throw(err,
+ "Getting the default input audio device ID failed",
+ "audio_osx_source::setup");
+
+ {
+ // retrieve the device name; max name length is 64 characters.
+
+ UInt32 prop_size = 65;
+ char c_name_buf[prop_size];
+ memset((void*)c_name_buf, 0, (size_t)prop_size);
+ --prop_size;
+
+ AudioObjectPropertyAddress ao_address = { kAudioDevicePropertyDeviceName,
+ kAudioDevicePropertyScopeInput,
+ 0 };
+
+ if ((err = AudioObjectGetPropertyData(d_input_ad_id,
+ &ao_address,
+ 0,
+ NULL,
+ &prop_size,
+ (void*)c_name_buf)) != noErr) {
+
+ check_error(err, "Unable to retrieve input audio device name");
+
+ } else {
+
+ GR_LOG_INFO(d_logger,
+ boost::format("\n\nUsing input audio device '%s'.\n ... "
+ "which is the current default input audio"
+ " device.\n Changing the default input"
+ " audio device in the System Preferences"
+ " will \n result in changing it here, too "
+ "(with an internal reconfiguration).\n") %
+ std::string(c_name_buf));
+ }
- d_using_default_device = true;
+ d_selected_name = c_name_buf;
+ }
- }
+ d_using_default_device = true;
+ }
- // retrieve the total number of channels for the selected input
- // audio device
+ // retrieve the total number of channels for the selected input
+ // audio device
- osx::get_num_channels_for_audio_device_id
- (d_input_ad_id, &d_n_dev_channels, NULL);
+ osx::get_num_channels_for_audio_device_id(d_input_ad_id, &d_n_dev_channels, NULL);
- // set the block output signature, if not already set
- // (d_n_user_channels is set in check_topology, which is called
- // before the flow-graph is running)
+ // set the block output signature, if not already set
+ // (d_n_user_channels is set in check_topology, which is called
+ // before the flow-graph is running)
- if (d_n_user_channels == 0) {
- set_output_signature(io_signature::make
- (1, d_n_dev_channels, sizeof(float)));
- }
+ if (d_n_user_channels == 0) {
+ set_output_signature(io_signature::make(1, d_n_dev_channels, sizeof(float)));
+ }
- // set the interim buffer size; to work with the GR scheduler,
- // must be at least 16kB. Pick 50 kB since that's plenty yet
- // not very much.
+ // set the interim buffer size; to work with the GR scheduler,
+ // must be at least 16kB. Pick 50 kB since that's plenty yet
+ // not very much.
- d_buffer_sample_count = (d_output_sample_rate < 50000.0 ?
- 50000 : (UInt32)d_output_sample_rate);
+ d_buffer_sample_count =
+ (d_output_sample_rate < 50000.0 ? 50000 : (UInt32)d_output_sample_rate);
#if _OSX_AU_DEBUG_
- std::cerr << "source(): max # samples = "
- << d_buffer_sample_count << std::endl;
+ std::cerr << "source(): max # samples = " << d_buffer_sample_count << std::endl;
#endif
- // create the default AudioUnit for input
+ // create the default AudioUnit for input
- // Open the default input unit
+ // Open the default input unit
#ifndef GR_USE_OLD_AUDIO_UNIT
- AudioComponentDescription desc;
+ AudioComponentDescription desc;
#else
- ComponentDescription desc;
+ ComponentDescription desc;
#endif
- desc.componentType = kAudioUnitType_Output;
- desc.componentSubType = kAudioUnitSubType_HALOutput;
- desc.componentManufacturer = kAudioUnitManufacturer_Apple;
- desc.componentFlags = 0;
- desc.componentFlagsMask = 0;
+ desc.componentType = kAudioUnitType_Output;
+ desc.componentSubType = kAudioUnitSubType_HALOutput;
+ desc.componentManufacturer = kAudioUnitManufacturer_Apple;
+ desc.componentFlags = 0;
+ desc.componentFlagsMask = 0;
#ifndef GR_USE_OLD_AUDIO_UNIT
- AudioComponent comp = AudioComponentFindNext(NULL, &desc);
- if(!comp) {
- GR_LOG_FATAL(d_logger, boost::format
- ("AudioComponentFindNext Failed"));
+ AudioComponent comp = AudioComponentFindNext(NULL, &desc);
+ if (!comp) {
+ GR_LOG_FATAL(d_logger, boost::format("AudioComponentFindNext Failed"));
throw std::runtime_error("audio_osx_source::setup");
- }
- err = AudioComponentInstanceNew(comp, &d_input_au);
- check_error_and_throw(err, "AudioComponentInstanceNew Failed",
- "audio_osx_source::setup");
+ }
+ err = AudioComponentInstanceNew(comp, &d_input_au);
+ check_error_and_throw(
+ err, "AudioComponentInstanceNew Failed", "audio_osx_source::setup");
#else
- Component comp = FindNextComponent(NULL, &desc);
- if(!comp) {
- GR_LOG_FATAL(d_logger, boost::format
- ("FindNextComponent Failed"));
+ Component comp = FindNextComponent(NULL, &desc);
+ if (!comp) {
+ GR_LOG_FATAL(d_logger, boost::format("FindNextComponent Failed"));
throw std::runtime_error("audio_osx_source::setup");
- }
- err = OpenAComponent(comp, &d_input_au);
- check_error_and_throw(err, "OpenAComponent Failed",
- "audio_osx_source::setup");
+ }
+ err = OpenAComponent(comp, &d_input_au);
+ check_error_and_throw(err, "OpenAComponent Failed", "audio_osx_source::setup");
#endif
- // must enable the AUHAL for input and disable output
- // before setting the AUHAL's current device
-
- // Enable input on the AUHAL
-
- UInt32 enable_io = 1;
- err = AudioUnitSetProperty
- (d_input_au,
- kAudioOutputUnitProperty_EnableIO,
- kAudioUnitScope_Input, 1, // input element
- &enable_io, sizeof(enable_io));
- check_error_and_throw
- (err, "AudioUnitSetProperty Input Enable",
- "audio_osx_source::setup");
-
- // Disable output on the AUHAL
-
- enable_io = 0;
- err = AudioUnitSetProperty
- (d_input_au,
- kAudioOutputUnitProperty_EnableIO,
- kAudioUnitScope_Output, 0, // output element
- &enable_io, sizeof(enable_io));
- check_error_and_throw
- (err, "AudioUnitSetProperty Output Disable",
- "audio_osx_source::setup");
-
- // set the selected device ID as the current input device
-
- err = AudioUnitSetProperty
- (d_input_au, kAudioOutputUnitProperty_CurrentDevice,
- kAudioUnitScope_Global, 0,
- &d_input_ad_id, sizeof(d_input_ad_id));
- check_error_and_throw
- (err, "Setting selected input device as current failed",
- "audio_osx_source::setup");
-
- // Set up a callback function to retrieve input from the Audio Device
-
- AURenderCallbackStruct au_callback = {
- reinterpret_cast<AURenderCallback>
- (&osx_source::au_input_callback),
- reinterpret_cast<void*>(this)
- };
- UInt32 prop_size = (UInt32)sizeof(au_callback);
-
- err = AudioUnitSetProperty
- (d_input_au,
- kAudioOutputUnitProperty_SetInputCallback,
- kAudioUnitScope_Global, 0,
- &au_callback, prop_size);
- check_error_and_throw
- (err, "Set Input Callback",
- "audio_osx_source::setup");
-
- // Get the Stream Format (device side; cannot generally be changed)
-
- prop_size = (UInt32)sizeof(d_asbd_device);
- memset((void*)(&d_asbd_device), 0, (size_t)prop_size);
- err = AudioUnitGetProperty
- (d_input_au,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Input, 1,
- &d_asbd_device, &prop_size);
- check_error_and_throw
- (err, "Get Device Input Stream Format (before) failed",
- "audio_osx_source::setup");
+ // must enable the AUHAL for input and disable output
+ // before setting the AUHAL's current device
+
+ // Enable input on the AUHAL
+
+ UInt32 enable_io = 1;
+ err = AudioUnitSetProperty(d_input_au,
+ kAudioOutputUnitProperty_EnableIO,
+ kAudioUnitScope_Input,
+ 1, // input element
+ &enable_io,
+ sizeof(enable_io));
+ check_error_and_throw(
+ err, "AudioUnitSetProperty Input Enable", "audio_osx_source::setup");
+
+ // Disable output on the AUHAL
+
+ enable_io = 0;
+ err = AudioUnitSetProperty(d_input_au,
+ kAudioOutputUnitProperty_EnableIO,
+ kAudioUnitScope_Output,
+ 0, // output element
+ &enable_io,
+ sizeof(enable_io));
+ check_error_and_throw(
+ err, "AudioUnitSetProperty Output Disable", "audio_osx_source::setup");
+
+ // set the selected device ID as the current input device
+
+ err = AudioUnitSetProperty(d_input_au,
+ kAudioOutputUnitProperty_CurrentDevice,
+ kAudioUnitScope_Global,
+ 0,
+ &d_input_ad_id,
+ sizeof(d_input_ad_id));
+ check_error_and_throw(err,
+ "Setting selected input device as current failed",
+ "audio_osx_source::setup");
+
+ // Set up a callback function to retrieve input from the Audio Device
+
+ AURenderCallbackStruct au_callback = { reinterpret_cast<AURenderCallback>(
+ &osx_source::au_input_callback),
+ reinterpret_cast<void*>(this) };
+ UInt32 prop_size = (UInt32)sizeof(au_callback);
+
+ err = AudioUnitSetProperty(d_input_au,
+ kAudioOutputUnitProperty_SetInputCallback,
+ kAudioUnitScope_Global,
+ 0,
+ &au_callback,
+ prop_size);
+ check_error_and_throw(err, "Set Input Callback", "audio_osx_source::setup");
+
+ // Get the Stream Format (device side; cannot generally be changed)
+
+ prop_size = (UInt32)sizeof(d_asbd_device);
+ memset((void*)(&d_asbd_device), 0, (size_t)prop_size);
+ err = AudioUnitGetProperty(d_input_au,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input,
+ 1,
+ &d_asbd_device,
+ &prop_size);
+ check_error_and_throw(
+ err, "Get Device Input Stream Format (before) failed", "audio_osx_source::setup");
#if _OSX_AU_DEBUG_
- std::cerr << std::endl << "---- Device Stream Format (before) ----"
- << std::endl << d_asbd_device << std::endl << std::endl;
+ std::cerr << std::endl
+ << "---- Device Stream Format (before) ----" << std::endl
+ << d_asbd_device << std::endl
+ << std::endl;
#endif
- // try to set the device (input) side of the audio device to the
- // sample rate of this source. This will likely fail, and
- // that's OK; just ignore the error since we can accomplish
- // audio input in other ways.
-
- prop_size = (UInt32)sizeof(d_asbd_device);
- d_asbd_device.mSampleRate = d_output_sample_rate;
- err = AudioUnitSetProperty
- (d_input_au,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Input, 1,
- &d_asbd_device, prop_size);
+ // try to set the device (input) side of the audio device to the
+ // sample rate of this source. This will likely fail, and
+ // that's OK; just ignore the error since we can accomplish
+ // audio input in other ways.
+
+ prop_size = (UInt32)sizeof(d_asbd_device);
+ d_asbd_device.mSampleRate = d_output_sample_rate;
+ err = AudioUnitSetProperty(d_input_au,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input,
+ 1,
+ &d_asbd_device,
+ prop_size);
#if _OSX_AU_DEBUG_
- check_error
- (err, "Set Device Input Stream Format failed (expected)");
+ check_error(err, "Set Device Input Stream Format failed (expected)");
#endif
- memset((void*)(&d_asbd_device), 0, (size_t)prop_size);
- err = AudioUnitGetProperty
- (d_input_au,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Input, 1,
- &d_asbd_device, &prop_size);
- check_error_and_throw
- (err, "Get Device Input Stream Format (after) failed",
- "audio_osx_source::setup");
+ memset((void*)(&d_asbd_device), 0, (size_t)prop_size);
+ err = AudioUnitGetProperty(d_input_au,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Input,
+ 1,
+ &d_asbd_device,
+ &prop_size);
+ check_error_and_throw(
+ err, "Get Device Input Stream Format (after) failed", "audio_osx_source::setup");
#if _OSX_AU_DEBUG_
- std::cerr << std::endl << "---- Device Stream Format (after) ----"
- << std::endl << d_asbd_device << std::endl << std::endl;
+ std::cerr << std::endl
+ << "---- Device Stream Format (after) ----" << std::endl
+ << d_asbd_device << std::endl
+ << std::endl;
#endif
- d_device_sample_rate = d_asbd_device.mSampleRate;
+ d_device_sample_rate = d_asbd_device.mSampleRate;
- // Get the Stream Format (client side; might be changeable)
+ // Get the Stream Format (client side; might be changeable)
- prop_size = (UInt32)sizeof(d_asbd_client);
- memset((void*)(&d_asbd_client), 0, (size_t)prop_size);
- err = AudioUnitGetProperty
- (d_input_au,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Output, 1,
- &d_asbd_client, &prop_size);
- check_error_and_throw
- (err, "Get Device Output Stream Format (before) failed",
- "audio_osx_source::setup");
+ prop_size = (UInt32)sizeof(d_asbd_client);
+ memset((void*)(&d_asbd_client), 0, (size_t)prop_size);
+ err = AudioUnitGetProperty(d_input_au,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Output,
+ 1,
+ &d_asbd_client,
+ &prop_size);
+ check_error_and_throw(err,
+ "Get Device Output Stream Format (before) failed",
+ "audio_osx_source::setup");
#if _OSX_AU_DEBUG_
- std::cerr << "---- Client Stream Format (Before) ----"
- << std::endl << d_asbd_client << std::endl << std::endl;
+ std::cerr << "---- Client Stream Format (Before) ----" << std::endl
+ << d_asbd_client << std::endl
+ << std::endl;
#endif
- // Set the format of all the AUs to the
- // input/output devices channel count
+ // Set the format of all the AUs to the
+ // input/output devices channel count
- d_asbd_client.mFormatID = kAudioFormatLinearPCM;
- d_asbd_client.mFormatFlags = (kAudioFormatFlagIsFloat |
- kAudioFormatFlagIsPacked |
+ d_asbd_client.mFormatID = kAudioFormatLinearPCM;
+ d_asbd_client.mFormatFlags = (kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked |
kAudioFormatFlagIsNonInterleaved);
- if((d_asbd_client.mFormatID == kAudioFormatLinearPCM) &&
- (d_n_dev_channels == 1)) {
+ if ((d_asbd_client.mFormatID == kAudioFormatLinearPCM) && (d_n_dev_channels == 1)) {
d_asbd_client.mFormatFlags &= ~kLinearPCMFormatFlagIsNonInterleaved;
- }
- d_asbd_client.mBytesPerFrame = (UInt32)sizeof(float);
- d_asbd_client.mFramesPerPacket = 1;
- d_asbd_client.mBitsPerChannel = d_asbd_client.mBytesPerFrame * 8;
- d_asbd_client.mChannelsPerFrame = d_n_dev_channels;
- d_asbd_client.mBytesPerPacket = d_asbd_client.mBytesPerFrame;
-
- // according to Apple docs [see, e.g., Apple Technical Note
- // TN2091 "Device input using the HAL Output Audio Unit"], the
- // device input and output sample rate must be the same; do
- // sample rate conversion elsewhere.
-
- d_asbd_client.mSampleRate = d_asbd_device.mSampleRate;
- err = AudioUnitSetProperty
- (d_input_au,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Output, 1,
- &d_asbd_client, prop_size);
- check_error_and_throw
- (err, "Set Device Output Stream Format failed",
- "audio_osx_source::setup");
-
- // Get the Stream Format (client side), again
-
- prop_size = (UInt32)sizeof(d_asbd_client);
- memset((void*)(&d_asbd_client), 0, (size_t)prop_size);
- err = AudioUnitGetProperty
- (d_input_au,
- kAudioUnitProperty_StreamFormat,
- kAudioUnitScope_Output, 1,
- &d_asbd_client, &prop_size);
- check_error_and_throw
- (err, "Get Device Output Stream Format (after) failed",
- "audio_osx_source::setup");
+ }
+ d_asbd_client.mBytesPerFrame = (UInt32)sizeof(float);
+ d_asbd_client.mFramesPerPacket = 1;
+ d_asbd_client.mBitsPerChannel = d_asbd_client.mBytesPerFrame * 8;
+ d_asbd_client.mChannelsPerFrame = d_n_dev_channels;
+ d_asbd_client.mBytesPerPacket = d_asbd_client.mBytesPerFrame;
+
+ // according to Apple docs [see, e.g., Apple Technical Note
+ // TN2091 "Device input using the HAL Output Audio Unit"], the
+ // device input and output sample rate must be the same; do
+ // sample rate conversion elsewhere.
+
+ d_asbd_client.mSampleRate = d_asbd_device.mSampleRate;
+ err = AudioUnitSetProperty(d_input_au,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Output,
+ 1,
+ &d_asbd_client,
+ prop_size);
+ check_error_and_throw(
+ err, "Set Device Output Stream Format failed", "audio_osx_source::setup");
+
+ // Get the Stream Format (client side), again
+
+ prop_size = (UInt32)sizeof(d_asbd_client);
+ memset((void*)(&d_asbd_client), 0, (size_t)prop_size);
+ err = AudioUnitGetProperty(d_input_au,
+ kAudioUnitProperty_StreamFormat,
+ kAudioUnitScope_Output,
+ 1,
+ &d_asbd_client,
+ &prop_size);
+ check_error_and_throw(
+ err, "Get Device Output Stream Format (after) failed", "audio_osx_source::setup");
#if _OSX_AU_DEBUG_
- std::cerr << "---- Client Stream Format (After) ----"
- << std::endl << d_asbd_client << std::endl << std::endl;
+ std::cerr << "---- Client Stream Format (After) ----" << std::endl
+ << d_asbd_client << std::endl
+ << std::endl;
#endif
- d_pass_through = (d_asbd_client.mSampleRate == d_output_sample_rate);
+ d_pass_through = (d_asbd_client.mSampleRate == d_output_sample_rate);
- if (d_pass_through) {
+ if (d_pass_through) {
// no need to do conversion if d_asbd_client matches user wants
d_lead_size_frames = d_trail_size_frames = 0L;
- }
- else {
+ } else {
- // create an ASBD for the user's wants
+ // create an ASBD for the user's wants
- memset((void*)(&d_asbd_user), 0, sizeof(d_asbd_user));
- d_asbd_user.mSampleRate = d_output_sample_rate;
- d_asbd_user.mFormatID = kAudioFormatLinearPCM;
- d_asbd_user.mFormatFlags = (kLinearPCMFormatFlagIsFloat |
- GR_PCM_ENDIANNESS |
- kLinearPCMFormatFlagIsPacked |
- kAudioFormatFlagIsNonInterleaved);
- d_asbd_user.mBytesPerPacket = (UInt32)sizeof(float);
- d_asbd_user.mFramesPerPacket = 1;
- d_asbd_user.mBytesPerFrame = d_asbd_user.mBytesPerPacket;
- d_asbd_user.mChannelsPerFrame = d_n_dev_channels;
- d_asbd_user.mBitsPerChannel = d_asbd_user.mBytesPerPacket * 8;
+ memset((void*)(&d_asbd_user), 0, sizeof(d_asbd_user));
+ d_asbd_user.mSampleRate = d_output_sample_rate;
+ d_asbd_user.mFormatID = kAudioFormatLinearPCM;
+ d_asbd_user.mFormatFlags =
+ (kLinearPCMFormatFlagIsFloat | GR_PCM_ENDIANNESS |
+ kLinearPCMFormatFlagIsPacked | kAudioFormatFlagIsNonInterleaved);
+ d_asbd_user.mBytesPerPacket = (UInt32)sizeof(float);
+ d_asbd_user.mFramesPerPacket = 1;
+ d_asbd_user.mBytesPerFrame = d_asbd_user.mBytesPerPacket;
+ d_asbd_user.mChannelsPerFrame = d_n_dev_channels;
+ d_asbd_user.mBitsPerChannel = d_asbd_user.mBytesPerPacket * 8;
// Create the audio converter
- err = AudioConverterNew(&d_asbd_client,
- &d_asbd_user,
- &d_audio_converter);
- check_error_and_throw
- (err, "AudioConverterNew failed",
- "audio_osx_source::setup");
+ err = AudioConverterNew(&d_asbd_client, &d_asbd_user, &d_audio_converter);
+ check_error_and_throw(err, "AudioConverterNew failed", "audio_osx_source::setup");
// Set the audio converter sample rate quality to "max" ...
// requires more samples, but should sound nicer
UInt32 ac_quality = kAudioConverterQuality_Max;
prop_size = (UInt32)sizeof(ac_quality);
- err = AudioConverterSetProperty
- (d_audio_converter,
- kAudioConverterSampleRateConverterQuality,
- prop_size, &ac_quality);
- check_error_and_throw
- (err, "Set Sample Rate Converter Quality failed",
- "audio_osx_source::setup");
+ err = AudioConverterSetProperty(d_audio_converter,
+ kAudioConverterSampleRateConverterQuality,
+ prop_size,
+ &ac_quality);
+ check_error_and_throw(
+ err, "Set Sample Rate Converter Quality failed", "audio_osx_source::setup");
// set the audio converter's prime method to "pre",
// which uses both leading and trailing frames
@@ -512,850 +501,767 @@ namespace gr {
UInt32 ac_prime_method = kConverterPrimeMethod_Pre;
prop_size = (UInt32)sizeof(ac_prime_method);
- err = AudioConverterSetProperty
- (d_audio_converter,
- kAudioConverterPrimeMethod,
- prop_size, &ac_prime_method);
- check_error_and_throw
- (err, "Set Prime Method failed",
- "audio_osx_source::setup");
+ err = AudioConverterSetProperty(
+ d_audio_converter, kAudioConverterPrimeMethod, prop_size, &ac_prime_method);
+ check_error_and_throw(err, "Set Prime Method failed", "audio_osx_source::setup");
// Get the size of the priming I/O buffer space to allow for
// pre-allocated buffers
- AudioConverterPrimeInfo ac_prime_info = {0, 0};
+ AudioConverterPrimeInfo ac_prime_info = { 0, 0 };
prop_size = (UInt32)sizeof(ac_prime_info);
- err = AudioConverterGetProperty
- (d_audio_converter,
- kAudioConverterPrimeInfo,
- &prop_size, &ac_prime_info);
- check_error_and_throw
- (err, "Get Prime Info failed",
- "audio_osx_source::setup");
-
- d_lead_size_frames = ac_prime_info.leadingFrames;
- d_trail_size_frames = ac_prime_info.trailingFrames;
- }
-
- d_lead_size_bytes = d_lead_size_frames * sizeof(float);
- d_trail_size_bytes = d_trail_size_frames * sizeof(float);
-
- prop_size = (UInt32)sizeof(d_device_buffer_size_frames);
- err = AudioUnitGetProperty
- (d_input_au,
- kAudioDevicePropertyBufferFrameSize,
- kAudioUnitScope_Global, 0,
- &d_device_buffer_size_frames, &prop_size);
- check_error_and_throw
- (err, "Get Buffer Frame Size failed",
- "audio_osx_source::setup");
-
- d_device_buffer_size_bytes = (d_device_buffer_size_frames *
- sizeof(float));
- d_input_buffer_size_bytes = (d_device_buffer_size_bytes +
- d_lead_size_bytes);
- d_input_buffer_size_frames = (d_device_buffer_size_frames +
- d_lead_size_frames);
-
- // outBufSizeBytes = floor (inBufSizeBytes * rate_out / rate_in)
- // since this is rarely exact, we need another buffer to hold
- // "extra" samples not processed at any given sampling period
- // this buffer must be at least 4 floats in size, but generally
- // follows the rule that
- // extraBufSize = ceil (rate_in / rate_out)*sizeof(float)
-
- d_extra_buffer_size_frames =
- ((UInt32)ceil(d_device_sample_rate /
- d_output_sample_rate) *
- sizeof(float));
- if(d_extra_buffer_size_frames < 4)
+ err = AudioConverterGetProperty(
+ d_audio_converter, kAudioConverterPrimeInfo, &prop_size, &ac_prime_info);
+ check_error_and_throw(err, "Get Prime Info failed", "audio_osx_source::setup");
+
+ d_lead_size_frames = ac_prime_info.leadingFrames;
+ d_trail_size_frames = ac_prime_info.trailingFrames;
+ }
+
+ d_lead_size_bytes = d_lead_size_frames * sizeof(float);
+ d_trail_size_bytes = d_trail_size_frames * sizeof(float);
+
+ prop_size = (UInt32)sizeof(d_device_buffer_size_frames);
+ err = AudioUnitGetProperty(d_input_au,
+ kAudioDevicePropertyBufferFrameSize,
+ kAudioUnitScope_Global,
+ 0,
+ &d_device_buffer_size_frames,
+ &prop_size);
+ check_error_and_throw(err, "Get Buffer Frame Size failed", "audio_osx_source::setup");
+
+ d_device_buffer_size_bytes = (d_device_buffer_size_frames * sizeof(float));
+ d_input_buffer_size_bytes = (d_device_buffer_size_bytes + d_lead_size_bytes);
+ d_input_buffer_size_frames = (d_device_buffer_size_frames + d_lead_size_frames);
+
+ // outBufSizeBytes = floor (inBufSizeBytes * rate_out / rate_in)
+ // since this is rarely exact, we need another buffer to hold
+ // "extra" samples not processed at any given sampling period
+ // this buffer must be at least 4 floats in size, but generally
+ // follows the rule that
+ // extraBufSize = ceil (rate_in / rate_out)*sizeof(float)
+
+ d_extra_buffer_size_frames =
+ ((UInt32)ceil(d_device_sample_rate / d_output_sample_rate) * sizeof(float));
+ if (d_extra_buffer_size_frames < 4)
d_extra_buffer_size_frames = 4;
- d_extra_buffer_size_bytes =
- d_extra_buffer_size_frames * sizeof(float);
-
- d_output_buffer_size_frames =
- (UInt32)ceil(((Float64)d_input_buffer_size_frames) *
- d_output_sample_rate / d_device_sample_rate);
- d_output_buffer_size_bytes =
- d_output_buffer_size_frames * sizeof(float);
- d_input_buffer_size_frames += d_extra_buffer_size_frames;
-
- // pre-alloc all CoreAudio buffers
-
- alloc_audio_buffer_list
- (&d_input_buffer, d_n_dev_channels,
- d_input_buffer_size_bytes);
- if(!d_pass_through) {
- alloc_audio_buffer_list
- (&d_output_buffer, d_n_dev_channels,
- d_output_buffer_size_bytes);
- }
- else {
+ d_extra_buffer_size_bytes = d_extra_buffer_size_frames * sizeof(float);
+
+ d_output_buffer_size_frames =
+ (UInt32)ceil(((Float64)d_input_buffer_size_frames) * d_output_sample_rate /
+ d_device_sample_rate);
+ d_output_buffer_size_bytes = d_output_buffer_size_frames * sizeof(float);
+ d_input_buffer_size_frames += d_extra_buffer_size_frames;
+
+ // pre-alloc all CoreAudio buffers
+
+ alloc_audio_buffer_list(&d_input_buffer, d_n_dev_channels, d_input_buffer_size_bytes);
+ if (!d_pass_through) {
+ alloc_audio_buffer_list(
+ &d_output_buffer, d_n_dev_channels, d_output_buffer_size_bytes);
+ } else {
d_output_buffer = d_input_buffer;
- }
-
- // allocate the output circular buffer(s), one per device
- // channel (the user may select fewer channels; those buffers
- // just won't get used).
-
- d_buffers.resize(d_n_dev_channels);
- for(UInt32 nn = 0; nn < d_n_dev_channels; ++nn) {
- d_buffers[nn] = new circular_buffer<float>
- (d_buffer_sample_count, false, false);
- }
-
- // clear the RunLoop (whatever that is); needed, for some
- // reason, before a listener will work.
-
- {
- CFRunLoopRef the_run_loop = NULL;
- AudioObjectPropertyAddress property = {
- kAudioHardwarePropertyRunLoop,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
- prop_size = (UInt32)sizeof(the_run_loop);
- err = AudioObjectSetPropertyData
- (kAudioObjectSystemObject, &property, 0, NULL,
- prop_size, &the_run_loop);
- check_error(err, "Clearing RunLoop failed; "
- "Audio Input Device Listener might not work.");
- }
-
- // set up listeners
+ }
-#ifndef GR_USE_OLD_AUDIO_UNIT
+ // allocate the output circular buffer(s), one per device
+ // channel (the user may select fewer channels; those buffers
+ // just won't get used).
- // 10.4 and newer
+ d_buffers.resize(d_n_dev_channels);
+ for (UInt32 nn = 0; nn < d_n_dev_channels; ++nn) {
+ d_buffers[nn] = new circular_buffer<float>(d_buffer_sample_count, false, false);
+ }
- {
+ // clear the RunLoop (whatever that is); needed, for some
+ // reason, before a listener will work.
- // set up a listener if hardware changes (at all)
+ {
+ CFRunLoopRef the_run_loop = NULL;
+ AudioObjectPropertyAddress property = { kAudioHardwarePropertyRunLoop,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster };
+ prop_size = (UInt32)sizeof(the_run_loop);
+ err = AudioObjectSetPropertyData(
+ kAudioObjectSystemObject, &property, 0, NULL, prop_size, &the_run_loop);
+ check_error(err,
+ "Clearing RunLoop failed; "
+ "Audio Input Device Listener might not work.");
+ }
- AudioObjectPropertyAddress property = {
- kAudioHardwarePropertyDevices,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
+ // set up listeners
- err = AudioObjectAddPropertyListener
- (kAudioObjectSystemObject, &property,
- reinterpret_cast<AudioObjectPropertyListenerProc>
- (&osx_source::hardware_listener),
- reinterpret_cast<void*>(this));
- check_error(err, "Adding Audio Hardware Listener failed");
- }
+#ifndef GR_USE_OLD_AUDIO_UNIT
- if (d_using_default_device) {
+ // 10.4 and newer
- // set up a listener if default hardware input device changes
+ {
+
+ // set up a listener if hardware changes (at all)
- AudioObjectPropertyAddress property = {
- kAudioHardwarePropertyDefaultInputDevice,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
+ AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster };
- err = AudioObjectAddPropertyListener
- (kAudioObjectSystemObject, &property,
- reinterpret_cast<AudioObjectPropertyListenerProc>
- (&osx_source::default_listener),
- reinterpret_cast<void*>(this));
- check_error(err, "Adding Default Input Audio Listener failed");
+ err = AudioObjectAddPropertyListener(
+ kAudioObjectSystemObject,
+ &property,
+ reinterpret_cast<AudioObjectPropertyListenerProc>(
+ &osx_source::hardware_listener),
+ reinterpret_cast<void*>(this));
+ check_error(err, "Adding Audio Hardware Listener failed");
+ }
- }
+ if (d_using_default_device) {
-#else
+ // set up a listener if default hardware input device changes
- // 10.5 and older
+ AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster };
+
+ err = AudioObjectAddPropertyListener(
+ kAudioObjectSystemObject,
+ &property,
+ reinterpret_cast<AudioObjectPropertyListenerProc>(
+ &osx_source::default_listener),
+ reinterpret_cast<void*>(this));
+ check_error(err, "Adding Default Input Audio Listener failed");
+ }
+
+#else
- err = AudioHardwareAddPropertyListener
- (kAudioHardwarePropertyDevices,
- reinterpret_cast<AudioHardwarePropertyListenerProc>
- (&osx_source::hardware_listener),
- reinterpret_cast<void*>(this));
- check_error(err, "Adding Audio Hardware Listener failed");
+ // 10.5 and older
- if (d_using_default_device) {
+ err = AudioHardwareAddPropertyListener(
+ kAudioHardwarePropertyDevices,
+ reinterpret_cast<AudioHardwarePropertyListenerProc>(
+ &osx_source::hardware_listener),
+ reinterpret_cast<void*>(this));
+ check_error(err, "Adding Audio Hardware Listener failed");
- err = AudioHardwareAddPropertyListener
- (kAudioHardwarePropertyDefaultInputDevice,
- reinterpret_cast<AudioHardwarePropertyListenerProc>
- (&osx_source::default_listener),
- reinterpret_cast<void*>(this));
- check_error(err, "Adding Default Input Audio Listener failed");
+ if (d_using_default_device) {
- }
+ err = AudioHardwareAddPropertyListener(
+ kAudioHardwarePropertyDefaultInputDevice,
+ reinterpret_cast<AudioHardwarePropertyListenerProc>(
+ &osx_source::default_listener),
+ reinterpret_cast<void*>(this));
+ check_error(err, "Adding Default Input Audio Listener failed");
+ }
#endif
- // initialize the AU for input, so that it is ready to be used
+ // initialize the AU for input, so that it is ready to be used
- err = AudioUnitInitialize(d_input_au);
- check_error_and_throw
- (err, "AudioUnitInitialize",
- "audio_osx_source::check_channels");
+ err = AudioUnitInitialize(d_input_au);
+ check_error_and_throw(err, "AudioUnitInitialize", "audio_osx_source::check_channels");
#if _OSX_AU_DEBUG_
- std::cerr << std::endl << "audio_osx_source Parameters:"
- << std::endl << " Device Sample Rate is "
- << d_device_sample_rate << std::endl
- << " Client Sample Rate is "
- << (d_pass_through ? d_output_sample_rate :
- d_device_sample_rate) << std::endl
- << " User Sample Rate is "
- << d_output_sample_rate << std::endl
- << " Do Passthrough is "
- << (d_pass_through ? "true" : "false") << std::endl
- << " Max Sample Count is "
- << d_buffer_sample_count << std::endl
- << " # Device Channels is "
- << d_n_dev_channels << std::endl
- << " Device Buffer Size in Frames = "
- << d_device_buffer_size_frames << std::endl
- << " Lead Size in Frames = "
- << d_lead_size_frames << std::endl
- << " Trail Size in Frames = "
- << d_trail_size_frames << std::endl
- << " Input Buffer Size in Frames = "
- << d_input_buffer_size_frames << std::endl
- << " Output Buffer Size in Frames = "
- << d_output_buffer_size_frames << std::endl
- << std::endl;
+ std::cerr << std::endl
+ << "audio_osx_source Parameters:" << std::endl
+ << " Device Sample Rate is " << d_device_sample_rate << std::endl
+ << " Client Sample Rate is "
+ << (d_pass_through ? d_output_sample_rate : d_device_sample_rate)
+ << std::endl
+ << " User Sample Rate is " << d_output_sample_rate << std::endl
+ << " Do Passthrough is " << (d_pass_through ? "true" : "false")
+ << std::endl
+ << " Max Sample Count is " << d_buffer_sample_count << std::endl
+ << " # Device Channels is " << d_n_dev_channels << std::endl
+ << " Device Buffer Size in Frames = " << d_device_buffer_size_frames
+ << std::endl
+ << " Lead Size in Frames = " << d_lead_size_frames << std::endl
+ << " Trail Size in Frames = " << d_trail_size_frames << std::endl
+ << " Input Buffer Size in Frames = " << d_input_buffer_size_frames
+ << std::endl
+ << " Output Buffer Size in Frames = " << d_output_buffer_size_frames
+ << std::endl
+ << std::endl;
#endif
- }
+}
- void
- osx_source::alloc_audio_buffer_list
- (AudioBufferList** t_abl,
- UInt32 n_channels,
- UInt32 input_buffer_size_bytes)
- {
- free_audio_buffer_list(t_abl);
- UInt32 prop_size = (offsetof(AudioBufferList, mBuffers[0]) +
- (sizeof(AudioBuffer) * n_channels));
- *t_abl = (AudioBufferList*)calloc(1, prop_size);
- (*t_abl)->mNumberBuffers = n_channels;
+void osx_source::alloc_audio_buffer_list(AudioBufferList** t_abl,
+ UInt32 n_channels,
+ UInt32 input_buffer_size_bytes)
+{
+ free_audio_buffer_list(t_abl);
+ UInt32 prop_size =
+ (offsetof(AudioBufferList, mBuffers[0]) + (sizeof(AudioBuffer) * n_channels));
+ *t_abl = (AudioBufferList*)calloc(1, prop_size);
+ (*t_abl)->mNumberBuffers = n_channels;
- int counter = n_channels;
+ int counter = n_channels;
#if _OSX_AU_DEBUG_
- std::cerr << "alloc_audio_buffer_list: (#chan, #bytes) == ("
- << n_channels << ", " << input_buffer_size_bytes
- << ")" << std::endl;
+ std::cerr << "alloc_audio_buffer_list: (#chan, #bytes) == (" << n_channels << ", "
+ << input_buffer_size_bytes << ")" << std::endl;
#endif
- while(--counter >= 0) {
- AudioBuffer* t_ab = &((*t_abl)->mBuffers[counter]);
- t_ab->mNumberChannels = 1;
- t_ab->mDataByteSize = input_buffer_size_bytes;
- t_ab->mData = calloc(1, input_buffer_size_bytes);
- }
+ while (--counter >= 0) {
+ AudioBuffer* t_ab = &((*t_abl)->mBuffers[counter]);
+ t_ab->mNumberChannels = 1;
+ t_ab->mDataByteSize = input_buffer_size_bytes;
+ t_ab->mData = calloc(1, input_buffer_size_bytes);
}
+}
- void
- osx_source::free_audio_buffer_list(AudioBufferList** t_abl)
- {
- // free pre-allocated audio buffer, if it exists
- if(*t_abl) {
+void osx_source::free_audio_buffer_list(AudioBufferList** t_abl)
+{
+ // free pre-allocated audio buffer, if it exists
+ if (*t_abl) {
int counter = (*t_abl)->mNumberBuffers;
- while(--counter >= 0) {
- AudioBuffer* t_ab = &((*t_abl)->mBuffers[counter]);
- free(t_ab->mData);
- t_ab->mData = 0;
- }
+ while (--counter >= 0) {
+ AudioBuffer* t_ab = &((*t_abl)->mBuffers[counter]);
+ free(t_ab->mData);
+ t_ab->mData = 0;
+ }
free(*t_abl);
(*t_abl) = 0;
- }
}
-
- bool
- osx_source::is_running()
- {
- UInt32 au_running = 0;
- if (d_input_au) {
-
- UInt32 prop_size = (UInt32)sizeof(au_running);
- OSStatus err = AudioUnitGetProperty
- (d_input_au,
- kAudioOutputUnitProperty_IsRunning,
- kAudioUnitScope_Global, 0,
- &au_running, &prop_size);
- check_error_and_throw
- (err, "AudioUnitGetProperty IsRunning",
- "audio_osx_source::is_running");
- }
-
- return(au_running != 0);
+}
+
+bool osx_source::is_running()
+{
+ UInt32 au_running = 0;
+ if (d_input_au) {
+
+ UInt32 prop_size = (UInt32)sizeof(au_running);
+ OSStatus err = AudioUnitGetProperty(d_input_au,
+ kAudioOutputUnitProperty_IsRunning,
+ kAudioUnitScope_Global,
+ 0,
+ &au_running,
+ &prop_size);
+ check_error_and_throw(
+ err, "AudioUnitGetProperty IsRunning", "audio_osx_source::is_running");
}
- bool
- osx_source::start()
- {
+ return (au_running != 0);
+}
+
+bool osx_source::start()
+{
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_source::start: Starting." << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::start: Starting."
+ << std::endl;
#endif
- if((!is_running ()) && d_input_au) {
+ if ((!is_running()) && d_input_au) {
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_source::start: Starting Audio Unit."
- << std::endl;
+ std::cerr << ((void*)(pthread_self()))
+ << " : audio_osx_source::start: Starting Audio Unit." << std::endl;
#endif
- // reset buffers before starting
+ // reset buffers before starting
- for(UInt32 nn = 0; nn < d_buffers.size(); ++nn) {
- d_buffers[nn]->reset();
- }
+ for (UInt32 nn = 0; nn < d_buffers.size(); ++nn) {
+ d_buffers[nn]->reset();
+ }
- // start the audio unit
+ // start the audio unit
OSStatus err = AudioOutputUnitStart(d_input_au);
- check_error_and_throw(err, "AudioOutputUnitStart",
- "audio_osx_source::start");
+ check_error_and_throw(err, "AudioOutputUnitStart", "audio_osx_source::start");
- // clear reset (will sometimes be necessary, and it has to
- // happen after AudioOutputUnitStart)
+ // clear reset (will sometimes be necessary, and it has to
+ // happen after AudioOutputUnitStart)
- d_do_reset = false;
-
- }
+ d_do_reset = false;
+ }
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_source::start: Returning." << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::start: Returning."
+ << std::endl;
#endif
- return (true);
- }
+ return (true);
+}
- bool
- osx_source::stop()
- {
+bool osx_source::stop()
+{
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_source::stop: Starting." << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::stop: Starting."
+ << std::endl;
#endif
- if(is_running ()) {
+ if (is_running()) {
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_source::stop: stopping audio unit."
- << std::endl;
+ std::cerr << ((void*)(pthread_self()))
+ << " : audio_osx_source::stop: stopping audio unit." << std::endl;
#endif
- // stop the audio unit
+ // stop the audio unit
OSStatus err = AudioOutputUnitStop(d_input_au);
- check_error_and_throw(err, "AudioOutputUnitStart",
- "audio_osx_source::stop");
+ check_error_and_throw(err, "AudioOutputUnitStart", "audio_osx_source::stop");
- // abort all buffers
+ // abort all buffers
- for(UInt32 nn = 0; nn < d_n_user_channels; ++nn) {
- d_buffers[nn]->abort ();
+ for (UInt32 nn = 0; nn < d_n_user_channels; ++nn) {
+ d_buffers[nn]->abort();
}
- }
+ }
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_source::stop: Returning." << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::stop: Returning."
+ << std::endl;
#endif
- return (true);
- }
+ return (true);
+}
- void
- osx_source::teardown()
- {
+void osx_source::teardown()
+{
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_source::teardown: Starting." << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::teardown: Starting."
+ << std::endl;
#endif
- OSStatus err = noErr;
+ OSStatus err = noErr;
- // stop the AudioUnit
+ // stop the AudioUnit
- stop();
+ stop();
- // remove the listeners
+ // remove the listeners
#ifndef GR_USE_OLD_AUDIO_UNIT
- // 10.4 and newer
- {
- AudioObjectPropertyAddress property = {
- kAudioHardwarePropertyDevices,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
-
- err = AudioObjectRemovePropertyListener
- (kAudioObjectSystemObject, &property,
- reinterpret_cast<AudioObjectPropertyListenerProc>
- (&osx_source::hardware_listener),
- reinterpret_cast<void*>(this));
+ // 10.4 and newer
+ {
+ AudioObjectPropertyAddress property = { kAudioHardwarePropertyDevices,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster };
+
+ err = AudioObjectRemovePropertyListener(
+ kAudioObjectSystemObject,
+ &property,
+ reinterpret_cast<AudioObjectPropertyListenerProc>(
+ &osx_source::hardware_listener),
+ reinterpret_cast<void*>(this));
#if _OSX_AU_DEBUG_
- check_error(err, "teardown: AudioObjectRemovePropertyListener "
- "hardware failed");
+ check_error(err,
+ "teardown: AudioObjectRemovePropertyListener "
+ "hardware failed");
#endif
+ }
- }
-
- if (d_using_default_device) {
+ if (d_using_default_device) {
- AudioObjectPropertyAddress property = {
- kAudioHardwarePropertyDefaultInputDevice,
- kAudioObjectPropertyScopeGlobal,
- kAudioObjectPropertyElementMaster
- };
+ AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster };
- err = AudioObjectRemovePropertyListener
- (kAudioObjectSystemObject, &property,
- reinterpret_cast<AudioObjectPropertyListenerProc>
- (&osx_source::default_listener),
- reinterpret_cast<void*>(this));
+ err = AudioObjectRemovePropertyListener(
+ kAudioObjectSystemObject,
+ &property,
+ reinterpret_cast<AudioObjectPropertyListenerProc>(
+ &osx_source::default_listener),
+ reinterpret_cast<void*>(this));
#if _OSX_AU_DEBUG_
- check_error(err, "AudioObjectRemovePropertyListener default");
+ check_error(err, "AudioObjectRemovePropertyListener default");
#endif
- d_using_default_device = false;
-
- }
+ d_using_default_device = false;
+ }
#else
- // 10.5 and older
+ // 10.5 and older
- err = AudioHardwareRemovePropertyListener
- (kAudioHardwarePropertyDevices,
- reinterpret_cast<AudioHardwarePropertyListenerProc>
- (&osx_source::hardware_listener));
+ err = AudioHardwareRemovePropertyListener(
+ kAudioHardwarePropertyDevices,
+ reinterpret_cast<AudioHardwarePropertyListenerProc>(
+ &osx_source::hardware_listener));
#if _OSX_AU_DEBUG_
- check_error(err, "AudioObjectRemovePropertyListener hardware");
+ check_error(err, "AudioObjectRemovePropertyListener hardware");
#endif
- if (d_using_default_device) {
- err = AudioHardwareRemovePropertyListener
- (kAudioHardwarePropertyDefaultInputDevice,
- reinterpret_cast<AudioHardwarePropertyListenerProc>
- (&osx_source::default_listener));
+ if (d_using_default_device) {
+ err = AudioHardwareRemovePropertyListener(
+ kAudioHardwarePropertyDefaultInputDevice,
+ reinterpret_cast<AudioHardwarePropertyListenerProc>(
+ &osx_source::default_listener));
#if _OSX_AU_DEBUG_
- check_error(err, "AudioObjectRemovePropertyListener default");
+ check_error(err, "AudioObjectRemovePropertyListener default");
#endif
- d_using_default_device = false;
-
- }
+ d_using_default_device = false;
+ }
#endif // GR_USE_OLD_AUDIO_UNIT
- // free pre-allocated audio buffers
- free_audio_buffer_list(&d_input_buffer);
+ // free pre-allocated audio buffers
+ free_audio_buffer_list(&d_input_buffer);
- if(!d_pass_through) {
+ if (!d_pass_through) {
err = AudioConverterDispose(d_audio_converter);
#if _OSX_AU_DEBUG_
check_error(err, "~audio_osx_source: AudioConverterDispose");
#endif
free_audio_buffer_list(&d_output_buffer);
- }
+ }
- // remove the audio unit
- err = AudioUnitUninitialize(d_input_au);
+ // remove the audio unit
+ err = AudioUnitUninitialize(d_input_au);
#if _OSX_AU_DEBUG_
- check_error(err, "~audio_osx_source: AudioUnitUninitialize");
+ check_error(err, "~audio_osx_source: AudioUnitUninitialize");
#endif
#ifndef GR_USE_OLD_AUDIO_UNIT
- err = AudioComponentInstanceDispose(d_input_au);
+ err = AudioComponentInstanceDispose(d_input_au);
#if _OSX_AU_DEBUG_
- check_error(err, "~audio_osx_source: AudioComponentInstanceDispose");
+ check_error(err, "~audio_osx_source: AudioComponentInstanceDispose");
#endif
#else
- err = CloseComponent(d_input_au);
+ err = CloseComponent(d_input_au);
#if _OSX_AU_DEBUG_
- check_error(err, "~audio_osx_source: CloseComponent");
+ check_error(err, "~audio_osx_source: CloseComponent");
#endif
#endif
- // empty and delete the queues
+ // empty and delete the queues
- for(UInt32 nn = 0; nn < d_buffers.size(); ++nn) {
+ for (UInt32 nn = 0; nn < d_buffers.size(); ++nn) {
delete d_buffers[nn];
d_buffers[nn] = 0;
- }
- d_buffers.resize(0);
+ }
+ d_buffers.resize(0);
- // clear important variables; not # user channels
+ // clear important variables; not # user channels
- d_queue_sample_count = 0;
- d_device_sample_rate = 0;
- d_n_dev_channels = 0;
- d_input_ad_id = 0;
- d_input_au = 0;
- d_input_buffer = d_output_buffer = 0;
- d_audio_converter = 0;
- d_using_default_device = false;
+ d_queue_sample_count = 0;
+ d_device_sample_rate = 0;
+ d_n_dev_channels = 0;
+ d_input_ad_id = 0;
+ d_input_au = 0;
+ d_input_buffer = d_output_buffer = 0;
+ d_audio_converter = 0;
+ d_using_default_device = false;
#if _OSX_AU_DEBUG_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_source::teardown: Returning." << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::teardown: Returning."
+ << std::endl;
#endif
+}
+
+bool osx_source::check_topology(int ninputs, int noutputs)
+{
+ // check # inputs to make sure it's valid
+ if (ninputs != 0) {
+
+ GR_LOG_FATAL(d_logger,
+ boost::format("check_topology(): number of input "
+ "streams provided (%d) should be 0.") %
+ ninputs);
+ throw std::runtime_error("audio_osx_source::check_topology");
}
- bool
- osx_source::check_topology(int ninputs, int noutputs)
- {
- // check # inputs to make sure it's valid
- if(ninputs != 0) {
-
- GR_LOG_FATAL(d_logger, boost::format
- ("check_topology(): number of input "
- "streams provided (%d) should be 0.")
- % ninputs);
- throw std::runtime_error
- ("audio_osx_source::check_topology");
+ // check # outputs to make sure it's valid
+ if ((noutputs < 1) | (noutputs > (int)d_n_dev_channels)) {
- }
-
- // check # outputs to make sure it's valid
- if((noutputs < 1) | (noutputs > (int) d_n_dev_channels)) {
-
- GR_LOG_FATAL(d_logger, boost::format
- ("check_topology(): number of output "
- "streams provided (%d) should be in [1,%d] "
- "for the selected input audio device.")
- % noutputs % d_n_dev_channels);
- throw std::runtime_error
- ("audio_osx_source::check_topology");
- }
+ GR_LOG_FATAL(d_logger,
+ boost::format("check_topology(): number of output "
+ "streams provided (%d) should be in [1,%d] "
+ "for the selected input audio device.") %
+ noutputs % d_n_dev_channels);
+ throw std::runtime_error("audio_osx_source::check_topology");
+ }
- // save the actual number of output (user) channels
+ // save the actual number of output (user) channels
- d_n_user_channels = noutputs;
+ d_n_user_channels = noutputs;
#if _OSX_AU_DEBUG_
- std::cerr << "chk_topo: Actual # user output channels = "
- << noutputs << std::endl;
+ std::cerr << "chk_topo: Actual # user output channels = " << noutputs << std::endl;
#endif
- return(true);
- }
+ return (true);
+}
- int
- osx_source::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
+int osx_source::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_source::work: Starting." << std::endl;
+ std::cerr << ((void*)(pthread_self())) << " : audio_osx_source::work: Starting."
+ << std::endl;
#endif
- if (d_do_reset) {
- if (d_hardware_changed) {
-
- // see if the current AudioDeviceID is still available
+ if (d_do_reset) {
+ if (d_hardware_changed) {
- std::vector < AudioDeviceID > all_ad_ids;
- osx::find_audio_devices
- (d_desired_name, true,
- &all_ad_ids, NULL);
- bool found = false;
- for (UInt32 nn = 0; (nn < all_ad_ids.size()) && (!found);
- ++nn) {
- found = (all_ad_ids[nn] == d_input_ad_id);
- }
- if (!found) {
+ // see if the current AudioDeviceID is still available
- GR_LOG_FATAL(d_logger, boost::format
- ("The selected input audio device ('%s') "
- "is no longer available.\n")
- % d_selected_name);
- return(gr::block::WORK_DONE);
+ std::vector<AudioDeviceID> all_ad_ids;
+ osx::find_audio_devices(d_desired_name, true, &all_ad_ids, NULL);
+ bool found = false;
+ for (UInt32 nn = 0; (nn < all_ad_ids.size()) && (!found); ++nn) {
+ found = (all_ad_ids[nn] == d_input_ad_id);
+ }
+ if (!found) {
- }
+ GR_LOG_FATAL(d_logger,
+ boost::format("The selected input audio device ('%s') "
+ "is no longer available.\n") %
+ d_selected_name);
+ return (gr::block::WORK_DONE);
+ }
- d_do_reset = d_hardware_changed = false;
+ d_do_reset = d_hardware_changed = false;
- } else {
+ } else {
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "audio_osx_source::work: doing reset."
- << std::endl;
+ std::cerr << "audio_osx_source::work: doing reset." << std::endl;
#endif
- GR_LOG_WARN(d_logger, boost::format
- ("\n\nThe default input audio device has "
- "changed; resetting audio.\nThere may "
- "be a sound glitch while resetting.\n"));
+ GR_LOG_WARN(d_logger,
+ boost::format("\n\nThe default input audio device has "
+ "changed; resetting audio.\nThere may "
+ "be a sound glitch while resetting.\n"));
- // for any changes, just tear down the current
- // configuration, then set it up again using the user's
- // parameters to try to make selections.
+ // for any changes, just tear down the current
+ // configuration, then set it up again using the user's
+ // parameters to try to make selections.
- teardown();
+ teardown();
- gr::thread::scoped_lock l(d_internal);
+ gr::thread::scoped_lock l(d_internal);
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "audio_osx_source::work: mutex locked."
- << std::endl;
+ std::cerr << "audio_osx_source::work: mutex locked." << std::endl;
#endif
- setup();
- start();
+ setup();
+ start();
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "audio_osx_source::work: returning after reset."
- << std::endl;
+ std::cerr << "audio_osx_source::work: returning after reset." << std::endl;
#endif
- return(0);
- }
- }
+ return (0);
+ }
+ }
- gr::thread::scoped_lock l(d_internal);
+ gr::thread::scoped_lock l(d_internal);
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "audio_osx_source::work: mutex locked." << std::endl;
+ std::cerr << "audio_osx_source::work: mutex locked." << std::endl;
#endif
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "work1: SC = " << d_queue_sample_count
- << ", #OI = " << noutput_items
- << ", #Chan = " << output_items.size() << std::endl;
+ std::cerr << "work1: SC = " << d_queue_sample_count << ", #OI = " << noutput_items
+ << ", #Chan = " << output_items.size() << std::endl;
#endif
- // set the actual # of output items to the 'desired' amount then
- // verify that data is available; if not enough data is
- // available, either wait until it is (is "ok_to_block" is
- // true), return (0) is no data is available and "ok_to_block"
- // is false, or process the actual amount of available data.
-
- UInt32 actual_noutput_items = noutput_items;
-
- if(d_queue_sample_count < actual_noutput_items) {
- if(d_queue_sample_count == 0) {
- // no data; ok_to_block decides what to do
- if(d_ok_to_block == true) {
- // block until there is data to return, or on reset
- while(d_queue_sample_count == 0) {
- // release control so-as to allow data to be retrieved;
- // block until there is data to return
+ // set the actual # of output items to the 'desired' amount then
+ // verify that data is available; if not enough data is
+ // available, either wait until it is (is "ok_to_block" is
+ // true), return (0) is no data is available and "ok_to_block"
+ // is false, or process the actual amount of available data.
+
+ UInt32 actual_noutput_items = noutput_items;
+
+ if (d_queue_sample_count < actual_noutput_items) {
+ if (d_queue_sample_count == 0) {
+ // no data; ok_to_block decides what to do
+ if (d_ok_to_block == true) {
+ // block until there is data to return, or on reset
+ while (d_queue_sample_count == 0) {
+ // release control so-as to allow data to be retrieved;
+ // block until there is data to return
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "audio_osx_source::work: waiting."
- << std::endl;
+ std::cerr << "audio_osx_source::work: waiting." << std::endl;
#endif
- d_waiting_for_data = true;
- d_cond_data.wait(l);
- d_waiting_for_data = false;
+ d_waiting_for_data = true;
+ d_cond_data.wait(l);
+ d_waiting_for_data = false;
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "audio_osx_source::work: done waiting."
- << std::endl;
+ std::cerr << "audio_osx_source::work: done waiting." << std::endl;
#endif
- // the condition's 'notify' was called; acquire control to
- // keep thread safe
+ // the condition's 'notify' was called; acquire control to
+ // keep thread safe
- // if doing a reset, just return here; reset will pick
- // up the next time this method is called.
- if (d_do_reset) {
+ // if doing a reset, just return here; reset will pick
+ // up the next time this method is called.
+ if (d_do_reset) {
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "audio_osx_source::work: "
- "returning for reset." << std::endl;
+ std::cerr << "audio_osx_source::work: "
+ "returning for reset."
+ << std::endl;
#endif
- return(0);
- }
- }
- }
- else {
- // no data & not blocking; return nothing
+ return (0);
+ }
+ }
+ } else {
+ // no data & not blocking; return nothing
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "audio_osx_source::work: no data "
- "& not blocking; returning 0." << std::endl;
+ std::cerr << "audio_osx_source::work: no data "
+ "& not blocking; returning 0."
+ << std::endl;
#endif
- return (0);
- }
+ return (0);
+ }
}
// use the actual amount of available data
actual_noutput_items = d_queue_sample_count;
- }
+ }
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "audio_osx_source::work: copying "
- << actual_noutput_items << " items per channel"
- << std::endl;
+ std::cerr << "audio_osx_source::work: copying " << actual_noutput_items
+ << " items per channel" << std::endl;
#endif
- // number of channels
- int l_counter = (int)output_items.size();
+ // number of channels
+ int l_counter = (int)output_items.size();
- // copy the items from the circular buffer(s) to 'work's output
- // buffers; verify that the number copied out is as expected.
+ // copy the items from the circular buffer(s) to 'work's output
+ // buffers; verify that the number copied out is as expected.
- while(--l_counter >= 0) {
+ while (--l_counter >= 0) {
size_t t_n_output_items = actual_noutput_items;
- d_buffers[l_counter]->dequeue
- ((float*)output_items[l_counter],
- &t_n_output_items);
+ d_buffers[l_counter]->dequeue((float*)output_items[l_counter], &t_n_output_items);
- if(t_n_output_items != actual_noutput_items) {
-
- GR_LOG_FATAL(d_logger, boost::format
- ("work(): ERROR: number of available "
- "items changing unexpectedly; expecting %d"
- ", got %d.")
- % actual_noutput_items % t_n_output_items);
- throw std::runtime_error("audio_osx_source::work()");
+ if (t_n_output_items != actual_noutput_items) {
+ GR_LOG_FATAL(d_logger,
+ boost::format("work(): ERROR: number of available "
+ "items changing unexpectedly; expecting %d"
+ ", got %d.") %
+ actual_noutput_items % t_n_output_items);
+ throw std::runtime_error("audio_osx_source::work()");
}
- }
+ }
- // subtract the actual number of items removed from the buffer(s)
- // from the local accounting of the number of available samples
+ // subtract the actual number of items removed from the buffer(s)
+ // from the local accounting of the number of available samples
- d_queue_sample_count -= actual_noutput_items;
+ d_queue_sample_count -= actual_noutput_items;
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "work2: SC = " << d_queue_sample_count
- << ", act#OI = " << actual_noutput_items << std::endl
- << "Returning." << std::endl;
+ std::cerr << "work2: SC = " << d_queue_sample_count
+ << ", act#OI = " << actual_noutput_items << std::endl
+ << "Returning." << std::endl;
#endif
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "audio_osx_source::work: returning." << std::endl;
+ std::cerr << "audio_osx_source::work: returning." << std::endl;
#endif
- return (actual_noutput_items);
- }
-
- OSStatus
- osx_source::converter_callback
- (AudioConverterRef in_audio_converter,
- UInt32* io_number_data_packets,
- AudioBufferList* io_data,
- AudioStreamPacketDescription** out_aspd,
- void* in_user_data)
- {
- // This callback is for us to provide the buffers to CoreAudio
- // for conversion. We need to set the buffers in the provided
- // buffer list (io_data) to the buffers we know about and use to
- // do data input (d_input_buffers).
-
- osx_source* This = static_cast<osx_source*>(in_user_data);
- AudioBufferList* l_input_abl = This->d_input_buffer;
- UInt32 total_input_buffer_size_bytes =
- ((*io_number_data_packets) * sizeof(float));
- int counter = This->d_n_dev_channels;
- io_data->mNumberBuffers = This->d_n_dev_channels;
- This->d_n_actual_input_frames = (*io_number_data_packets);
+ return (actual_noutput_items);
+}
+
+OSStatus osx_source::converter_callback(AudioConverterRef in_audio_converter,
+ UInt32* io_number_data_packets,
+ AudioBufferList* io_data,
+ AudioStreamPacketDescription** out_aspd,
+ void* in_user_data)
+{
+ // This callback is for us to provide the buffers to CoreAudio
+ // for conversion. We need to set the buffers in the provided
+ // buffer list (io_data) to the buffers we know about and use to
+ // do data input (d_input_buffers).
+
+ osx_source* This = static_cast<osx_source*>(in_user_data);
+ AudioBufferList* l_input_abl = This->d_input_buffer;
+ UInt32 total_input_buffer_size_bytes = ((*io_number_data_packets) * sizeof(float));
+ int counter = This->d_n_dev_channels;
+ io_data->mNumberBuffers = This->d_n_dev_channels;
+ This->d_n_actual_input_frames = (*io_number_data_packets);
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "cc1: io#DP = " << (*io_number_data_packets)
- << ", TIBSB = " << total_input_buffer_size_bytes
- << ", #C = " << counter << std::endl;
+ std::cerr << "cc1: io#DP = " << (*io_number_data_packets)
+ << ", TIBSB = " << total_input_buffer_size_bytes << ", #C = " << counter
+ << std::endl;
#endif
- while(--counter >= 0) {
+ while (--counter >= 0) {
AudioBuffer* t_ab = &(io_data->mBuffers[counter]);
t_ab->mNumberChannels = 1;
t_ab->mData = l_input_abl->mBuffers[counter].mData;
t_ab->mDataByteSize = total_input_buffer_size_bytes;
- }
+ }
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "cc2: Returning." << std::endl;
+ std::cerr << "cc2: Returning." << std::endl;
#endif
- return (noErr);
- }
+ return (noErr);
+}
- OSStatus
- osx_source::au_input_callback
- (void *in_ref_con,
- AudioUnitRenderActionFlags *io_action_flags,
- const AudioTimeStamp *in_time_stamp,
- UInt32 in_bus_number,
- UInt32 in_number_frames,
- AudioBufferList *io_data)
- {
+OSStatus osx_source::au_input_callback(void* in_ref_con,
+ AudioUnitRenderActionFlags* io_action_flags,
+ const AudioTimeStamp* in_time_stamp,
+ UInt32 in_bus_number,
+ UInt32 in_number_frames,
+ AudioBufferList* io_data)
+{
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << ((void*)(pthread_self()))
- << " : audio_osx_source::au_input_callback: Starting."
- << std::endl;
+ std::cerr << ((void*)(pthread_self()))
+ << " : audio_osx_source::au_input_callback: Starting." << std::endl;
#endif
- osx_source* This = reinterpret_cast
- <osx_source*>(in_ref_con);
- gr::thread::scoped_lock l(This->d_internal);
- gr::logger_ptr d_logger = This->d_logger;
+ osx_source* This = reinterpret_cast<osx_source*>(in_ref_con);
+ gr::thread::scoped_lock l(This->d_internal);
+ gr::logger_ptr d_logger = This->d_logger;
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "audio_osx_source::au_input_callback: mutex locked."
- << std::endl;
+ std::cerr << "audio_osx_source::au_input_callback: mutex locked." << std::endl;
#endif
- OSStatus err = noErr;
+ OSStatus err = noErr;
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "cb0: in#Fr = " << in_number_frames
- << ", inBus# = " << in_bus_number
- << ", idD = " << ((void*)io_data)
- << ", d_ib = " << ((void*)(This->d_input_buffer))
- << ", d_ib#c = " << This->d_input_buffer->mNumberBuffers
- << ", SC = " << This->d_queue_sample_count << std::endl;
+ std::cerr << "cb0: in#Fr = " << in_number_frames << ", inBus# = " << in_bus_number
+ << ", idD = " << ((void*)io_data)
+ << ", d_ib = " << ((void*)(This->d_input_buffer))
+ << ", d_ib#c = " << This->d_input_buffer->mNumberBuffers
+ << ", SC = " << This->d_queue_sample_count << std::endl;
#endif
- if (This->d_do_reset) {
-
- // clear audio data; do not render since it will generate an error
-
- AudioBufferList* t_abl = This->d_input_buffer;
- for (UInt32 nn = 0; nn < t_abl->mNumberBuffers; ++nn) {
- AudioBuffer* t_ab = &(t_abl->mBuffers[nn]);
- memset(t_ab->mData, 0, (size_t)((t_ab->mDataByteSize) *
- (t_ab->mNumberChannels)));
- }
- } else {
+ if (This->d_do_reset) {
- // Get the new audio data from the input device
+ // clear audio data; do not render since it will generate an error
- err = AudioUnitRender
- (This->d_input_au, io_action_flags,
- in_time_stamp, 1, //inBusNumber,
- in_number_frames, This->d_input_buffer);
- check_error_and_throw
- (err, "AudioUnitRender",
- "audio_osx_source::au_input_callback");
-
- }
+ AudioBufferList* t_abl = This->d_input_buffer;
+ for (UInt32 nn = 0; nn < t_abl->mNumberBuffers; ++nn) {
+ AudioBuffer* t_ab = &(t_abl->mBuffers[nn]);
+ memset(t_ab->mData,
+ 0,
+ (size_t)((t_ab->mDataByteSize) * (t_ab->mNumberChannels)));
+ }
+ } else {
+
+ // Get the new audio data from the input device
+
+ err = AudioUnitRender(This->d_input_au,
+ io_action_flags,
+ in_time_stamp,
+ 1, // inBusNumber,
+ in_number_frames,
+ This->d_input_buffer);
+ check_error_and_throw(
+ err, "AudioUnitRender", "audio_osx_source::au_input_callback");
+ }
- UInt32 available_input_frames =
- This->d_n_available_input_frames = in_number_frames;
+ UInt32 available_input_frames = This->d_n_available_input_frames = in_number_frames;
- // get the number of actual output frames,
- // either via converting the buffer or not
+ // get the number of actual output frames,
+ // either via converting the buffer or not
- UInt32 actual_output_frames = available_input_frames;
+ UInt32 actual_output_frames = available_input_frames;
- if(!This->d_pass_through) {
- UInt32 available_input_bytes =
- available_input_frames * sizeof(float);
+ if (!This->d_pass_through) {
+ UInt32 available_input_bytes = available_input_frames * sizeof(float);
UInt32 available_output_bytes = available_input_bytes;
UInt32 prop_size = sizeof(available_output_bytes);
- err = AudioConverterGetProperty
- (This->d_audio_converter,
- kAudioConverterPropertyCalculateOutputBufferSize,
- &prop_size,
- &available_output_bytes);
- check_error_and_throw
- (err, "Get Output Buffer Size failed",
- "audio_osx_source::au_input_callback");
+ err = AudioConverterGetProperty(This->d_audio_converter,
+ kAudioConverterPropertyCalculateOutputBufferSize,
+ &prop_size,
+ &available_output_bytes);
+ check_error_and_throw(
+ err, "Get Output Buffer Size failed", "audio_osx_source::au_input_callback");
- UInt32 available_output_frames =
- available_output_bytes / sizeof(float);
+ UInt32 available_output_frames = available_output_bytes / sizeof(float);
#if 0
// when decimating too much, the output sounds warbly due to
@@ -1392,17 +1298,17 @@ namespace gr {
// convert the data to the correct rate; on input,
// actual_output_frames is the number of available output frames
- err = AudioConverterFillComplexBuffer
- (This->d_audio_converter,
- reinterpret_cast<AudioConverterComplexInputDataProc>
- (&(This->converter_callback)),
- in_ref_con,
- &actual_output_frames,
- This->d_output_buffer,
- NULL);
- check_error_and_throw
- (err, "AudioConverterFillComplexBuffer failed",
- "audio_osx_source::au_input_callback");
+ err = AudioConverterFillComplexBuffer(
+ This->d_audio_converter,
+ reinterpret_cast<AudioConverterComplexInputDataProc>(
+ &(This->converter_callback)),
+ in_ref_con,
+ &actual_output_frames,
+ This->d_output_buffer,
+ NULL);
+ check_error_and_throw(err,
+ "AudioConverterFillComplexBuffer failed",
+ "audio_osx_source::au_input_callback");
// on output, actual_output_frames is the actual number of
// output frames
@@ -1410,111 +1316,97 @@ namespace gr {
#if _OSX_AU_DEBUG_RENDER_
std::cerr << "cb2: actual: #IF = " << This->d_n_actual_input_frames
<< ", #OF = " << actual_output_frames << std::endl;
- if(This->d_n_actual_input_frames != available_input_frames)
- std::cerr << "cb2.1: avail#IF = " << available_input_frames
- << ", actual#IF = " << This->d_n_actual_input_frames << std::endl;
+ if (This->d_n_actual_input_frames != available_input_frames)
+ std::cerr << "cb2.1: avail#IF = " << available_input_frames
+ << ", actual#IF = " << This->d_n_actual_input_frames << std::endl;
#endif
- }
+ }
- // add the output frames to the buffers' queue, checking for overflow
+ // add the output frames to the buffers' queue, checking for overflow
- int counter = This->d_n_user_channels;
- int res = 0;
+ int counter = This->d_n_user_channels;
+ int res = 0;
- while(--counter >= 0) {
- float* in_buffer = (float*)
- This->d_output_buffer->mBuffers[counter].mData;
+ while (--counter >= 0) {
+ float* in_buffer = (float*)This->d_output_buffer->mBuffers[counter].mData;
#if _OSX_AU_DEBUG_RENDER_
std::cerr << "cb3: enqueuing audio data." << std::endl;
#endif
- int l_res = This->d_buffers[counter]->enqueue
- (in_buffer, actual_output_frames);
- if(l_res == -1)
- res = -1;
- }
+ int l_res = This->d_buffers[counter]->enqueue(in_buffer, actual_output_frames);
+ if (l_res == -1)
+ res = -1;
+ }
- if(res == -1) {
+ if (res == -1) {
// data coming in too fast
// drop oldest buffer
fputs("aO", stderr);
fflush(stderr);
// set the local number of samples available to the max
- This->d_queue_sample_count =
- This->d_buffers[0]->buffer_length_items();
- }
- else {
+ This->d_queue_sample_count = This->d_buffers[0]->buffer_length_items();
+ } else {
// keep up the local sample count
This->d_queue_sample_count += actual_output_frames;
- }
+ }
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "cb4: #OI = " << actual_output_frames
- << ", #Cnt = " << This->d_queue_sample_count
- << ", mSC = " << This->d_buffer_sample_count << std::endl;
+ std::cerr << "cb4: #OI = " << actual_output_frames
+ << ", #Cnt = " << This->d_queue_sample_count
+ << ", mSC = " << This->d_buffer_sample_count << std::endl;
#endif
- // signal that data is available, if appropriate
+ // signal that data is available, if appropriate
- if (This->d_waiting_for_data) {
- This->d_cond_data.notify_one();
- }
+ if (This->d_waiting_for_data) {
+ This->d_cond_data.notify_one();
+ }
#if _OSX_AU_DEBUG_RENDER_
- std::cerr << "cb5: returning." << std::endl;
+ std::cerr << "cb5: returning." << std::endl;
#endif
- return(err);
- }
+ return (err);
+}
#ifndef GR_USE_OLD_AUDIO_UNIT
- OSStatus
- osx_source::hardware_listener
- (AudioObjectID in_object_id,
- UInt32 in_num_addresses,
- const AudioObjectPropertyAddress in_addresses[],
- void* in_client_data)
+OSStatus osx_source::hardware_listener(AudioObjectID in_object_id,
+ UInt32 in_num_addresses,
+ const AudioObjectPropertyAddress in_addresses[],
+ void* in_client_data)
#else
- OSStatus
- osx_source::hardware_listener
- (AudioHardwarePropertyID in_property_id,
- void* in_client_data)
+OSStatus osx_source::hardware_listener(AudioHardwarePropertyID in_property_id,
+ void* in_client_data)
#endif
- {
- osx_source* This = reinterpret_cast
- <osx_source*>(in_client_data);
- This->reset(true);
- return(noErr);
- }
+{
+ osx_source* This = reinterpret_cast<osx_source*>(in_client_data);
+ This->reset(true);
+ return (noErr);
+}
#ifndef GR_USE_OLD_AUDIO_UNIT
- OSStatus
- osx_source::default_listener
- (AudioObjectID in_object_id,
- UInt32 in_num_addresses,
- const AudioObjectPropertyAddress in_addresses[],
- void* in_client_data)
+OSStatus osx_source::default_listener(AudioObjectID in_object_id,
+ UInt32 in_num_addresses,
+ const AudioObjectPropertyAddress in_addresses[],
+ void* in_client_data)
#else
- OSStatus
- osx_source::default_listener
- (AudioHardwarePropertyID in_property_id,
- void* in_client_data)
+OSStatus osx_source::default_listener(AudioHardwarePropertyID in_property_id,
+ void* in_client_data)
#endif
- {
- osx_source* This = reinterpret_cast
- <osx_source*>(in_client_data);
- This->reset(false);
- return(noErr);
- }
+{
+ osx_source* This = reinterpret_cast<osx_source*>(in_client_data);
+ This->reset(false);
+ return (noErr);
+}
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/osx/osx_source.h b/gr-audio/lib/osx/osx_source.h
index 3c9147d26c..688ff3c32d 100644
--- a/gr-audio/lib/osx/osx_source.h
+++ b/gr-audio/lib/osx/osx_source.h
@@ -29,147 +29,132 @@
#include "circular_buffer.h"
namespace gr {
- namespace audio {
-
- /*!
- * \brief audio source using OSX
- * \ingroup audio_blk
- *
- * Input signature is one or two streams of floats.
- * Samples must be in the range [-1,1].
- */
- class osx_source : public source
- {
- private:
-
- Float64 d_device_sample_rate, d_output_sample_rate;
- UInt32 d_input_buffer_size_frames, d_input_buffer_size_bytes;
- UInt32 d_output_buffer_size_frames, d_output_buffer_size_bytes;
- UInt32 d_device_buffer_size_frames, d_device_buffer_size_bytes;
- UInt32 d_lead_size_frames, d_lead_size_bytes;
- UInt32 d_trail_size_frames, d_trail_size_bytes;
- UInt32 d_extra_buffer_size_frames, d_extra_buffer_size_bytes;
- UInt32 d_queue_sample_count, d_buffer_sample_count;
- UInt32 d_n_available_input_frames, d_n_actual_input_frames;
- UInt32 d_n_user_channels, d_n_dev_channels;
- bool d_ok_to_block, d_pass_through;
- bool d_waiting_for_data, d_do_reset, d_hardware_changed;
- bool d_using_default_device;
- gr::thread::mutex d_internal;
- gr::thread::condition_variable d_cond_data;
- std::vector < circular_buffer<float>* > d_buffers;
- std::string d_desired_name, d_selected_name;
+namespace audio {
- // CoreAudio variables
-
- AudioDeviceID d_input_ad_id;
- AudioUnit d_input_au;
- AudioBufferList* d_input_buffer;
- AudioBufferList* d_output_buffer;
- AudioConverterRef d_audio_converter;
+/*!
+ * \brief audio source using OSX
+ * \ingroup audio_blk
+ *
+ * Input signature is one or two streams of floats.
+ * Samples must be in the range [-1,1].
+ */
+class osx_source : public source
+{
+private:
+ Float64 d_device_sample_rate, d_output_sample_rate;
+ UInt32 d_input_buffer_size_frames, d_input_buffer_size_bytes;
+ UInt32 d_output_buffer_size_frames, d_output_buffer_size_bytes;
+ UInt32 d_device_buffer_size_frames, d_device_buffer_size_bytes;
+ UInt32 d_lead_size_frames, d_lead_size_bytes;
+ UInt32 d_trail_size_frames, d_trail_size_bytes;
+ UInt32 d_extra_buffer_size_frames, d_extra_buffer_size_bytes;
+ UInt32 d_queue_sample_count, d_buffer_sample_count;
+ UInt32 d_n_available_input_frames, d_n_actual_input_frames;
+ UInt32 d_n_user_channels, d_n_dev_channels;
+ bool d_ok_to_block, d_pass_through;
+ bool d_waiting_for_data, d_do_reset, d_hardware_changed;
+ bool d_using_default_device;
+ gr::thread::mutex d_internal;
+ gr::thread::condition_variable d_cond_data;
+ std::vector<circular_buffer<float>*> d_buffers;
+ std::string d_desired_name, d_selected_name;
- // d_asbd_device: ASBD of the device that is creating the input
- // data stream
+ // CoreAudio variables
- AudioStreamBasicDescription d_asbd_device;
+ AudioDeviceID d_input_ad_id;
+ AudioUnit d_input_au;
+ AudioBufferList* d_input_buffer;
+ AudioBufferList* d_output_buffer;
+ AudioConverterRef d_audio_converter;
- // d_asbd_client: ASBD of the client side (output) of the
- // hardware device
+ // d_asbd_device: ASBD of the device that is creating the input
+ // data stream
- AudioStreamBasicDescription d_asbd_client;
+ AudioStreamBasicDescription d_asbd_device;
- // d_asbd_user: ASBD of the user's arguments, if an audio
- // converter is needed outside that provided by the client side.
+ // d_asbd_client: ASBD of the client side (output) of the
+ // hardware device
- AudioStreamBasicDescription d_asbd_user;
+ AudioStreamBasicDescription d_asbd_client;
- public:
+ // d_asbd_user: ASBD of the user's arguments, if an audio
+ // converter is needed outside that provided by the client side.
- osx_source(int sample_rate,
- const std::string& device_name,
- bool ok_to_block);
+ AudioStreamBasicDescription d_asbd_user;
- virtual inline ~osx_source() {
- teardown();
- }
+public:
+ osx_source(int sample_rate, const std::string& device_name, bool ok_to_block);
- virtual bool start();
- virtual bool stop();
+ virtual inline ~osx_source() { teardown(); }
- virtual bool check_topology(int ninputs, int noutputs);
+ virtual bool start();
+ virtual bool stop();
- virtual int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
+ virtual bool check_topology(int ninputs, int noutputs);
- inline void reset(bool hardware_changed) {
- d_hardware_changed = hardware_changed;
- d_do_reset = true;
- }
+ virtual int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
- private:
+ inline void reset(bool hardware_changed)
+ {
+ d_hardware_changed = hardware_changed;
+ d_do_reset = true;
+ }
- bool is_running();
+private:
+ bool is_running();
- void setup();
+ void setup();
- void teardown();
+ void teardown();
- void alloc_audio_buffer_list
- (AudioBufferList** t_abl,
- UInt32 n_channels,
- UInt32 input_buffer_size_bytes);
+ void alloc_audio_buffer_list(AudioBufferList** t_abl,
+ UInt32 n_channels,
+ UInt32 input_buffer_size_bytes);
- void free_audio_buffer_list
- (AudioBufferList** t_abl);
+ void free_audio_buffer_list(AudioBufferList** t_abl);
- static OSStatus converter_callback
- (AudioConverterRef in_audio_converter,
- UInt32* io_number_data_packets,
- AudioBufferList* io_data,
- AudioStreamPacketDescription** out_aspd,
- void* in_user_data);
+ static OSStatus converter_callback(AudioConverterRef in_audio_converter,
+ UInt32* io_number_data_packets,
+ AudioBufferList* io_data,
+ AudioStreamPacketDescription** out_aspd,
+ void* in_user_data);
- static OSStatus au_input_callback
- (void *in_ref_con,
- AudioUnitRenderActionFlags *io_action_flags,
- const AudioTimeStamp *in_time_stamp,
- UInt32 in_bus_number,
- UInt32 in_number_frames,
- AudioBufferList *io_data);
+ static OSStatus au_input_callback(void* in_ref_con,
+ AudioUnitRenderActionFlags* io_action_flags,
+ const AudioTimeStamp* in_time_stamp,
+ UInt32 in_bus_number,
+ UInt32 in_number_frames,
+ AudioBufferList* io_data);
#ifndef GR_USE_OLD_AUDIO_UNIT
- // OSX 10.4 and newer
+ // OSX 10.4 and newer
- static OSStatus hardware_listener
- (AudioObjectID in_object_id,
- UInt32 in_num_addresses,
- const AudioObjectPropertyAddress in_addresses[],
- void* in_client_data);
+ static OSStatus hardware_listener(AudioObjectID in_object_id,
+ UInt32 in_num_addresses,
+ const AudioObjectPropertyAddress in_addresses[],
+ void* in_client_data);
- static OSStatus default_listener
- (AudioObjectID in_object_id,
- UInt32 in_num_addresses,
- const AudioObjectPropertyAddress in_addresses[],
- void* in_client_data);
+ static OSStatus default_listener(AudioObjectID in_object_id,
+ UInt32 in_num_addresses,
+ const AudioObjectPropertyAddress in_addresses[],
+ void* in_client_data);
#else
- // OSX 10.6 and older; removed as of 10.7
+ // OSX 10.6 and older; removed as of 10.7
- static OSStatus hardware_listener
- (AudioHardwarePropertyID in_property_id,
- void* in_client_data);
+ static OSStatus hardware_listener(AudioHardwarePropertyID in_property_id,
+ void* in_client_data);
- static OSStatus default_listener
- (AudioHardwarePropertyID in_property_id,
- void* in_client_data);
+ static OSStatus default_listener(AudioHardwarePropertyID in_property_id,
+ void* in_client_data);
#endif
-
- };
- } /* namespace audio */
+};
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_AUDIO_OSX_SOURCE_H */
diff --git a/gr-audio/lib/portaudio/portaudio_impl.cc b/gr-audio/lib/portaudio/portaudio_impl.cc
index acc92cf237..38b02d5a27 100644
--- a/gr-audio/lib/portaudio/portaudio_impl.cc
+++ b/gr-audio/lib/portaudio/portaudio_impl.cc
@@ -29,80 +29,81 @@
#include <string.h>
namespace gr {
- namespace audio {
+namespace audio {
- PaDeviceIndex
- pa_find_device_by_name(const char *name)
- {
- int i;
- int numDevices;
- const PaDeviceInfo *pdi;
- int len = strlen(name);
- PaDeviceIndex result = paNoDevice;
- numDevices = Pa_GetDeviceCount();
- for(i = 0; i < numDevices; i++) {
+PaDeviceIndex pa_find_device_by_name(const char* name)
+{
+ int i;
+ int numDevices;
+ const PaDeviceInfo* pdi;
+ int len = strlen(name);
+ PaDeviceIndex result = paNoDevice;
+ numDevices = Pa_GetDeviceCount();
+ for (i = 0; i < numDevices; i++) {
pdi = Pa_GetDeviceInfo(i);
- if(strncmp(name, pdi->name, len) == 0) {
- result = i;
- break;
+ if (strncmp(name, pdi->name, len) == 0) {
+ result = i;
+ break;
}
- }
- return result;
}
+ return result;
+}
- void
- print_devices()
- {
- int numDevices, defaultDisplayed;
- const PaDeviceInfo *deviceInfo;
+void print_devices()
+{
+ int numDevices, defaultDisplayed;
+ const PaDeviceInfo* deviceInfo;
- numDevices = Pa_GetDeviceCount();
- if(numDevices < 0)
+ numDevices = Pa_GetDeviceCount();
+ if (numDevices < 0)
return;
- printf("Number of devices found = %d\n", numDevices);
+ printf("Number of devices found = %d\n", numDevices);
- for(int i = 0; i < numDevices; i++) {
+ for (int i = 0; i < numDevices; i++) {
deviceInfo = Pa_GetDeviceInfo(i);
printf("--------------------------------------- device #%d\n", i);
/* Mark global and API specific default devices */
defaultDisplayed = 0;
- if(i == Pa_GetDefaultInputDevice()) {
- printf("[ Default Input");
- defaultDisplayed = 1;
- }
- else if(i == Pa_GetHostApiInfo(deviceInfo->hostApi)->defaultInputDevice) {
- const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
- printf("[ Default %s Input", hostInfo->name);
- defaultDisplayed = 1;
+ if (i == Pa_GetDefaultInputDevice()) {
+ printf("[ Default Input");
+ defaultDisplayed = 1;
+ } else if (i == Pa_GetHostApiInfo(deviceInfo->hostApi)->defaultInputDevice) {
+ const PaHostApiInfo* hostInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
+ printf("[ Default %s Input", hostInfo->name);
+ defaultDisplayed = 1;
}
- if(i == Pa_GetDefaultOutputDevice()) {
- printf((defaultDisplayed ? "," : "["));
- printf(" Default Output");
- defaultDisplayed = 1;
- }
- else if(i == Pa_GetHostApiInfo(deviceInfo->hostApi)->defaultOutputDevice) {
- const PaHostApiInfo *hostInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
- printf((defaultDisplayed ? "," : "["));
- printf(" Default %s Output", hostInfo->name);
- defaultDisplayed = 1;
+ if (i == Pa_GetDefaultOutputDevice()) {
+ printf((defaultDisplayed ? "," : "["));
+ printf(" Default Output");
+ defaultDisplayed = 1;
+ } else if (i == Pa_GetHostApiInfo(deviceInfo->hostApi)->defaultOutputDevice) {
+ const PaHostApiInfo* hostInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
+ printf((defaultDisplayed ? "," : "["));
+ printf(" Default %s Output", hostInfo->name);
+ defaultDisplayed = 1;
}
- if(defaultDisplayed)
- printf(" ]\n");
+ if (defaultDisplayed)
+ printf(" ]\n");
/* print device info fields */
printf("Name = %s\n", deviceInfo->name);
- printf("Host API = %s\n", Pa_GetHostApiInfo(deviceInfo->hostApi)->name );
+ printf("Host API = %s\n",
+ Pa_GetHostApiInfo(deviceInfo->hostApi)->name);
printf("Max inputs = %d", deviceInfo->maxInputChannels);
printf(", Max outputs = %d\n", deviceInfo->maxOutputChannels);
- printf("Default low input latency = %8.3f\n", deviceInfo->defaultLowInputLatency);
- printf("Default low output latency = %8.3f\n", deviceInfo->defaultLowOutputLatency);
- printf("Default high input latency = %8.3f\n", deviceInfo->defaultHighInputLatency);
- printf("Default high output latency = %8.3f\n", deviceInfo->defaultHighOutputLatency);
- }
+ printf("Default low input latency = %8.3f\n",
+ deviceInfo->defaultLowInputLatency);
+ printf("Default low output latency = %8.3f\n",
+ deviceInfo->defaultLowOutputLatency);
+ printf("Default high input latency = %8.3f\n",
+ deviceInfo->defaultHighInputLatency);
+ printf("Default high output latency = %8.3f\n",
+ deviceInfo->defaultHighOutputLatency);
}
+}
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/portaudio/portaudio_impl.h b/gr-audio/lib/portaudio/portaudio_impl.h
index 0cb099e591..f57a601ac7 100644
--- a/gr-audio/lib/portaudio/portaudio_impl.h
+++ b/gr-audio/lib/portaudio/portaudio_impl.h
@@ -27,12 +27,12 @@
#include <portaudio.h>
namespace gr {
- namespace audio {
+namespace audio {
- PaDeviceIndex pa_find_device_by_name(const char *name);
- void print_devices();
+PaDeviceIndex pa_find_device_by_name(const char* name);
+void print_devices();
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_AUDIO_PORTAUDIO_IMPL_H */
diff --git a/gr-audio/lib/portaudio/portaudio_sink.cc b/gr-audio/lib/portaudio/portaudio_sink.cc
index 56ade35b19..e9ff3759da 100644
--- a/gr-audio/lib/portaudio/portaudio_sink.cc
+++ b/gr-audio/lib/portaudio/portaudio_sink.cc
@@ -43,233 +43,234 @@
#endif
namespace gr {
- namespace audio {
-
- sink::sptr
- portaudio_sink_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block)
- {
- return sink::sptr
- (new portaudio_sink(sampling_rate, device_name, ok_to_block));
- }
+namespace audio {
+
+sink::sptr
+portaudio_sink_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block)
+{
+ return sink::sptr(new portaudio_sink(sampling_rate, device_name, ok_to_block));
+}
//#define LOGGING 0 // define to 0 or 1
#define SAMPLE_FORMAT paFloat32
- typedef float sample_t;
+typedef float sample_t;
- // Number of portaudio buffers in the ringbuffer
- static const unsigned int N_BUFFERS = 4;
-
- static std::string
- default_device_name()
- {
- return prefs::singleton()->get_string
- ("audio_portaudio", "default_output_device", "");
- }
+// Number of portaudio buffers in the ringbuffer
+static const unsigned int N_BUFFERS = 4;
- void
- portaudio_sink::create_ringbuffer(void)
- {
- int bufsize_samples = d_portaudio_buffer_size_frames * d_output_parameters.channelCount;
+static std::string default_device_name()
+{
+ return prefs::singleton()->get_string("audio_portaudio", "default_output_device", "");
+}
- if(d_verbose) {
- fprintf(stderr,"ring buffer size = %d frames\n",
- N_BUFFERS*bufsize_samples/d_output_parameters.channelCount);
- }
+void portaudio_sink::create_ringbuffer(void)
+{
+ int bufsize_samples =
+ d_portaudio_buffer_size_frames * d_output_parameters.channelCount;
- // FYI, the buffer indices are in units of samples.
- d_writer = gr::make_buffer(N_BUFFERS * bufsize_samples, sizeof(sample_t));
- d_reader = gr::buffer_add_reader(d_writer, 0);
+ if (d_verbose) {
+ fprintf(stderr,
+ "ring buffer size = %d frames\n",
+ N_BUFFERS * bufsize_samples / d_output_parameters.channelCount);
}
- /*
- * This routine will be called by the PortAudio engine when audio is needed.
- * It may called at interrupt level on some machines so don't do anything
- * that could mess up the system like calling malloc() or free().
- *
- * Our job is to write framesPerBuffer frames into outputBuffer.
- */
- int
- portaudio_sink_callback(const void *inputBuffer,
- void *outputBuffer,
+ // FYI, the buffer indices are in units of samples.
+ d_writer = gr::make_buffer(N_BUFFERS * bufsize_samples, sizeof(sample_t));
+ d_reader = gr::buffer_add_reader(d_writer, 0);
+}
+
+/*
+ * This routine will be called by the PortAudio engine when audio is needed.
+ * It may called at interrupt level on some machines so don't do anything
+ * that could mess up the system like calling malloc() or free().
+ *
+ * Our job is to write framesPerBuffer frames into outputBuffer.
+ */
+int portaudio_sink_callback(const void* inputBuffer,
+ void* outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
- void *arg)
- {
- portaudio_sink *self = (portaudio_sink *)arg;
- int nreqd_samples =
- framesPerBuffer * self->d_output_parameters.channelCount;
+ void* arg)
+{
+ portaudio_sink* self = (portaudio_sink*)arg;
+ int nreqd_samples = framesPerBuffer * self->d_output_parameters.channelCount;
- int navail_samples = self->d_reader->items_available();
+ int navail_samples = self->d_reader->items_available();
- if(nreqd_samples <= navail_samples) { // We've got enough data...
+ if (nreqd_samples <= navail_samples) { // We've got enough data...
{
- gr::thread::scoped_lock guard(self->d_ringbuffer_mutex);
+ gr::thread::scoped_lock guard(self->d_ringbuffer_mutex);
- memcpy(outputBuffer,
- self->d_reader->read_pointer(),
- nreqd_samples * sizeof(sample_t));
- self->d_reader->update_read_pointer(nreqd_samples);
+ memcpy(outputBuffer,
+ self->d_reader->read_pointer(),
+ nreqd_samples * sizeof(sample_t));
+ self->d_reader->update_read_pointer(nreqd_samples);
- self->d_ringbuffer_ready = true;
+ self->d_ringbuffer_ready = true;
}
// Tell the sink thread there is new room in the ringbuffer.
self->d_ringbuffer_cond.notify_one();
return paContinue;
- }
+ }
- else { // underrun
+ else { // underrun
self->d_nunderuns++;
- ssize_t r = ::write(2, "aU", 2); // FIXME change to non-blocking call
- if(r == -1) {
- perror("audio_portaudio_source::portaudio_source_callback write error to stderr.");
+ ssize_t r = ::write(2, "aU", 2); // FIXME change to non-blocking call
+ if (r == -1) {
+ perror("audio_portaudio_source::portaudio_source_callback write error to "
+ "stderr.");
}
// FIXME we should transfer what we've got and pad the rest
memset(outputBuffer, 0, nreqd_samples * sizeof(sample_t));
self->d_ringbuffer_ready = true;
- self->d_ringbuffer_cond.notify_one(); // Tell the sink to get going!
+ self->d_ringbuffer_cond.notify_one(); // Tell the sink to get going!
return paContinue;
- }
}
-
- // ----------------------------------------------------------------
-
- portaudio_sink::portaudio_sink(int sampling_rate,
- const std::string device_name,
- bool ok_to_block)
- : sync_block("audio_portaudio_sink",
- io_signature::make(0, 0, 0),
- io_signature::make(0, 0, 0)),
- d_sampling_rate(sampling_rate),
- d_device_name(device_name.empty() ? default_device_name() : device_name),
- d_ok_to_block(ok_to_block),
- d_verbose(prefs::singleton()->get_bool("audio_portaudio", "verbose", false)),
- d_portaudio_buffer_size_frames(0),
- d_stream(0),
- d_ringbuffer_mutex(),
- d_ringbuffer_cond(),
- d_ringbuffer_ready(false),
- d_nunderuns(0)
- {
- memset(&d_output_parameters, 0, sizeof(d_output_parameters));
- //if(LOGGING)
- // d_log = gri_logger::singleton();
-
- PaError err;
- int i, numDevices;
- PaDeviceIndex device = 0;
- const PaDeviceInfo *deviceInfo = NULL;
-
- err = Pa_Initialize();
- if(err != paNoError) {
+}
+
+// ----------------------------------------------------------------
+
+portaudio_sink::portaudio_sink(int sampling_rate,
+ const std::string device_name,
+ bool ok_to_block)
+ : sync_block("audio_portaudio_sink",
+ io_signature::make(0, 0, 0),
+ io_signature::make(0, 0, 0)),
+ d_sampling_rate(sampling_rate),
+ d_device_name(device_name.empty() ? default_device_name() : device_name),
+ d_ok_to_block(ok_to_block),
+ d_verbose(prefs::singleton()->get_bool("audio_portaudio", "verbose", false)),
+ d_portaudio_buffer_size_frames(0),
+ d_stream(0),
+ d_ringbuffer_mutex(),
+ d_ringbuffer_cond(),
+ d_ringbuffer_ready(false),
+ d_nunderuns(0)
+{
+ memset(&d_output_parameters, 0, sizeof(d_output_parameters));
+ // if(LOGGING)
+ // d_log = gri_logger::singleton();
+
+ PaError err;
+ int i, numDevices;
+ PaDeviceIndex device = 0;
+ const PaDeviceInfo* deviceInfo = NULL;
+
+ err = Pa_Initialize();
+ if (err != paNoError) {
bail("Initialize failed", err);
- }
+ }
- if(d_verbose)
+ if (d_verbose)
print_devices();
- numDevices = Pa_GetDeviceCount();
- if(numDevices < 0)
+ numDevices = Pa_GetDeviceCount();
+ if (numDevices < 0)
bail("Pa Device count failed", 0);
- if(numDevices == 0)
+ if (numDevices == 0)
bail("no devices available", 0);
- if(d_device_name.empty()) {
+ if (d_device_name.empty()) {
// FIXME Get smarter about picking something
- fprintf(stderr,"\nUsing Default Device\n");
+ fprintf(stderr, "\nUsing Default Device\n");
device = Pa_GetDefaultOutputDevice();
deviceInfo = Pa_GetDeviceInfo(device);
- fprintf(stderr,"%s is the chosen device using %s as the host\n",
- deviceInfo->name, Pa_GetHostApiInfo(deviceInfo->hostApi)->name);
- }
- else {
+ fprintf(stderr,
+ "%s is the chosen device using %s as the host\n",
+ deviceInfo->name,
+ Pa_GetHostApiInfo(deviceInfo->hostApi)->name);
+ } else {
bool found = false;
- fprintf(stderr,"\nTest Devices\n");
- for(i = 0; i < numDevices; i++) {
- deviceInfo = Pa_GetDeviceInfo(i);
- fprintf(stderr,"Testing device name: %s",deviceInfo->name);
-
- if(deviceInfo->maxOutputChannels <= 0) {
- fprintf(stderr,"\n");
- continue;
- }
-
- if(strstr(deviceInfo->name, d_device_name.c_str())) {
- fprintf(stderr," Chosen!\n");
- device = i;
- fprintf(stderr,"%s using %s as the host\n",d_device_name.c_str(),
- Pa_GetHostApiInfo(deviceInfo->hostApi)->name), fflush(stderr);
- found = true;
- deviceInfo = Pa_GetDeviceInfo(device);
- i = numDevices; // force loop exit
- }
- else
- fprintf(stderr,"\n"), fflush(stderr);
+ fprintf(stderr, "\nTest Devices\n");
+ for (i = 0; i < numDevices; i++) {
+ deviceInfo = Pa_GetDeviceInfo(i);
+ fprintf(stderr, "Testing device name: %s", deviceInfo->name);
+
+ if (deviceInfo->maxOutputChannels <= 0) {
+ fprintf(stderr, "\n");
+ continue;
+ }
+
+ if (strstr(deviceInfo->name, d_device_name.c_str())) {
+ fprintf(stderr, " Chosen!\n");
+ device = i;
+ fprintf(stderr,
+ "%s using %s as the host\n",
+ d_device_name.c_str(),
+ Pa_GetHostApiInfo(deviceInfo->hostApi)->name),
+ fflush(stderr);
+ found = true;
+ deviceInfo = Pa_GetDeviceInfo(device);
+ i = numDevices; // force loop exit
+ } else
+ fprintf(stderr, "\n"), fflush(stderr);
}
- if(!found) {
- bail("Failed to find specified device name", 0);
- exit(1);
+ if (!found) {
+ bail("Failed to find specified device name", 0);
+ exit(1);
}
- }
-
- d_output_parameters.device = device;
- d_output_parameters.channelCount = deviceInfo->maxOutputChannels;
- d_output_parameters.sampleFormat = SAMPLE_FORMAT;
- d_output_parameters.suggestedLatency = deviceInfo->defaultLowOutputLatency;
- d_output_parameters.hostApiSpecificStreamInfo = NULL;
-
- // We fill in the real channelCount in check_topology when we know
- // how many inputs are connected to us.
-
- // Now that we know the maximum number of channels (allegedly)
- // supported by the h/w, we can compute a reasonable input
- // signature. The portaudio specs say that they'll accept any
- // number of channels from 1 to max.
- set_input_signature(io_signature::make(1, deviceInfo->maxOutputChannels,
- sizeof(sample_t)));
}
- bool
- portaudio_sink::check_topology(int ninputs, int noutputs)
- {
- PaError err;
+ d_output_parameters.device = device;
+ d_output_parameters.channelCount = deviceInfo->maxOutputChannels;
+ d_output_parameters.sampleFormat = SAMPLE_FORMAT;
+ d_output_parameters.suggestedLatency = deviceInfo->defaultLowOutputLatency;
+ d_output_parameters.hostApiSpecificStreamInfo = NULL;
+
+ // We fill in the real channelCount in check_topology when we know
+ // how many inputs are connected to us.
- if(Pa_IsStreamActive(d_stream)) {
+ // Now that we know the maximum number of channels (allegedly)
+ // supported by the h/w, we can compute a reasonable input
+ // signature. The portaudio specs say that they'll accept any
+ // number of channels from 1 to max.
+ set_input_signature(
+ io_signature::make(1, deviceInfo->maxOutputChannels, sizeof(sample_t)));
+}
+
+bool portaudio_sink::check_topology(int ninputs, int noutputs)
+{
+ PaError err;
+
+ if (Pa_IsStreamActive(d_stream)) {
Pa_CloseStream(d_stream);
d_stream = 0;
- d_reader.reset(); // boost::shared_ptr for d_reader = 0
- d_writer.reset(); // boost::shared_ptr for d_write = 0
- }
+ d_reader.reset(); // boost::shared_ptr for d_reader = 0
+ d_writer.reset(); // boost::shared_ptr for d_write = 0
+ }
- d_output_parameters.channelCount = ninputs; // # of channels we're really using
+ d_output_parameters.channelCount = ninputs; // # of channels we're really using
#if 1
- d_portaudio_buffer_size_frames = (int)(0.0213333333 * d_sampling_rate + 0.5); // Force 1024 frame buffers at 48000
- fprintf(stderr, "Latency = %8.5f, requested sampling_rate = %g\n", // Force latency to 21.3333333.. ms
- 0.0213333333, (double)d_sampling_rate);
+ d_portaudio_buffer_size_frames =
+ (int)(0.0213333333 * d_sampling_rate + 0.5); // Force 1024 frame buffers at 48000
+ fprintf(stderr,
+ "Latency = %8.5f, requested sampling_rate = %g\n", // Force latency
+ // to 21.3333333.. ms
+ 0.0213333333,
+ (double)d_sampling_rate);
#endif
- err = Pa_OpenStream(&d_stream,
- NULL, // No input
- &d_output_parameters,
- d_sampling_rate,
- d_portaudio_buffer_size_frames,
- paClipOff,
- &portaudio_sink_callback,
- (void*)this);
-
- if(err != paNoError) {
+ err = Pa_OpenStream(&d_stream,
+ NULL, // No input
+ &d_output_parameters,
+ d_sampling_rate,
+ d_portaudio_buffer_size_frames,
+ paClipOff,
+ &portaudio_sink_callback,
+ (void*)this);
+
+ if (err != paNoError) {
output_error_msg("OpenStream failed", err);
return false;
- }
+ }
#if 0
const PaStreamInfo *psi = Pa_GetStreamInfo(d_stream);
@@ -279,100 +280,100 @@ namespace gr {
d_output_parameters.suggestedLatency, psi->sampleRate);
#endif
- fprintf(stderr, "d_portaudio_buffer_size_frames = %d\n",
- d_portaudio_buffer_size_frames);
+ fprintf(
+ stderr, "d_portaudio_buffer_size_frames = %d\n", d_portaudio_buffer_size_frames);
- assert(d_portaudio_buffer_size_frames != 0);
+ assert(d_portaudio_buffer_size_frames != 0);
- create_ringbuffer();
+ create_ringbuffer();
- err = Pa_StartStream(d_stream);
- if(err != paNoError) {
+ err = Pa_StartStream(d_stream);
+ if (err != paNoError) {
output_error_msg("StartStream failed", err);
return false;
- }
-
- return true;
}
- portaudio_sink::~portaudio_sink()
- {
- Pa_StopStream(d_stream); // wait for output to drain
- Pa_CloseStream(d_stream);
- Pa_Terminate();
- }
+ return true;
+}
+
+portaudio_sink::~portaudio_sink()
+{
+ Pa_StopStream(d_stream); // wait for output to drain
+ Pa_CloseStream(d_stream);
+ Pa_Terminate();
+}
- /*
- * This version consumes everything sent to it, blocking if required.
- * I think this will allow us better control of the total buffering/latency
- * in the audio path.
- */
- int
- portaudio_sink::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- const float **in = (const float **)&input_items[0];
- const unsigned nchan = d_output_parameters.channelCount; // # of channels == samples/frame
-
- int k;
- for(k = 0; k < noutput_items;) {
- int nframes = d_writer->space_available() / nchan; // How much space in ringbuffer
- if(nframes == 0) { // no room...
- if(d_ok_to_block) {
- {
- gr::thread::scoped_lock guard(d_ringbuffer_mutex);
- while(!d_ringbuffer_ready)
- d_ringbuffer_cond.wait(guard);
+/*
+ * This version consumes everything sent to it, blocking if required.
+ * I think this will allow us better control of the total buffering/latency
+ * in the audio path.
+ */
+int portaudio_sink::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ const float** in = (const float**)&input_items[0];
+ const unsigned nchan =
+ d_output_parameters.channelCount; // # of channels == samples/frame
+
+ int k;
+ for (k = 0; k < noutput_items;) {
+ int nframes = d_writer->space_available() / nchan; // How much space in ringbuffer
+ if (nframes == 0) { // no room...
+ if (d_ok_to_block) {
+ {
+ gr::thread::scoped_lock guard(d_ringbuffer_mutex);
+ while (!d_ringbuffer_ready)
+ d_ringbuffer_cond.wait(guard);
+ }
+ continue;
+ } else {
+ // There's no room and we're not allowed to block.
+ // (A USRP is most likely controlling the pacing through the pipeline.)
+ // We drop the samples on the ground, and say we processed them all ;)
+ //
+ // FIXME, there's probably room for a bit more finesse here.
+ return noutput_items;
}
- continue;
- }
- else {
- // There's no room and we're not allowed to block.
- // (A USRP is most likely controlling the pacing through the pipeline.)
- // We drop the samples on the ground, and say we processed them all ;)
- //
- // FIXME, there's probably room for a bit more finesse here.
- return noutput_items;
- }
}
// We can write the smaller of the request and the room we've got
{
- gr::thread::scoped_lock guard(d_ringbuffer_mutex);
+ gr::thread::scoped_lock guard(d_ringbuffer_mutex);
- int nf = std::min(noutput_items - k, nframes);
- float *p = (float*)d_writer->write_pointer();
+ int nf = std::min(noutput_items - k, nframes);
+ float* p = (float*)d_writer->write_pointer();
- for(int i = 0; i < nf; i++) {
- for(unsigned int c = 0; c < nchan; c++) {
- *p++ = in[c][k + i];
+ for (int i = 0; i < nf; i++) {
+ for (unsigned int c = 0; c < nchan; c++) {
+ *p++ = in[c][k + i];
+ }
}
- }
- d_writer->update_write_pointer(nf * nchan);
- k += nf;
+ d_writer->update_write_pointer(nf * nchan);
+ k += nf;
- d_ringbuffer_ready = false;
+ d_ringbuffer_ready = false;
}
- }
-
- return k; // tell how many we actually did
- }
-
- void
- portaudio_sink::output_error_msg(const char *msg, int err)
- {
- fprintf(stderr, "audio_portaudio_sink[%s]: %s: %s\n",
- d_device_name.c_str(), msg, Pa_GetErrorText(err));
- }
-
- void
- portaudio_sink::bail(const char *msg, int err)
- {
- output_error_msg(msg, err);
- throw std::runtime_error("audio_portaudio_sink");
}
- } /* namespace audio */
+ return k; // tell how many we actually did
+}
+
+void portaudio_sink::output_error_msg(const char* msg, int err)
+{
+ fprintf(stderr,
+ "audio_portaudio_sink[%s]: %s: %s\n",
+ d_device_name.c_str(),
+ msg,
+ Pa_GetErrorText(err));
+}
+
+void portaudio_sink::bail(const char* msg, int err)
+{
+ output_error_msg(msg, err);
+ throw std::runtime_error("audio_portaudio_sink");
+}
+
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/portaudio/portaudio_sink.h b/gr-audio/lib/portaudio/portaudio_sink.h
index d86681036f..98e72fc2c2 100644
--- a/gr-audio/lib/portaudio/portaudio_sink.h
+++ b/gr-audio/lib/portaudio/portaudio_sink.h
@@ -31,60 +31,58 @@
//#include <gri_logger.h>
namespace gr {
- namespace audio {
+namespace audio {
- PaStreamCallback portaudio_sink_callback;
+PaStreamCallback portaudio_sink_callback;
- /*!
- * \brief Audio sink using PORTAUDIO
- * \ingroup audio_blk
- *
- * Input samples must be in the range [-1,1].
- */
- class portaudio_sink : public sink
- {
- friend PaStreamCallback portaudio_sink_callback;
+/*!
+ * \brief Audio sink using PORTAUDIO
+ * \ingroup audio_blk
+ *
+ * Input samples must be in the range [-1,1].
+ */
+class portaudio_sink : public sink
+{
+ friend PaStreamCallback portaudio_sink_callback;
- unsigned int d_sampling_rate;
- std::string d_device_name;
- bool d_ok_to_block;
- bool d_verbose;
+ unsigned int d_sampling_rate;
+ std::string d_device_name;
+ bool d_ok_to_block;
+ bool d_verbose;
- unsigned int d_portaudio_buffer_size_frames; // number of frames in a portaudio buffer
+ unsigned int d_portaudio_buffer_size_frames; // number of frames in a portaudio buffer
- PaStream *d_stream;
- PaStreamParameters d_output_parameters;
+ PaStream* d_stream;
+ PaStreamParameters d_output_parameters;
- gr::buffer_sptr d_writer; // buffer used between work and callback
- gr::buffer_reader_sptr d_reader;
+ gr::buffer_sptr d_writer; // buffer used between work and callback
+ gr::buffer_reader_sptr d_reader;
- gr::thread::mutex d_ringbuffer_mutex;
- gr::thread::condition_variable d_ringbuffer_cond;
- bool d_ringbuffer_ready;
+ gr::thread::mutex d_ringbuffer_mutex;
+ gr::thread::condition_variable d_ringbuffer_cond;
+ bool d_ringbuffer_ready;
- // random stats
- int d_nunderuns; // count of underruns
- //gri_logger_sptr d_log; // handle to non-blocking logging instance
+ // random stats
+ int d_nunderuns; // count of underruns
+ // gri_logger_sptr d_log; // handle to non-blocking logging instance
- void output_error_msg(const char *msg, int err);
- void bail(const char *msg, int err);
- void create_ringbuffer();
+ void output_error_msg(const char* msg, int err);
+ void bail(const char* msg, int err);
+ void create_ringbuffer();
- public:
- portaudio_sink(int sampling_rate,
- const std::string device_name,
- bool ok_to_block);
+public:
+ portaudio_sink(int sampling_rate, const std::string device_name, bool ok_to_block);
- ~portaudio_sink();
+ ~portaudio_sink();
- bool check_topology(int ninputs, int noutputs);
+ bool check_topology(int ninputs, int noutputs);
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_AUDIO_PORTAUDIO_SINK_H */
diff --git a/gr-audio/lib/portaudio/portaudio_source.cc b/gr-audio/lib/portaudio/portaudio_source.cc
index 767fc8e281..f785362946 100644
--- a/gr-audio/lib/portaudio/portaudio_source.cc
+++ b/gr-audio/lib/portaudio/portaudio_source.cc
@@ -43,228 +43,230 @@
#endif
namespace gr {
- namespace audio {
-
- source::sptr
- portaudio_source_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block)
- {
- return source::sptr
- (new portaudio_source(sampling_rate, device_name, ok_to_block));
- }
+namespace audio {
+
+source::sptr
+portaudio_source_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block)
+{
+ return source::sptr(new portaudio_source(sampling_rate, device_name, ok_to_block));
+}
//#define LOGGING 0 // define to 0 or 1
#define SAMPLE_FORMAT paFloat32
- typedef float sample_t;
+typedef float sample_t;
- // Number of portaudio buffers in the ringbuffer
- static const unsigned int N_BUFFERS = 4;
+// Number of portaudio buffers in the ringbuffer
+static const unsigned int N_BUFFERS = 4;
- static std::string
- default_device_name()
- {
- return prefs::singleton()->get_string
- ("audio_portaudio", "default_input_device", "");
- }
+static std::string default_device_name()
+{
+ return prefs::singleton()->get_string("audio_portaudio", "default_input_device", "");
+}
- void
- portaudio_source::create_ringbuffer(void)
- {
- int bufsize_samples = d_portaudio_buffer_size_frames * d_input_parameters.channelCount;
+void portaudio_source::create_ringbuffer(void)
+{
+ int bufsize_samples =
+ d_portaudio_buffer_size_frames * d_input_parameters.channelCount;
- if(d_verbose) {
- fprintf(stderr, "ring buffer size = %d frames\n",
- N_BUFFERS*bufsize_samples/d_input_parameters.channelCount);
- }
-
- // FYI, the buffer indices are in units of samples.
- d_writer = gr::make_buffer(N_BUFFERS * bufsize_samples, sizeof(sample_t));
- d_reader = gr::buffer_add_reader(d_writer, 0);
+ if (d_verbose) {
+ fprintf(stderr,
+ "ring buffer size = %d frames\n",
+ N_BUFFERS * bufsize_samples / d_input_parameters.channelCount);
}
- /*
- * This routine will be called by the PortAudio engine when audio is needed.
- * It may called at interrupt level on some machines so don't do anything
- * that could mess up the system like calling malloc() or free().
- *
- * Our job is to copy framesPerBuffer frames from inputBuffer.
- */
- int
- portaudio_source_callback(const void *inputBuffer,
- void *outputBuffer,
+ // FYI, the buffer indices are in units of samples.
+ d_writer = gr::make_buffer(N_BUFFERS * bufsize_samples, sizeof(sample_t));
+ d_reader = gr::buffer_add_reader(d_writer, 0);
+}
+
+/*
+ * This routine will be called by the PortAudio engine when audio is needed.
+ * It may called at interrupt level on some machines so don't do anything
+ * that could mess up the system like calling malloc() or free().
+ *
+ * Our job is to copy framesPerBuffer frames from inputBuffer.
+ */
+int portaudio_source_callback(const void* inputBuffer,
+ void* outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
- void *arg)
- {
- portaudio_source *self = (portaudio_source *)arg;
- int nchan = self->d_input_parameters.channelCount;
- int nframes_to_copy = framesPerBuffer;
- int nframes_room = self->d_writer->space_available() / nchan;
-
- if(nframes_to_copy <= nframes_room) { // We've got room for the data ..
- //if (LOGGING)
+ void* arg)
+{
+ portaudio_source* self = (portaudio_source*)arg;
+ int nchan = self->d_input_parameters.channelCount;
+ int nframes_to_copy = framesPerBuffer;
+ int nframes_room = self->d_writer->space_available() / nchan;
+
+ if (nframes_to_copy <= nframes_room) { // We've got room for the data ..
+ // if (LOGGING)
// self->d_log->printf("PAsrc cb: f/b = %4ld\n", framesPerBuffer);
// copy from input buffer to ringbuffer
{
- gr::thread::scoped_lock(d_ringbuffer_mutex);
+ gr::thread::scoped_lock(d_ringbuffer_mutex);
- memcpy(self->d_writer->write_pointer(),
- inputBuffer,
- nframes_to_copy * nchan * sizeof(sample_t));
- self->d_writer->update_write_pointer(nframes_to_copy * nchan);
+ memcpy(self->d_writer->write_pointer(),
+ inputBuffer,
+ nframes_to_copy * nchan * sizeof(sample_t));
+ self->d_writer->update_write_pointer(nframes_to_copy * nchan);
- // Tell the source thread there is new data in the ringbuffer.
- self->d_ringbuffer_ready = true;
+ // Tell the source thread there is new data in the ringbuffer.
+ self->d_ringbuffer_ready = true;
}
self->d_ringbuffer_cond.notify_one();
return paContinue;
- }
+ }
- else { // overrun
+ else { // overrun
self->d_noverruns++;
- ssize_t r = ::write(2, "aO", 2); // FIXME change to non-blocking call
- if(r == -1) {
- perror("audio_portaudio_source::portaudio_source_callback write error to stderr.");
+ ssize_t r = ::write(2, "aO", 2); // FIXME change to non-blocking call
+ if (r == -1) {
+ perror("audio_portaudio_source::portaudio_source_callback write error to "
+ "stderr.");
}
self->d_ringbuffer_ready = false;
- self->d_ringbuffer_cond.notify_one(); // Tell the sink to get going!
+ self->d_ringbuffer_cond.notify_one(); // Tell the sink to get going!
return paContinue;
- }
}
-
- // ----------------------------------------------------------------
-
- portaudio_source::portaudio_source(int sampling_rate,
- const std::string device_name,
- bool ok_to_block)
- : sync_block("audio_portaudio_source",
- io_signature::make(0, 0, 0),
- io_signature::make(0, 0, 0)),
- d_sampling_rate(sampling_rate),
- d_device_name(device_name.empty() ? default_device_name() : device_name),
- d_ok_to_block(ok_to_block),
- d_verbose(prefs::singleton()->get_bool("audio_portaudio", "verbose", false)),
- d_portaudio_buffer_size_frames(0),
- d_stream(0),
- d_ringbuffer_mutex(),
- d_ringbuffer_cond(),
- d_ringbuffer_ready(false),
- d_noverruns(0)
- {
- memset(&d_input_parameters, 0, sizeof(d_input_parameters));
- //if(LOGGING)
- // d_log = gri_logger::singleton();
-
- PaError err;
- int i, numDevices;
- PaDeviceIndex device = 0;
- const PaDeviceInfo *deviceInfo = NULL;
-
- err = Pa_Initialize();
- if(err != paNoError) {
+}
+
+// ----------------------------------------------------------------
+
+portaudio_source::portaudio_source(int sampling_rate,
+ const std::string device_name,
+ bool ok_to_block)
+ : sync_block("audio_portaudio_source",
+ io_signature::make(0, 0, 0),
+ io_signature::make(0, 0, 0)),
+ d_sampling_rate(sampling_rate),
+ d_device_name(device_name.empty() ? default_device_name() : device_name),
+ d_ok_to_block(ok_to_block),
+ d_verbose(prefs::singleton()->get_bool("audio_portaudio", "verbose", false)),
+ d_portaudio_buffer_size_frames(0),
+ d_stream(0),
+ d_ringbuffer_mutex(),
+ d_ringbuffer_cond(),
+ d_ringbuffer_ready(false),
+ d_noverruns(0)
+{
+ memset(&d_input_parameters, 0, sizeof(d_input_parameters));
+ // if(LOGGING)
+ // d_log = gri_logger::singleton();
+
+ PaError err;
+ int i, numDevices;
+ PaDeviceIndex device = 0;
+ const PaDeviceInfo* deviceInfo = NULL;
+
+ err = Pa_Initialize();
+ if (err != paNoError) {
bail("Initialize failed", err);
- }
+ }
- if(d_verbose)
+ if (d_verbose)
print_devices();
- numDevices = Pa_GetDeviceCount();
- if(numDevices < 0)
+ numDevices = Pa_GetDeviceCount();
+ if (numDevices < 0)
bail("Pa Device count failed", 0);
- if(numDevices == 0)
+ if (numDevices == 0)
bail("no devices available", 0);
- if(d_device_name.empty()) {
+ if (d_device_name.empty()) {
// FIXME Get smarter about picking something
device = Pa_GetDefaultInputDevice();
deviceInfo = Pa_GetDeviceInfo(device);
- fprintf(stderr,"%s is the chosen device using %s as the host\n",
- deviceInfo->name, Pa_GetHostApiInfo(deviceInfo->hostApi)->name);
- }
- else {
+ fprintf(stderr,
+ "%s is the chosen device using %s as the host\n",
+ deviceInfo->name,
+ Pa_GetHostApiInfo(deviceInfo->hostApi)->name);
+ } else {
bool found = false;
- for(i = 0; i < numDevices; i++) {
- deviceInfo = Pa_GetDeviceInfo(i);
- fprintf(stderr,"Testing device name: %s",deviceInfo->name);
- if(deviceInfo->maxInputChannels <= 0) {
- fprintf(stderr,"\n");
- continue;
- }
- if(strstr(deviceInfo->name, d_device_name.c_str())) {
- fprintf(stderr," Chosen!\n");
- device = i;
- fprintf(stderr,"%s using %s as the host\n",d_device_name.c_str(),
- Pa_GetHostApiInfo(deviceInfo->hostApi)->name), fflush(stderr);
- found = true;
- deviceInfo = Pa_GetDeviceInfo(device);
- i = numDevices; // force loop exit
- }
- else
- fprintf(stderr,"\n"),fflush(stderr);
+ for (i = 0; i < numDevices; i++) {
+ deviceInfo = Pa_GetDeviceInfo(i);
+ fprintf(stderr, "Testing device name: %s", deviceInfo->name);
+ if (deviceInfo->maxInputChannels <= 0) {
+ fprintf(stderr, "\n");
+ continue;
+ }
+ if (strstr(deviceInfo->name, d_device_name.c_str())) {
+ fprintf(stderr, " Chosen!\n");
+ device = i;
+ fprintf(stderr,
+ "%s using %s as the host\n",
+ d_device_name.c_str(),
+ Pa_GetHostApiInfo(deviceInfo->hostApi)->name),
+ fflush(stderr);
+ found = true;
+ deviceInfo = Pa_GetDeviceInfo(device);
+ i = numDevices; // force loop exit
+ } else
+ fprintf(stderr, "\n"), fflush(stderr);
}
- if(!found) {
- bail("Failed to find specified device name", 0);
+ if (!found) {
+ bail("Failed to find specified device name", 0);
}
- }
-
- d_input_parameters.device = device;
- d_input_parameters.channelCount = deviceInfo->maxInputChannels;
- d_input_parameters.sampleFormat = SAMPLE_FORMAT;
- d_input_parameters.suggestedLatency = deviceInfo->defaultLowInputLatency;
- d_input_parameters.hostApiSpecificStreamInfo = NULL;
-
- // We fill in the real channelCount in check_topology when we know
- // how many inputs are connected to us.
-
- // Now that we know the maximum number of channels (allegedly)
- // supported by the h/w, we can compute a reasonable output
- // signature. The portaudio specs say that they'll accept any
- // number of channels from 1 to max.
- set_output_signature(io_signature::make(1, deviceInfo->maxInputChannels,
- sizeof (sample_t)));
}
- bool
- portaudio_source::check_topology(int ninputs, int noutputs)
- {
- PaError err;
+ d_input_parameters.device = device;
+ d_input_parameters.channelCount = deviceInfo->maxInputChannels;
+ d_input_parameters.sampleFormat = SAMPLE_FORMAT;
+ d_input_parameters.suggestedLatency = deviceInfo->defaultLowInputLatency;
+ d_input_parameters.hostApiSpecificStreamInfo = NULL;
+
+ // We fill in the real channelCount in check_topology when we know
+ // how many inputs are connected to us.
- if(Pa_IsStreamActive(d_stream)) {
+ // Now that we know the maximum number of channels (allegedly)
+ // supported by the h/w, we can compute a reasonable output
+ // signature. The portaudio specs say that they'll accept any
+ // number of channels from 1 to max.
+ set_output_signature(
+ io_signature::make(1, deviceInfo->maxInputChannels, sizeof(sample_t)));
+}
+
+bool portaudio_source::check_topology(int ninputs, int noutputs)
+{
+ PaError err;
+
+ if (Pa_IsStreamActive(d_stream)) {
Pa_CloseStream(d_stream);
d_stream = 0;
- d_reader.reset(); // boost::shared_ptr for d_reader = 0
- d_writer.reset(); // boost::shared_ptr for d_write = 0
- }
+ d_reader.reset(); // boost::shared_ptr for d_reader = 0
+ d_writer.reset(); // boost::shared_ptr for d_write = 0
+ }
- d_input_parameters.channelCount = noutputs; // # of channels we're really using
+ d_input_parameters.channelCount = noutputs; // # of channels we're really using
#if 1
- d_portaudio_buffer_size_frames = (int)(0.0213333333 * d_sampling_rate + 0.5); // Force 512 frame buffers at 48000
- fprintf(stderr, "Latency = %8.5f, requested sampling_rate = %g\n", // Force latency to 21.3333333.. ms
- 0.0213333333, (double)d_sampling_rate);
+ d_portaudio_buffer_size_frames =
+ (int)(0.0213333333 * d_sampling_rate + 0.5); // Force 512 frame buffers at 48000
+ fprintf(stderr,
+ "Latency = %8.5f, requested sampling_rate = %g\n", // Force latency
+ // to 21.3333333.. ms
+ 0.0213333333,
+ (double)d_sampling_rate);
#endif
- err = Pa_OpenStream(&d_stream,
- &d_input_parameters,
- NULL, // No output
- d_sampling_rate,
- d_portaudio_buffer_size_frames,
- paClipOff,
- &portaudio_source_callback,
- (void*)this);
-
- if(err != paNoError) {
+ err = Pa_OpenStream(&d_stream,
+ &d_input_parameters,
+ NULL, // No output
+ d_sampling_rate,
+ d_portaudio_buffer_size_frames,
+ paClipOff,
+ &portaudio_source_callback,
+ (void*)this);
+
+ if (err != paNoError) {
output_error_msg("OpenStream failed", err);
return false;
- }
+ }
#if 0
const PaStreamInfo *psi = Pa_GetStreamInfo(d_stream);
@@ -274,113 +276,114 @@ namespace gr {
d_input_parameters.suggestedLatency, psi->sampleRate);
#endif
- fprintf(stderr, "d_portaudio_buffer_size_frames = %d\n",
- d_portaudio_buffer_size_frames);
+ fprintf(
+ stderr, "d_portaudio_buffer_size_frames = %d\n", d_portaudio_buffer_size_frames);
- assert(d_portaudio_buffer_size_frames != 0);
+ assert(d_portaudio_buffer_size_frames != 0);
- create_ringbuffer();
+ create_ringbuffer();
- err = Pa_StartStream(d_stream);
- if(err != paNoError) {
+ err = Pa_StartStream(d_stream);
+ if (err != paNoError) {
output_error_msg("StartStream failed", err);
return false;
- }
-
- return true;
- }
-
- portaudio_source::~portaudio_source()
- {
- Pa_StopStream(d_stream); // wait for output to drain
- Pa_CloseStream(d_stream);
- Pa_Terminate();
}
- int
- portaudio_source::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- float **out = (float **)&output_items[0];
- const unsigned nchan = d_input_parameters.channelCount; // # of channels == samples/frame
-
- int k;
- for(k = 0; k < noutput_items;) {
- int nframes = d_reader->items_available() / nchan; // # of frames in ringbuffer
- if(nframes == 0) { // no data right now...
- if(k > 0) // If we've produced anything so far, return that
- return k;
-
- if(d_ok_to_block) {
- gr::thread::scoped_lock guard(d_ringbuffer_mutex);
- while(d_ringbuffer_ready == false)
- d_ringbuffer_cond.wait(guard); // block here, then try again
- continue;
- }
-
- assert(k == 0);
-
- // There's no data and we're not allowed to block.
- // (A USRP is most likely controlling the pacing through the pipeline.)
- // This is an underrun. The scheduler wouldn't have called us if it
- // had anything better to do. Thus we really need to produce some amount
- // of "fill".
- //
- // There are lots of options for comfort noise, etc.
- // FIXME We'll fill with zeros for now. Yes, it will "click"...
-
- // Fill with some frames of zeros
- {
- gr::thread::scoped_lock guard(d_ringbuffer_mutex);
-
- int nf = std::min(noutput_items - k, (int)d_portaudio_buffer_size_frames);
- for(int i = 0; i < nf; i++) {
- for(unsigned int c = 0; c < nchan; c++) {
- out[c][k + i] = 0;
- }
+ return true;
+}
+
+portaudio_source::~portaudio_source()
+{
+ Pa_StopStream(d_stream); // wait for output to drain
+ Pa_CloseStream(d_stream);
+ Pa_Terminate();
+}
+
+int portaudio_source::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ float** out = (float**)&output_items[0];
+ const unsigned nchan =
+ d_input_parameters.channelCount; // # of channels == samples/frame
+
+ int k;
+ for (k = 0; k < noutput_items;) {
+ int nframes = d_reader->items_available() / nchan; // # of frames in ringbuffer
+ if (nframes == 0) { // no data right now...
+ if (k > 0) // If we've produced anything so far, return that
+ return k;
+
+ if (d_ok_to_block) {
+ gr::thread::scoped_lock guard(d_ringbuffer_mutex);
+ while (d_ringbuffer_ready == false)
+ d_ringbuffer_cond.wait(guard); // block here, then try again
+ continue;
}
- k += nf;
- d_ringbuffer_ready = false;
- return k;
- }
+ assert(k == 0);
+
+ // There's no data and we're not allowed to block.
+ // (A USRP is most likely controlling the pacing through the pipeline.)
+ // This is an underrun. The scheduler wouldn't have called us if it
+ // had anything better to do. Thus we really need to produce some amount
+ // of "fill".
+ //
+ // There are lots of options for comfort noise, etc.
+ // FIXME We'll fill with zeros for now. Yes, it will "click"...
+
+ // Fill with some frames of zeros
+ {
+ gr::thread::scoped_lock guard(d_ringbuffer_mutex);
+
+ int nf = std::min(noutput_items - k, (int)d_portaudio_buffer_size_frames);
+ for (int i = 0; i < nf; i++) {
+ for (unsigned int c = 0; c < nchan; c++) {
+ out[c][k + i] = 0;
+ }
+ }
+ k += nf;
+
+ d_ringbuffer_ready = false;
+ return k;
+ }
}
// We can read the smaller of the request and what's in the buffer.
{
- gr::thread::scoped_lock guard(d_ringbuffer_mutex);
+ gr::thread::scoped_lock guard(d_ringbuffer_mutex);
- int nf = std::min(noutput_items - k, nframes);
+ int nf = std::min(noutput_items - k, nframes);
- const float *p = (const float*)d_reader->read_pointer();
- for(int i = 0; i < nf; i++) {
- for(unsigned int c = 0; c < nchan; c++) {
- out[c][k + i] = *p++;
+ const float* p = (const float*)d_reader->read_pointer();
+ for (int i = 0; i < nf; i++) {
+ for (unsigned int c = 0; c < nchan; c++) {
+ out[c][k + i] = *p++;
+ }
}
- }
- d_reader->update_read_pointer(nf * nchan);
- k += nf;
- d_ringbuffer_ready = false;
+ d_reader->update_read_pointer(nf * nchan);
+ k += nf;
+ d_ringbuffer_ready = false;
}
- }
-
- return k; // tell how many we actually did
- }
-
- void
- portaudio_source::output_error_msg(const char *msg, int err)
- {
- fprintf(stderr, "audio_portaudio_source[%s]: %s: %s\n",
- d_device_name.c_str (), msg, Pa_GetErrorText(err));
- }
-
- void
- portaudio_source::bail(const char *msg, int err)
- {
- output_error_msg(msg, err);
- throw std::runtime_error("audio_portaudio_source");
}
- } /* namespace audio */
+ return k; // tell how many we actually did
+}
+
+void portaudio_source::output_error_msg(const char* msg, int err)
+{
+ fprintf(stderr,
+ "audio_portaudio_source[%s]: %s: %s\n",
+ d_device_name.c_str(),
+ msg,
+ Pa_GetErrorText(err));
+}
+
+void portaudio_source::bail(const char* msg, int err)
+{
+ output_error_msg(msg, err);
+ throw std::runtime_error("audio_portaudio_source");
+}
+
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/portaudio/portaudio_source.h b/gr-audio/lib/portaudio/portaudio_source.h
index 7d315c5bc1..a72cdd4129 100644
--- a/gr-audio/lib/portaudio/portaudio_source.h
+++ b/gr-audio/lib/portaudio/portaudio_source.h
@@ -31,59 +31,57 @@
#include <stdexcept>
namespace gr {
- namespace audio {
+namespace audio {
- PaStreamCallback portaudio_source_callback;
+PaStreamCallback portaudio_source_callback;
- /*!
- * \brief Audio source using PORTAUDIO
- * \ingroup audio_blk
- *
- * Input samples must be in the range [-1,1].
- */
- class portaudio_source : public source
- {
- friend PaStreamCallback portaudio_source_callback;
+/*!
+ * \brief Audio source using PORTAUDIO
+ * \ingroup audio_blk
+ *
+ * Input samples must be in the range [-1,1].
+ */
+class portaudio_source : public source
+{
+ friend PaStreamCallback portaudio_source_callback;
- unsigned int d_sampling_rate;
- std::string d_device_name;
- bool d_ok_to_block;
- bool d_verbose;
+ unsigned int d_sampling_rate;
+ std::string d_device_name;
+ bool d_ok_to_block;
+ bool d_verbose;
- unsigned int d_portaudio_buffer_size_frames; // number of frames in a portaudio buffer
+ unsigned int d_portaudio_buffer_size_frames; // number of frames in a portaudio buffer
- PaStream *d_stream;
- PaStreamParameters d_input_parameters;
+ PaStream* d_stream;
+ PaStreamParameters d_input_parameters;
- gr::buffer_sptr d_writer; // buffer used between work and callback
- gr::buffer_reader_sptr d_reader;
+ gr::buffer_sptr d_writer; // buffer used between work and callback
+ gr::buffer_reader_sptr d_reader;
- gr::thread::mutex d_ringbuffer_mutex;
- gr::thread::condition_variable d_ringbuffer_cond;
- bool d_ringbuffer_ready;
+ gr::thread::mutex d_ringbuffer_mutex;
+ gr::thread::condition_variable d_ringbuffer_cond;
+ bool d_ringbuffer_ready;
- // random stats
- int d_noverruns; // count of overruns
+ // random stats
+ int d_noverruns; // count of overruns
- void output_error_msg(const char *msg, int err);
- void bail(const char *msg, int err);
- void create_ringbuffer();
+ void output_error_msg(const char* msg, int err);
+ void bail(const char* msg, int err);
+ void create_ringbuffer();
- public:
- portaudio_source(int sampling_rate,
- const std::string device_name,
- bool ok_to_block);
+public:
+ portaudio_source(int sampling_rate, const std::string device_name, bool ok_to_block);
- ~portaudio_source();
+ ~portaudio_source();
- bool check_topology(int ninputs, int noutputs);
+ bool check_topology(int ninputs, int noutputs);
- int work(int ninput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
+ int work(int ninput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_AUDIO_PORTAUDIO_SOURCE_H */
diff --git a/gr-audio/lib/windows/windows_sink.cc b/gr-audio/lib/windows/windows_sink.cc
index 6c17084c08..7c220ff831 100644
--- a/gr-audio/lib/windows/windows_sink.cc
+++ b/gr-audio/lib/windows/windows_sink.cc
@@ -1,24 +1,24 @@
/* -*- c++ -*- */
/*
-* Copyright 2004-2011,2013-2014 Free Software Foundation, Inc.
-*
-* This file is part of GNU Radio
-*
-* GNU Radio is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 3, or (at your option)
-* any later version.
-*
-* GNU Radio is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with GNU Radio; see the file COPYING. If not, write to
-* the Free Software Foundation, Inc., 51 Franklin Street,
-* Boston, MA 02110-1301, USA.
-*/
+ * Copyright 2004-2011,2013-2014 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -40,343 +40,357 @@
#include <sstream>
namespace gr {
- namespace audio {
+namespace audio {
- sink::sptr
- windows_sink_fcn(int sampling_rate,
- const std::string &device_name,
- bool ok_to_block)
- {
- return sink::sptr
- (new windows_sink(sampling_rate, device_name, ok_to_block));
- }
+sink::sptr
+windows_sink_fcn(int sampling_rate, const std::string& device_name, bool ok_to_block)
+{
+ return sink::sptr(new windows_sink(sampling_rate, device_name, ok_to_block));
+}
- static const double CHUNK_TIME = prefs::singleton()->get_double("audio_windows", "period_time", 0.1); // 100 ms (below 3ms distortion will likely occur regardless of number of buffers, will likely be a higher limit on slower machines)
- static const int nPeriods = prefs::singleton()->get_long("audio_windows", "nperiods", 4); // 4 should be more than enough with a normal chunk time (2 will likely work as well)... at 3ms chunks 10 was enough on a fast machine
- static const bool verbose = prefs::singleton()->get_bool("audio_windows", "verbose", false);
- static const std::string default_device = prefs::singleton()->get_string("audio_windows", "standard_output_device", "default");
+static const double CHUNK_TIME = prefs::singleton()->get_double(
+ "audio_windows",
+ "period_time",
+ 0.1); // 100 ms (below 3ms distortion will likely occur regardless of number of
+ // buffers, will likely be a higher limit on slower machines)
+static const int nPeriods = prefs::singleton()->get_long(
+ "audio_windows",
+ "nperiods",
+ 4); // 4 should be more than enough with a normal chunk time (2 will likely work as
+ // well)... at 3ms chunks 10 was enough on a fast machine
+static const bool verbose =
+ prefs::singleton()->get_bool("audio_windows", "verbose", false);
+static const std::string default_device =
+ prefs::singleton()->get_string("audio_windows", "standard_output_device", "default");
- static std::string
- default_device_name()
- {
- return (default_device == "default" ? "WAVE_MAPPER" : default_device);
- }
+static std::string default_device_name()
+{
+ return (default_device == "default" ? "WAVE_MAPPER" : default_device);
+}
- windows_sink::windows_sink(int sampling_freq, const std::string device_name, bool ok_to_block)
- : sync_block("audio_windows_sink",
- io_signature::make(1, 2, sizeof(float)),
- io_signature::make(0, 0, 0)),
- d_sampling_freq(sampling_freq),
- d_device_name(device_name.empty() ? default_device_name() : device_name),
- d_fd(-1), d_buffers(0), d_chunk_size(0), d_ok_to_block(ok_to_block)
- {
- /* Initialize the WAVEFORMATEX for 16-bit, 44KHz, stereo */
- wave_format.wFormatTag = WAVE_FORMAT_PCM;
- wave_format.nChannels = 2; // changing this will require adjustments to the work routine.
- wave_format.wBitsPerSample = 16; // changing this will necessitate changing buffer type from short.
- wave_format.nSamplesPerSec = d_sampling_freq; // 44100 is default but up to flowgraph settings;
- wave_format.nBlockAlign =
- wave_format.nChannels * (wave_format.wBitsPerSample / 8);
- wave_format.nAvgBytesPerSec =
- wave_format.nSamplesPerSec * wave_format.nBlockAlign;
- wave_format.cbSize = 0;
+windows_sink::windows_sink(int sampling_freq,
+ const std::string device_name,
+ bool ok_to_block)
+ : sync_block("audio_windows_sink",
+ io_signature::make(1, 2, sizeof(float)),
+ io_signature::make(0, 0, 0)),
+ d_sampling_freq(sampling_freq),
+ d_device_name(device_name.empty() ? default_device_name() : device_name),
+ d_fd(-1),
+ d_buffers(0),
+ d_chunk_size(0),
+ d_ok_to_block(ok_to_block)
+{
+ /* Initialize the WAVEFORMATEX for 16-bit, 44KHz, stereo */
+ wave_format.wFormatTag = WAVE_FORMAT_PCM;
+ wave_format.nChannels =
+ 2; // changing this will require adjustments to the work routine.
+ wave_format.wBitsPerSample =
+ 16; // changing this will necessitate changing buffer type from short.
+ wave_format.nSamplesPerSec =
+ d_sampling_freq; // 44100 is default but up to flowgraph settings;
+ wave_format.nBlockAlign = wave_format.nChannels * (wave_format.wBitsPerSample / 8);
+ wave_format.nAvgBytesPerSec = wave_format.nSamplesPerSec * wave_format.nBlockAlign;
+ wave_format.cbSize = 0;
- d_chunk_size = (int)(d_sampling_freq * CHUNK_TIME); // Samples per chunk
- set_output_multiple(d_chunk_size);
- d_buffer_size = d_chunk_size * wave_format.nChannels * (wave_format.wBitsPerSample / 8); // room for 16-bit audio on two channels.
+ d_chunk_size = (int)(d_sampling_freq * CHUNK_TIME); // Samples per chunk
+ set_output_multiple(d_chunk_size);
+ d_buffer_size =
+ d_chunk_size * wave_format.nChannels *
+ (wave_format.wBitsPerSample / 8); // room for 16-bit audio on two channels.
- d_wave_write_event = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (open_waveout_device() < 0) {
+ d_wave_write_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (open_waveout_device() < 0) {
perror("audio_windows_sink:open_waveout_device() failed\n");
- throw
- std::runtime_error("audio_windows_sink:open_waveout_device() failed");
- }
- else if (verbose) {
+ throw std::runtime_error("audio_windows_sink:open_waveout_device() failed");
+ } else if (verbose) {
GR_LOG_INFO(d_logger, "Opened windows waveout device");
- }
- d_buffers = new LPWAVEHDR[nPeriods];
- for (int i = 0; i < nPeriods; i++)
- {
+ }
+ d_buffers = new LPWAVEHDR[nPeriods];
+ for (int i = 0; i < nPeriods; i++) {
d_buffers[i] = new WAVEHDR;
d_buffers[i]->dwLoops = 0L;
d_buffers[i]->dwFlags = WHDR_DONE;
d_buffers[i]->dwBufferLength = d_buffer_size;
d_buffers[i]->lpData = new CHAR[d_buffer_size];
- }
- if (verbose) GR_LOG_INFO(d_logger, boost::format("Initialized %1% %2%ms audio buffers, total memory used: %3$0.2fkB") % (nPeriods) % (CHUNK_TIME * 1000) % ((d_buffer_size * nPeriods) / 1024.0));
}
+ if (verbose)
+ GR_LOG_INFO(
+ d_logger,
+ boost::format(
+ "Initialized %1% %2%ms audio buffers, total memory used: %3$0.2fkB") %
+ (nPeriods) % (CHUNK_TIME * 1000) % ((d_buffer_size * nPeriods) / 1024.0));
+}
- windows_sink::~windows_sink()
- {
- // stop playback and set all buffers to DONE.
- waveOutReset(d_h_waveout);
- // Now we can deallocate the buffers
- for (int i = 0; i < nPeriods; i++)
- {
+windows_sink::~windows_sink()
+{
+ // stop playback and set all buffers to DONE.
+ waveOutReset(d_h_waveout);
+ // Now we can deallocate the buffers
+ for (int i = 0; i < nPeriods; i++) {
if (d_buffers[i]->dwFlags & (WHDR_DONE | WHDR_PREPARED)) {
- waveOutUnprepareHeader(d_h_waveout, d_buffers[i], sizeof(d_buffers[i]));
- }
- else {
-
+ waveOutUnprepareHeader(d_h_waveout, d_buffers[i], sizeof(d_buffers[i]));
+ } else {
}
delete d_buffers[i]->lpData;
- }
- /* Free the callback Event */
- CloseHandle(d_wave_write_event);
- waveOutClose(d_h_waveout);
- delete [] d_buffers;
}
+ /* Free the callback Event */
+ CloseHandle(d_wave_write_event);
+ waveOutClose(d_h_waveout);
+ delete[] d_buffers;
+}
- int
- windows_sink::work(int noutput_items,
- gr_vector_const_void_star & input_items,
- gr_vector_void_star & output_items)
- {
- const float *f0, *f1;
+int windows_sink::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ const float *f0, *f1;
- int samples_sent = 0;
- int samples_tosend = 0;
- switch (input_items.size()) {
- case 1: // mono input
+ int samples_sent = 0;
+ int samples_tosend = 0;
+ switch (input_items.size()) {
+ case 1: // mono input
f0 = (const float*)input_items[0];
break;
- case 2: // stereo input
+ case 2: // stereo input
f0 = (const float*)input_items[0];
f1 = (const float*)input_items[1];
break;
- }
+ }
- while (samples_sent < noutput_items) {
+ while (samples_sent < noutput_items) {
// Pick the first available wave header (buffer)
- // If none available, then wait until the processing event if fired and check again
- // Not all events free up a buffer, so it could take more than one loop to get one
- // however, to avoid a lock, only wait 1 second for a freed up buffer then abort.
+ // If none available, then wait until the processing event if fired and check
+ // again Not all events free up a buffer, so it could take more than one loop to
+ // get one however, to avoid a lock, only wait 1 second for a freed up buffer then
+ // abort.
LPWAVEHDR chosen_header = NULL;
int c = 0;
- while (!chosen_header)
- {
- ResetEvent(d_wave_write_event);
- for (int i = 0; i < nPeriods; i++)
- {
- if (d_buffers[i]->dwFlags & WHDR_DONE) {
- // uncomment the below to see which buffers are being consumed
- // printf("%d ", i);
- chosen_header = d_buffers[i];
- break;
- }
- }
- if (!chosen_header) {
- if (!d_ok_to_block)
- {
- // drop the input data, print warning, and return control.
- printf("aO");
- return noutput_items;
+ while (!chosen_header) {
+ ResetEvent(d_wave_write_event);
+ for (int i = 0; i < nPeriods; i++) {
+ if (d_buffers[i]->dwFlags & WHDR_DONE) {
+ // uncomment the below to see which buffers are being consumed
+ // printf("%d ", i);
+ chosen_header = d_buffers[i];
+ break;
+ }
}
- else {
- WaitForSingleObject(d_wave_write_event, 100);
+ if (!chosen_header) {
+ if (!d_ok_to_block) {
+ // drop the input data, print warning, and return control.
+ printf("aO");
+ return noutput_items;
+ } else {
+ WaitForSingleObject(d_wave_write_event, 100);
+ }
}
- }
- if (c++ > 10) {
- // After waiting for 1 second, then something else is seriously wrong so let's
- // just fail and give some debugging information about the status
- // of the buffers.
- for (int i = 0; i < nPeriods; i++) {
- printf("%d: %d\n", i, d_buffers[i]->dwFlags);
+ if (c++ > 10) {
+ // After waiting for 1 second, then something else is seriously wrong so
+ // let's just fail and give some debugging information about the status of
+ // the buffers.
+ for (int i = 0; i < nPeriods; i++) {
+ printf("%d: %d\n", i, d_buffers[i]->dwFlags);
+ }
+ perror("audio_windows_sink: no audio buffers available");
+ return -1;
}
- perror("audio_windows_sink: no audio buffers available");
- return -1;
- }
}
- short *d_buffer = (short *)chosen_header->lpData;
- samples_tosend = noutput_items - samples_sent >= d_chunk_size ? d_chunk_size : noutput_items - samples_sent;
+ short* d_buffer = (short*)chosen_header->lpData;
+ samples_tosend = noutput_items - samples_sent >= d_chunk_size
+ ? d_chunk_size
+ : noutput_items - samples_sent;
switch (input_items.size()) {
- case 1: // mono input
- for (int j = 0; j < samples_tosend; j++) {
- d_buffer[2 * j + 0] = (short)(f0[j] * 32767);
- d_buffer[2 * j + 1] = (short)(f0[j] * 32767);
- }
- f0 += samples_tosend;
- break;
- case 2: // stereo input
- for (int j = 0; j < samples_tosend; j++) {
- d_buffer[2 * j + 0] = (short)(f0[j] * 32767);
- d_buffer[2 * j + 1] = (short)(f1[j] * 32767);
- }
- f0 += samples_tosend;
- f1 += samples_tosend;
- break;
+ case 1: // mono input
+ for (int j = 0; j < samples_tosend; j++) {
+ d_buffer[2 * j + 0] = (short)(f0[j] * 32767);
+ d_buffer[2 * j + 1] = (short)(f0[j] * 32767);
+ }
+ f0 += samples_tosend;
+ break;
+ case 2: // stereo input
+ for (int j = 0; j < samples_tosend; j++) {
+ d_buffer[2 * j + 0] = (short)(f0[j] * 32767);
+ d_buffer[2 * j + 1] = (short)(f1[j] * 32767);
+ }
+ f0 += samples_tosend;
+ f1 += samples_tosend;
+ break;
}
if (write_waveout(chosen_header) < 0) {
- perror("audio_windows_sink: write failed");
+ perror("audio_windows_sink: write failed");
}
samples_sent += samples_tosend;
- }
- return samples_sent;
}
+ return samples_sent;
+}
- int
- windows_sink::string_to_int(const std::string & s)
- {
- int i;
- std::istringstream(s) >> i;
- return i;
- }
+int windows_sink::string_to_int(const std::string& s)
+{
+ int i;
+ std::istringstream(s) >> i;
+ return i;
+}
- MMRESULT windows_sink::is_format_supported(LPWAVEFORMATEX pwfx, UINT uDeviceID)
- {
- return (waveOutOpen(
- NULL, // ptr can be NULL for query
- uDeviceID, // the device identifier
- pwfx, // defines requested format
- NULL, // no callback
- NULL, // no instance data
- WAVE_FORMAT_QUERY)); // query only, do not open device
- }
+MMRESULT windows_sink::is_format_supported(LPWAVEFORMATEX pwfx, UINT uDeviceID)
+{
+ return (waveOutOpen(NULL, // ptr can be NULL for query
+ uDeviceID, // the device identifier
+ pwfx, // defines requested format
+ NULL, // no callback
+ NULL, // no instance data
+ WAVE_FORMAT_QUERY)); // query only, do not open device
+}
- bool windows_sink::is_number(const std::string& s)
- {
- std::string::const_iterator it = s.begin();
- while (it != s.end() && std::isdigit(*it)) ++it;
- return !s.empty() && it == s.end();
- }
+bool windows_sink::is_number(const std::string& s)
+{
+ std::string::const_iterator it = s.begin();
+ while (it != s.end() && std::isdigit(*it))
+ ++it;
+ return !s.empty() && it == s.end();
+}
- UINT windows_sink::find_device(std::string szDeviceName)
- {
- UINT result = -1;
- UINT num_devices = waveOutGetNumDevs();
- if (num_devices > 0) {
+UINT windows_sink::find_device(std::string szDeviceName)
+{
+ UINT result = -1;
+ UINT num_devices = waveOutGetNumDevs();
+ if (num_devices > 0) {
// what the device name passed as a number?
- if (is_number(szDeviceName))
- {
- // a number, so must be referencing a device ID (which incremement from zero)
- UINT num = std::stoul(szDeviceName);
- if (num < num_devices) {
- result = num;
- }
- else {
- GR_LOG_INFO(d_logger, boost::format("Warning: waveOut deviceID %d was not found, defaulting to WAVE_MAPPER") % num);
- result = WAVE_MAPPER;
- }
+ if (is_number(szDeviceName)) {
+ // a number, so must be referencing a device ID (which incremement from zero)
+ UINT num = std::stoul(szDeviceName);
+ if (num < num_devices) {
+ result = num;
+ } else {
+ GR_LOG_INFO(d_logger,
+ boost::format("Warning: waveOut deviceID %d was not found, "
+ "defaulting to WAVE_MAPPER") %
+ num);
+ result = WAVE_MAPPER;
+ }
- }
- else {
- // device name passed as string
- for (UINT i = 0; i < num_devices; i++)
- {
- WAVEOUTCAPS woc;
- if (waveOutGetDevCaps(i, &woc, sizeof(woc)) != MMSYSERR_NOERROR)
- {
- perror("Error: Could not retrieve wave out device capabilities for device");
- return -1;
+ } else {
+ // device name passed as string
+ for (UINT i = 0; i < num_devices; i++) {
+ WAVEOUTCAPS woc;
+ if (waveOutGetDevCaps(i, &woc, sizeof(woc)) != MMSYSERR_NOERROR) {
+ perror("Error: Could not retrieve wave out device capabilities for "
+ "device");
+ return -1;
+ }
+ if (woc.szPname == szDeviceName) {
+ result = i;
+ }
+ if (verbose)
+ GR_LOG_INFO(d_logger,
+ boost::format("WaveOut Device %d: %s") % i % woc.szPname);
}
- if (woc.szPname == szDeviceName)
- {
- result = i;
+ if (result == -1) {
+ GR_LOG_INFO(d_logger,
+ boost::format("Warning: waveOut device '%s' was not found, "
+ "defaulting to WAVE_MAPPER") %
+ szDeviceName);
+ result = WAVE_MAPPER;
}
- if (verbose) GR_LOG_INFO(d_logger, boost::format("WaveOut Device %d: %s") % i % woc.szPname);
- }
- if (result == -1) {
- GR_LOG_INFO(d_logger, boost::format("Warning: waveOut device '%s' was not found, defaulting to WAVE_MAPPER") % szDeviceName);
- result = WAVE_MAPPER;
- }
}
- }
- else {
+ } else {
perror("Error: No WaveOut devices present or accessible");
- }
- return result;
}
+ return result;
+}
- int
- windows_sink::open_waveout_device(void)
- {
- UINT u_device_id;
- unsigned long result;
+int windows_sink::open_waveout_device(void)
+{
+ UINT u_device_id;
+ unsigned long result;
- /** Identifier of the waveform-audio output device to open. It
- can be either a device identifier or a handle of an open
- waveform-audio input device. You can use the following flag
- instead of a device identifier.
- WAVE_MAPPER The function selects a waveform-audio output
- device capable of playing the given format.
- */
- if (d_device_name.empty() || default_device_name() == d_device_name)
+ /** Identifier of the waveform-audio output device to open. It
+ can be either a device identifier or a handle of an open
+ waveform-audio input device. You can use the following flag
+ instead of a device identifier.
+ WAVE_MAPPER The function selects a waveform-audio output
+ device capable of playing the given format.
+ */
+ if (d_device_name.empty() || default_device_name() == d_device_name)
u_device_id = WAVE_MAPPER;
- else
+ else
// The below could be uncommented to allow selection of different device handles
// however it is unclear what other devices are out there and how a user
// would know the device ID so at the moment we will ignore that setting
// and stick with WAVE_MAPPER
u_device_id = find_device(d_device_name);
- if (verbose) GR_LOG_INFO(d_logger, boost::format("waveOut Device ID: %1%") % (u_device_id));
+ if (verbose)
+ GR_LOG_INFO(d_logger, boost::format("waveOut Device ID: %1%") % (u_device_id));
- // Check if the sampling rate/bits/channels are good to go with the device.
- MMRESULT supported = is_format_supported(&wave_format, u_device_id);
- if (supported != MMSYSERR_NOERROR) {
+ // Check if the sampling rate/bits/channels are good to go with the device.
+ MMRESULT supported = is_format_supported(&wave_format, u_device_id);
+ if (supported != MMSYSERR_NOERROR) {
char err_msg[50];
waveOutGetErrorText(supported, err_msg, 50);
GR_LOG_INFO(d_logger, boost::format("format error: %s") % err_msg);
- perror("audio_windows_sink: Requested audio format is not supported by device driver");
+ perror("audio_windows_sink: Requested audio format is not supported by device "
+ "driver");
return -1;
- }
+ }
- // Open a waveform device for output using event callback.
- result = waveOutOpen(&d_h_waveout, u_device_id,
- &wave_format,
- (DWORD_PTR)d_wave_write_event,
- 0, CALLBACK_EVENT | WAVE_ALLOWSYNC);
+ // Open a waveform device for output using event callback.
+ result = waveOutOpen(&d_h_waveout,
+ u_device_id,
+ &wave_format,
+ (DWORD_PTR)d_wave_write_event,
+ 0,
+ CALLBACK_EVENT | WAVE_ALLOWSYNC);
- if (result) {
+ if (result) {
perror("audio_windows_sink: Failed to open waveform output device.");
return -1;
- }
- return 0;
}
+ return 0;
+}
- int
- windows_sink::write_waveout(LPWAVEHDR lp_wave_hdr)
- {
- UINT w_result;
+int windows_sink::write_waveout(LPWAVEHDR lp_wave_hdr)
+{
+ UINT w_result;
- /* Clear the WHDR_DONE bit (which the driver set last time that
- this WAVEHDR was sent via waveOutWrite and was played). Some
- drivers need this to be cleared */
- lp_wave_hdr->dwFlags = 0L;
+ /* Clear the WHDR_DONE bit (which the driver set last time that
+ this WAVEHDR was sent via waveOutWrite and was played). Some
+ drivers need this to be cleared */
+ lp_wave_hdr->dwFlags = 0L;
- w_result =
- waveOutPrepareHeader(d_h_waveout, lp_wave_hdr, sizeof(WAVEHDR));
- if (w_result != 0) {
+ w_result = waveOutPrepareHeader(d_h_waveout, lp_wave_hdr, sizeof(WAVEHDR));
+ if (w_result != 0) {
perror("audio_windows_sink: Failed to waveOutPrepareHeader");
return -1;
- }
+ }
- w_result = waveOutWrite(d_h_waveout, lp_wave_hdr, sizeof(WAVEHDR));
- if (w_result != 0) {
+ w_result = waveOutWrite(d_h_waveout, lp_wave_hdr, sizeof(WAVEHDR));
+ if (w_result != 0) {
perror("audio_windows_sink: Failed to write block to device");
switch (w_result) {
case MMSYSERR_INVALHANDLE:
- fprintf(stderr, "Specified device handle is invalid.\n");
- break;
+ fprintf(stderr, "Specified device handle is invalid.\n");
+ break;
case MMSYSERR_NODRIVER:
- fprintf(stderr, " No device driver is present.\n");
- break;
+ fprintf(stderr, " No device driver is present.\n");
+ break;
case MMSYSERR_NOMEM:
- fprintf(stderr, " Unable to allocate or lock memory.\n");
- break;
+ fprintf(stderr, " Unable to allocate or lock memory.\n");
+ break;
case WAVERR_UNPREPARED:
- fprintf(stderr,
- " The data block pointed to by the pwh parameter hasn't been prepared.\n");
- break;
+ fprintf(stderr,
+ " The data block pointed to by the pwh parameter hasn't been "
+ "prepared.\n");
+ break;
default:
- fprintf(stderr, "Unknown error %i\n", w_result);
+ fprintf(stderr, "Unknown error %i\n", w_result);
}
waveOutUnprepareHeader(d_h_waveout, lp_wave_hdr, sizeof(WAVEHDR));
return -1;
- }
- return 0;
}
- } /* namespace audio */
+ return 0;
+}
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/windows/windows_sink.h b/gr-audio/lib/windows/windows_sink.h
index de905c68fd..fcfae94dcb 100644
--- a/gr-audio/lib/windows/windows_sink.h
+++ b/gr-audio/lib/windows/windows_sink.h
@@ -24,7 +24,7 @@
#define INCLUDED_AUDIO_WINDOWS_SINK_H
#define WIN32_LEAN_AND_MEAN
-#define NOMINMAX // stops windef.h defining max/min under cygwin
+#define NOMINMAX // stops windef.h defining max/min under cygwin
#include <windows.h>
#include <mmsystem.h>
@@ -33,48 +33,46 @@
#include <string>
namespace gr {
- namespace audio {
+namespace audio {
- /*!
- * \brief audio sink using winmm mmsystem (win32 only)
- * \ingroup audio_blk
- *
- * input signature is one or two streams of floats.
- * Input samples must be in the range [-1,1].
- */
- class windows_sink : public sink
- {
- int d_sampling_freq;
- std::string d_device_name;
- int d_fd;
- LPWAVEHDR *d_buffers;
- DWORD d_chunk_size;
- DWORD d_buffer_size;
- bool d_ok_to_block;
- HWAVEOUT d_h_waveout;
- HANDLE d_wave_write_event;
- WAVEFORMATEX wave_format;
+/*!
+ * \brief audio sink using winmm mmsystem (win32 only)
+ * \ingroup audio_blk
+ *
+ * input signature is one or two streams of floats.
+ * Input samples must be in the range [-1,1].
+ */
+class windows_sink : public sink
+{
+ int d_sampling_freq;
+ std::string d_device_name;
+ int d_fd;
+ LPWAVEHDR* d_buffers;
+ DWORD d_chunk_size;
+ DWORD d_buffer_size;
+ bool d_ok_to_block;
+ HWAVEOUT d_h_waveout;
+ HANDLE d_wave_write_event;
+ WAVEFORMATEX wave_format;
- protected:
- int string_to_int(const std::string & s);
- int open_waveout_device(void);
- int write_waveout(LPWAVEHDR lp_wave_hdr);
- MMRESULT is_format_supported(LPWAVEFORMATEX pwfx, UINT uDeviceID);
- bool is_number(const std::string& s);
- UINT find_device(std::string szDeviceName);
+protected:
+ int string_to_int(const std::string& s);
+ int open_waveout_device(void);
+ int write_waveout(LPWAVEHDR lp_wave_hdr);
+ MMRESULT is_format_supported(LPWAVEFORMATEX pwfx, UINT uDeviceID);
+ bool is_number(const std::string& s);
+ UINT find_device(std::string szDeviceName);
- public:
- windows_sink(int sampling_freq,
- const std::string device_name,
- bool ok_to_block);
- ~windows_sink();
+public:
+ windows_sink(int sampling_freq, const std::string device_name, bool ok_to_block);
+ ~windows_sink();
- int work(int noutput_items,
- gr_vector_const_void_star & input_items,
- gr_vector_void_star & output_items);
- };
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_AUDIO_WINDOWS_SINK_H */
diff --git a/gr-audio/lib/windows/windows_source.cc b/gr-audio/lib/windows/windows_source.cc
index b5550a59c2..5389a2383b 100644
--- a/gr-audio/lib/windows/windows_source.cc
+++ b/gr-audio/lib/windows/windows_source.cc
@@ -40,297 +40,305 @@
namespace gr {
- namespace audio {
+namespace audio {
- // Currently this audio source will only support a single channel input at 16-bits. So a stereo input will likely be turned into a mono by the wave mapper
+// Currently this audio source will only support a single channel input at 16-bits. So a
+// stereo input will likely be turned into a mono by the wave mapper
- source::sptr
- windows_source_fcn(int sampling_rate,
- const std::string &device_name,
- bool)
- {
- return source::sptr
- (new windows_source(sampling_rate, device_name));
- }
+source::sptr windows_source_fcn(int sampling_rate, const std::string& device_name, bool)
+{
+ return source::sptr(new windows_source(sampling_rate, device_name));
+}
- static const double CHUNK_TIME = prefs::singleton()->get_double("audio_windows", "period_time", 0.1); // 100 ms (below 3ms distortion will likely occur regardless of number of buffers, will likely be a higher limit on slower machines)
- static const int nPeriods = prefs::singleton()->get_long("audio_windows", "nperiods", 4); // 4 should be more than enough with a normal chunk time (2 will likely work as well)... at 3ms chunks 10 was enough on a fast machine
- static const bool verbose = prefs::singleton()->get_bool("audio_windows", "verbose", false);
- static const std::string default_device = prefs::singleton()->get_string("audio_windows", "standard_input_device", "default");
+static const double CHUNK_TIME = prefs::singleton()->get_double(
+ "audio_windows",
+ "period_time",
+ 0.1); // 100 ms (below 3ms distortion will likely occur regardless of number of
+ // buffers, will likely be a higher limit on slower machines)
+static const int nPeriods = prefs::singleton()->get_long(
+ "audio_windows",
+ "nperiods",
+ 4); // 4 should be more than enough with a normal chunk time (2 will likely work as
+ // well)... at 3ms chunks 10 was enough on a fast machine
+static const bool verbose =
+ prefs::singleton()->get_bool("audio_windows", "verbose", false);
+static const std::string default_device =
+ prefs::singleton()->get_string("audio_windows", "standard_input_device", "default");
- static std::string
- default_device_name()
- {
- return (default_device == "default" ? "WAVE_MAPPER" : default_device);
- }
+static std::string default_device_name()
+{
+ return (default_device == "default" ? "WAVE_MAPPER" : default_device);
+}
- windows_source::windows_source(int sampling_freq,
- const std::string device_name)
- : sync_block("audio_windows_source",
- io_signature::make(0, 0, 0),
- io_signature::make(1, 1, sizeof(float))),
- d_sampling_freq(sampling_freq),
- d_device_name(device_name.empty() ? default_device_name() : device_name),
- d_fd(-1), lp_buffers(0), d_chunk_size(0)
- {
- /* Initialize the WAVEFORMATEX for 16-bit, mono */
- wave_format.wFormatTag = WAVE_FORMAT_PCM;
- wave_format.nChannels = 1; // changing this will require adjustments to the work routine.
- wave_format.wBitsPerSample = 16; // changing this will necessitate changing buffer type from short.
- wave_format.nSamplesPerSec = d_sampling_freq; // defined by flowgraph settings, but note that the microphone will likely have a native sample rate
- // that the audio system may upsample to you desired rate, so check where the cutoff ends up or check your control panel
- wave_format.nBlockAlign =
- wave_format.nChannels * (wave_format.wBitsPerSample / 8);
- wave_format.nAvgBytesPerSec =
- wave_format.nSamplesPerSec * wave_format.nBlockAlign;
- wave_format.cbSize = 0;
+windows_source::windows_source(int sampling_freq, const std::string device_name)
+ : sync_block("audio_windows_source",
+ io_signature::make(0, 0, 0),
+ io_signature::make(1, 1, sizeof(float))),
+ d_sampling_freq(sampling_freq),
+ d_device_name(device_name.empty() ? default_device_name() : device_name),
+ d_fd(-1),
+ lp_buffers(0),
+ d_chunk_size(0)
+{
+ /* Initialize the WAVEFORMATEX for 16-bit, mono */
+ wave_format.wFormatTag = WAVE_FORMAT_PCM;
+ wave_format.nChannels =
+ 1; // changing this will require adjustments to the work routine.
+ wave_format.wBitsPerSample =
+ 16; // changing this will necessitate changing buffer type from short.
+ wave_format.nSamplesPerSec =
+ d_sampling_freq; // defined by flowgraph settings, but note that the microphone
+ // will likely have a native sample rate that the audio system
+ // may upsample to you desired rate, so check where the cutoff
+ // ends up or check your control panel
+ wave_format.nBlockAlign = wave_format.nChannels * (wave_format.wBitsPerSample / 8);
+ wave_format.nAvgBytesPerSec = wave_format.nSamplesPerSec * wave_format.nBlockAlign;
+ wave_format.cbSize = 0;
- d_chunk_size = (int)(d_sampling_freq * CHUNK_TIME); // Samples per chunk
- set_output_multiple(d_chunk_size);
- d_buffer_size = d_chunk_size * wave_format.nChannels * (wave_format.wBitsPerSample / 8); // room for 16-bit audio on one channel.
+ d_chunk_size = (int)(d_sampling_freq * CHUNK_TIME); // Samples per chunk
+ set_output_multiple(d_chunk_size);
+ d_buffer_size =
+ d_chunk_size * wave_format.nChannels *
+ (wave_format.wBitsPerSample / 8); // room for 16-bit audio on one channel.
- if (open_wavein_device() < 0) {
- perror("audio_windows_source:open_wavein_device() failed\n");
- throw
- std::runtime_error("audio_windows_source:open_wavein_device() failed");
- }
- else if (verbose) {
- GR_LOG_INFO(d_logger, "Opened windows wavein device");
- }
- lp_buffers = new LPWAVEHDR[nPeriods];
- for (int i = 0; i < nPeriods; i++)
- {
- lp_buffers[i] = new WAVEHDR;
- LPWAVEHDR lp_buffer = lp_buffers[i];
- lp_buffer->dwLoops = 0L;
- lp_buffer->dwFlags = 0;
- lp_buffer->dwBufferLength = d_buffer_size;
- lp_buffer->lpData = new CHAR[d_buffer_size];
- MMRESULT w_result =
- waveInPrepareHeader(d_h_wavein, lp_buffer, sizeof(WAVEHDR));
- if (w_result != 0) {
- perror("audio_windows_source: Failed to waveInPrepareHeader");
- throw
- std::runtime_error("audio_windows_source:open_wavein_device() failed");
- }
- waveInAddBuffer(d_h_wavein, lp_buffer, sizeof(WAVEHDR));
- }
- waveInStart(d_h_wavein);
- if (verbose) GR_LOG_INFO(d_logger, boost::format("Initialized %1% %2%ms audio buffers, total memory used: %3$0.2fkB") % (nPeriods) % (CHUNK_TIME * 1000) % ((d_buffer_size * nPeriods) / 1024.0));
- }
+ if (open_wavein_device() < 0) {
+ perror("audio_windows_source:open_wavein_device() failed\n");
+ throw std::runtime_error("audio_windows_source:open_wavein_device() failed");
+ } else if (verbose) {
+ GR_LOG_INFO(d_logger, "Opened windows wavein device");
+ }
+ lp_buffers = new LPWAVEHDR[nPeriods];
+ for (int i = 0; i < nPeriods; i++) {
+ lp_buffers[i] = new WAVEHDR;
+ LPWAVEHDR lp_buffer = lp_buffers[i];
+ lp_buffer->dwLoops = 0L;
+ lp_buffer->dwFlags = 0;
+ lp_buffer->dwBufferLength = d_buffer_size;
+ lp_buffer->lpData = new CHAR[d_buffer_size];
+ MMRESULT w_result = waveInPrepareHeader(d_h_wavein, lp_buffer, sizeof(WAVEHDR));
+ if (w_result != 0) {
+ perror("audio_windows_source: Failed to waveInPrepareHeader");
+ throw std::runtime_error("audio_windows_source:open_wavein_device() failed");
+ }
+ waveInAddBuffer(d_h_wavein, lp_buffer, sizeof(WAVEHDR));
+ }
+ waveInStart(d_h_wavein);
+ if (verbose)
+ GR_LOG_INFO(
+ d_logger,
+ boost::format(
+ "Initialized %1% %2%ms audio buffers, total memory used: %3$0.2fkB") %
+ (nPeriods) % (CHUNK_TIME * 1000) % ((d_buffer_size * nPeriods) / 1024.0));
+}
- windows_source::~windows_source()
- {
- // stop playback and set all buffers to DONE.
- waveInReset(d_h_wavein);
- // Now we can deallocate the buffers
- for (int i = 0; i < nPeriods; i++)
- {
- if (lp_buffers[i]->dwFlags & (WHDR_DONE | WHDR_PREPARED)) {
- waveInUnprepareHeader(d_h_wavein, lp_buffers[i], sizeof(WAVEHDR));
- }
- else {
+windows_source::~windows_source()
+{
+ // stop playback and set all buffers to DONE.
+ waveInReset(d_h_wavein);
+ // Now we can deallocate the buffers
+ for (int i = 0; i < nPeriods; i++) {
+ if (lp_buffers[i]->dwFlags & (WHDR_DONE | WHDR_PREPARED)) {
+ waveInUnprepareHeader(d_h_wavein, lp_buffers[i], sizeof(WAVEHDR));
+ } else {
+ }
+ delete lp_buffers[i]->lpData;
+ }
+ /* Free the callback Event */
+ waveInClose(d_h_wavein);
+ delete[] lp_buffers;
+}
- }
- delete lp_buffers[i]->lpData;
- }
- /* Free the callback Event */
- waveInClose(d_h_wavein);
- delete[] lp_buffers;
- }
+int windows_source::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ float *f0, *f1;
+ DWORD dw_items = 0;
- int
- windows_source::work(int noutput_items,
- gr_vector_const_void_star & input_items,
- gr_vector_void_star & output_items)
- {
- float *f0, *f1;
- DWORD dw_items = 0;
+ while (!buffer_queue.empty()) {
+ // Pull the next incoming buffer off the queue
+ LPWAVEHDR next_header = buffer_queue.front();
- while (!buffer_queue.empty())
- {
- // Pull the next incoming buffer off the queue
- LPWAVEHDR next_header = buffer_queue.front();
+ // Convert and calculate the number of samples (might not be full)
+ short* lp_buffer = (short*)next_header->lpData;
+ DWORD buffer_length = next_header->dwBytesRecorded / sizeof(short);
- // Convert and calculate the number of samples (might not be full)
- short *lp_buffer = (short *)next_header->lpData;
- DWORD buffer_length = next_header->dwBytesRecorded / sizeof(short);
+ if (buffer_length + dw_items > noutput_items * output_items.size()) {
+ // There's not enough output buffer space to send the whole input buffer
+ // so don't try, just leave it in the queue
+ // or else we'd have to track how much we sent etc
+ // In theory we should never reach this code because the buffers should all be
+ // sized the same
+ return dw_items;
+ } else {
+ switch (output_items.size()) {
+ case 1: // mono output
+ f0 = (float*)output_items[0];
- if (buffer_length + dw_items > noutput_items * output_items.size()) {
- // There's not enough output buffer space to send the whole input buffer
- // so don't try, just leave it in the queue
- // or else we'd have to track how much we sent etc
- // In theory we should never reach this code because the buffers should all be
- // sized the same
- return dw_items;
- }
- else {
- switch (output_items.size()) {
- case 1: // mono output
- f0 = (float*)output_items[0];
+ for (int j = 0; j < buffer_length; j++) {
+ f0[dw_items + j] = (float)(lp_buffer[j]) / 32767.0;
+ }
+ dw_items += buffer_length;
+ break;
+ case 2: // stereo output (interleaved in the buffer)
+ f0 = (float*)output_items[0];
+ f1 = (float*)output_items[1];
- for (int j = 0; j < buffer_length; j++) {
- f0[dw_items + j] = (float)(lp_buffer[j]) / 32767.0;
- }
- dw_items += buffer_length;
- break;
- case 2: // stereo output (interleaved in the buffer)
- f0 = (float*)output_items[0];
- f1 = (float*)output_items[1];
+ for (int j = 0; j < buffer_length / 2; j++) {
+ f0[dw_items + j] = (float)(lp_buffer[2 * j + 0]) / 32767.0;
+ f1[dw_items + j] = (float)(lp_buffer[2 * j + 1]) / 32767.0;
+ }
+ dw_items += buffer_length / 2;
+ }
+ buffer_queue.pop();
- for (int j = 0; j < buffer_length / 2; j++) {
- f0[dw_items + j] = (float)(lp_buffer[2 * j + 0]) / 32767.0;
- f1[dw_items + j] = (float)(lp_buffer[2 * j + 1]) / 32767.0;
- }
- dw_items += buffer_length / 2;
- }
- buffer_queue.pop();
+ // Recycle the buffer
+ next_header->dwFlags = 0;
+ waveInPrepareHeader(d_h_wavein, next_header, sizeof(WAVEHDR));
+ waveInAddBuffer(d_h_wavein, next_header, sizeof(WAVEHDR));
+ }
+ }
+ return dw_items;
+}
- // Recycle the buffer
- next_header->dwFlags = 0;
- waveInPrepareHeader(d_h_wavein, next_header, sizeof(WAVEHDR));
- waveInAddBuffer(d_h_wavein, next_header, sizeof(WAVEHDR));
- }
- }
- return dw_items;
- }
+int windows_source::string_to_int(const std::string& s)
+{
+ int i;
+ std::istringstream(s) >> i;
+ return i;
+}
- int
- windows_source::string_to_int(const std::string & s)
- {
- int i;
- std::istringstream(s) >> i;
- return i;
- }
+MMRESULT windows_source::is_format_supported(LPWAVEFORMATEX pwfx, UINT uDeviceID)
+{
+ return (waveInOpen(NULL, // ptr can be NULL for query
+ uDeviceID, // the device identifier
+ pwfx, // defines requested format
+ NULL, // no callback
+ NULL, // no instance data
+ WAVE_FORMAT_QUERY)); // query only, do not open device
+}
- MMRESULT windows_source::is_format_supported(LPWAVEFORMATEX pwfx, UINT uDeviceID)
- {
- return (waveInOpen(
- NULL, // ptr can be NULL for query
- uDeviceID, // the device identifier
- pwfx, // defines requested format
- NULL, // no callback
- NULL, // no instance data
- WAVE_FORMAT_QUERY)); // query only, do not open device
- }
+bool windows_source::is_number(const std::string& s)
+{
+ std::string::const_iterator it = s.begin();
+ while (it != s.end() && std::isdigit(*it))
+ ++it;
+ return !s.empty() && it == s.end();
+}
- bool windows_source::is_number(const std::string& s)
- {
- std::string::const_iterator it = s.begin();
- while (it != s.end() && std::isdigit(*it)) ++it;
- return !s.empty() && it == s.end();
- }
+UINT windows_source::find_device(std::string szDeviceName)
+{
+ UINT result = -1;
+ UINT num_devices = waveInGetNumDevs();
+ if (num_devices > 0) {
+ // what the device name passed as a number?
+ if (is_number(szDeviceName)) {
+ // a number, so must be referencing a device ID (which incremement from zero)
+ UINT num = std::stoul(szDeviceName);
+ if (num < num_devices) {
+ result = num;
+ } else {
+ GR_LOG_INFO(d_logger,
+ boost::format("Warning: waveIn deviceID %d was not found, "
+ "defaulting to WAVE_MAPPER") %
+ num);
+ result = WAVE_MAPPER;
+ }
- UINT windows_source::find_device(std::string szDeviceName)
- {
- UINT result = -1;
- UINT num_devices = waveInGetNumDevs();
- if (num_devices > 0) {
- // what the device name passed as a number?
- if (is_number(szDeviceName))
- {
- // a number, so must be referencing a device ID (which incremement from zero)
- UINT num = std::stoul(szDeviceName);
- if (num < num_devices) {
- result = num;
- }
- else {
- GR_LOG_INFO(d_logger, boost::format("Warning: waveIn deviceID %d was not found, defaulting to WAVE_MAPPER") % num);
- result = WAVE_MAPPER;
- }
+ } else {
+ // device name passed as string
+ for (UINT i = 0; i < num_devices; i++) {
+ WAVEINCAPS woc;
+ if (waveInGetDevCaps(i, &woc, sizeof(woc)) != MMSYSERR_NOERROR) {
+ perror("Error: Could not retrieve wave out device capabilities for "
+ "device");
+ return -1;
+ }
+ if (woc.szPname == szDeviceName) {
+ result = i;
+ }
+ if (verbose)
+ GR_LOG_INFO(d_logger,
+ boost::format("WaveIn Device %d: %s") % i % woc.szPname);
+ }
+ if (result == -1) {
+ GR_LOG_INFO(d_logger,
+ boost::format("Warning: waveIn device '%s' was not found, "
+ "defaulting to WAVE_MAPPER") %
+ szDeviceName);
+ result = WAVE_MAPPER;
+ }
+ }
+ } else {
+ perror("Error: No WaveIn devices present or accessible");
+ }
+ return result;
+}
- }
- else {
- // device name passed as string
- for (UINT i = 0; i < num_devices; i++)
- {
- WAVEINCAPS woc;
- if (waveInGetDevCaps(i, &woc, sizeof(woc)) != MMSYSERR_NOERROR)
- {
- perror("Error: Could not retrieve wave out device capabilities for device");
- return -1;
- }
- if (woc.szPname == szDeviceName)
- {
- result = i;
- }
- if (verbose) GR_LOG_INFO(d_logger, boost::format("WaveIn Device %d: %s") % i % woc.szPname);
- }
- if (result == -1) {
- GR_LOG_INFO(d_logger, boost::format("Warning: waveIn device '%s' was not found, defaulting to WAVE_MAPPER") % szDeviceName);
- result = WAVE_MAPPER;
- }
- }
- }
- else {
- perror("Error: No WaveIn devices present or accessible");
- }
- return result;
- }
+int windows_source::open_wavein_device(void)
+{
+ UINT u_device_id;
+ unsigned long result;
- int
- windows_source::open_wavein_device(void)
- {
- UINT u_device_id;
- unsigned long result;
+ /** Identifier of the waveform-audio output device to open. It
+ can be either a device identifier or a handle of an open
+ waveform-audio input device. You can use the following flag
+ instead of a device identifier.
+ WAVE_MAPPER The function selects a waveform-audio output
+ device capable of playing the given format.
+ */
+ if (d_device_name.empty() || default_device_name() == d_device_name)
+ u_device_id = WAVE_MAPPER;
+ else
+ // The below could be uncommented to allow selection of different device handles
+ // however it is unclear what other devices are out there and how a user
+ // would know the device ID so at the moment we will ignore that setting
+ // and stick with WAVE_MAPPER
+ u_device_id = find_device(d_device_name);
+ if (verbose)
+ GR_LOG_INFO(d_logger, boost::format("waveIn Device ID: %1%") % (u_device_id));
- /** Identifier of the waveform-audio output device to open. It
- can be either a device identifier or a handle of an open
- waveform-audio input device. You can use the following flag
- instead of a device identifier.
- WAVE_MAPPER The function selects a waveform-audio output
- device capable of playing the given format.
- */
- if (d_device_name.empty() || default_device_name() == d_device_name)
- u_device_id = WAVE_MAPPER;
- else
- // The below could be uncommented to allow selection of different device handles
- // however it is unclear what other devices are out there and how a user
- // would know the device ID so at the moment we will ignore that setting
- // and stick with WAVE_MAPPER
- u_device_id = find_device(d_device_name);
- if (verbose) GR_LOG_INFO(d_logger, boost::format("waveIn Device ID: %1%") % (u_device_id));
+ // Check if the sampling rate/bits/channels are good to go with the device.
+ MMRESULT supported = is_format_supported(&wave_format, u_device_id);
+ if (supported != MMSYSERR_NOERROR) {
+ char err_msg[50];
+ waveInGetErrorText(supported, err_msg, 50);
+ GR_LOG_INFO(d_logger, boost::format("format error: %s") % err_msg);
+ perror("audio_windows_source: Requested audio format is not supported by device "
+ "driver");
+ return -1;
+ }
- // Check if the sampling rate/bits/channels are good to go with the device.
- MMRESULT supported = is_format_supported(&wave_format, u_device_id);
- if (supported != MMSYSERR_NOERROR) {
- char err_msg[50];
- waveInGetErrorText(supported, err_msg, 50);
- GR_LOG_INFO(d_logger, boost::format("format error: %s") % err_msg);
- perror("audio_windows_source: Requested audio format is not supported by device driver");
- return -1;
- }
+ // Open a waveform device for output using event callback.
+ result = waveInOpen(&d_h_wavein,
+ u_device_id,
+ &wave_format,
+ (DWORD_PTR)&read_wavein,
+ (DWORD_PTR)&buffer_queue,
+ CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
- // Open a waveform device for output using event callback.
- result = waveInOpen(&d_h_wavein, u_device_id,
- &wave_format,
- (DWORD_PTR)&read_wavein,
- (DWORD_PTR)&buffer_queue, CALLBACK_FUNCTION | WAVE_ALLOWSYNC);
+ if (result) {
+ perror("audio_windows_source: Failed to open waveform output device.");
+ return -1;
+ }
+ return 0;
+}
- if (result) {
- perror("audio_windows_source: Failed to open waveform output device.");
- return -1;
- }
- return 0;
- }
-
- static void CALLBACK read_wavein(
- HWAVEIN hwi,
- UINT uMsg,
- DWORD_PTR dwInstance,
- DWORD_PTR dwParam1,
- DWORD_PTR dwParam2
- )
- {
- // Ignore WIM_OPEN and WIM_CLOSE messages
- if (uMsg == WIM_DATA) {
- if (!dwInstance) {
- perror("audio_windows_source: callback function missing buffer queue");
- }
- LPWAVEHDR lp_wave_hdr = (LPWAVEHDR)dwParam1; // The new audio data
- boost::lockfree::spsc_queue<LPWAVEHDR> *q = (boost::lockfree::spsc_queue<LPWAVEHDR> *)dwInstance; // The buffer queue we assigned to the device to track the buffers that need to be sent
- q->push(lp_wave_hdr); // Add the buffer to that queue
- }
- }
- } /* namespace audio */
+static void CALLBACK read_wavein(
+ HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
+{
+ // Ignore WIM_OPEN and WIM_CLOSE messages
+ if (uMsg == WIM_DATA) {
+ if (!dwInstance) {
+ perror("audio_windows_source: callback function missing buffer queue");
+ }
+ LPWAVEHDR lp_wave_hdr = (LPWAVEHDR)dwParam1; // The new audio data
+ boost::lockfree::spsc_queue<LPWAVEHDR>* q =
+ (boost::lockfree::spsc_queue<LPWAVEHDR>*)
+ dwInstance; // The buffer queue we assigned to the device to track the
+ // buffers that need to be sent
+ q->push(lp_wave_hdr); // Add the buffer to that queue
+ }
+}
+} /* namespace audio */
} /* namespace gr */
diff --git a/gr-audio/lib/windows/windows_source.h b/gr-audio/lib/windows/windows_source.h
index edb89a73ce..cf858647aa 100644
--- a/gr-audio/lib/windows/windows_source.h
+++ b/gr-audio/lib/windows/windows_source.h
@@ -24,7 +24,7 @@
#define INCLUDED_AUDIO_WINDOWS_SOURCE_H
#define WIN32_LEAN_AND_MEAN
-#define NOMINMAX // stops windef.h defining max/min under cygwin
+#define NOMINMAX // stops windef.h defining max/min under cygwin
#include <windows.h>
#include <mmsystem.h>
@@ -35,53 +35,47 @@
#include <boost/lockfree/spsc_queue.hpp>
namespace gr {
- namespace audio {
+namespace audio {
- /*!
- * \brief audio source using winmm mmsystem (win32 only)
- * \ingroup audio_blk
- *
- * Output signature is one or two streams of floats.
- * Output samples will be in the range [-1,1].
- */
- class windows_source : public source
- {
- int d_sampling_freq;
- std::string d_device_name;
- int d_fd;
- LPWAVEHDR *lp_buffers;
- DWORD d_chunk_size;
- DWORD d_buffer_size;
- HWAVEIN d_h_wavein;
- WAVEFORMATEX wave_format;
+/*!
+ * \brief audio source using winmm mmsystem (win32 only)
+ * \ingroup audio_blk
+ *
+ * Output signature is one or two streams of floats.
+ * Output samples will be in the range [-1,1].
+ */
+class windows_source : public source
+{
+ int d_sampling_freq;
+ std::string d_device_name;
+ int d_fd;
+ LPWAVEHDR* lp_buffers;
+ DWORD d_chunk_size;
+ DWORD d_buffer_size;
+ HWAVEIN d_h_wavein;
+ WAVEFORMATEX wave_format;
- protected:
- int string_to_int(const std::string & s);
- int open_wavein_device(void);
- MMRESULT is_format_supported(LPWAVEFORMATEX pwfx, UINT uDeviceID);
- bool is_number(const std::string& s);
- UINT find_device(std::string szDeviceName);
- boost::lockfree::spsc_queue<LPWAVEHDR> buffer_queue{ 100 };
+protected:
+ int string_to_int(const std::string& s);
+ int open_wavein_device(void);
+ MMRESULT is_format_supported(LPWAVEFORMATEX pwfx, UINT uDeviceID);
+ bool is_number(const std::string& s);
+ UINT find_device(std::string szDeviceName);
+ boost::lockfree::spsc_queue<LPWAVEHDR> buffer_queue{ 100 };
- public:
- windows_source(int sampling_freq,
- const std::string device_name = "");
- ~windows_source();
+public:
+ windows_source(int sampling_freq, const std::string device_name = "");
+ ~windows_source();
- int work(int noutput_items,
- gr_vector_const_void_star & input_items,
- gr_vector_void_star & output_items);
- };
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items);
+};
- static void CALLBACK read_wavein(
- HWAVEIN hwi,
- UINT uMsg,
- DWORD_PTR dwInstance,
- DWORD_PTR dwParam1,
- DWORD_PTR dwParam2
- );
+static void CALLBACK read_wavein(
+ HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
- } /* namespace audio */
+} /* namespace audio */
} /* namespace gr */
#endif /* INCLUDED_AUDIO_WINDOWS_SOURCE_H */