From da7daddf453601a86c9b94c8c31da1fe4c76e89b Mon Sep 17 00:00:00 2001 From: Bruno Morais Date: Thu, 6 Jun 2019 16:54:11 +0200 Subject: Allow writing audio to a named pipe (fifo) instead of live device Fixes #684 --- contrib/config-example | 1 + contrib/pianobar.1 | 6 ++++++ src/player.c | 30 ++++++++++++++++++++++++++---- src/settings.c | 5 +++++ src/settings.h | 1 + 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/contrib/config-example b/contrib/config-example index 275659f..d6186c4 100644 --- a/contrib/config-example +++ b/contrib/config-example @@ -50,6 +50,7 @@ #ca_bundle = /etc/ssl/certs/ca-certificates.crt #gain_mul = 1.0 #sample_rate = 44100 +#audio_pipe = /tmp/mypipe # Format strings #format_nowplaying_song = %t by %a on %l%r%@%s diff --git a/contrib/pianobar.1 b/contrib/pianobar.1 index 196bbb2..0cdf6c8 100644 --- a/contrib/pianobar.1 +++ b/contrib/pianobar.1 @@ -179,6 +179,12 @@ Replacement for %@ in station format string. It's " @ " by default. .B audio_quality = {high, medium, low} Select audio quality. +.TP +.B audio_pipe = /path/to/fifo +Stream decoded, raw audio samples to a pipe instead of the default audio device. Use +.B sample_rate +to enforce a fixed sample rate. + .TP .B autoselect = {1,0} Auto-select last remaining item of filtered list. Currently enabled for station diff --git a/src/player.c b/src/player.c index 848d58b..d73b718 100644 --- a/src/player.c +++ b/src/player.c @@ -38,9 +38,11 @@ THE SOFTWARE. #include #include #include +#include #include #include #include +#include #include #include @@ -340,10 +342,30 @@ static bool openDevice (player_t * const player) { aoFmt.rate = getSampleRate (player); aoFmt.byte_format = AO_FMT_NATIVE; - int driver = ao_default_driver_id (); - if ((player->aoDev = ao_open_live (driver, &aoFmt, NULL)) == NULL) { - BarUiMsg (player->settings, MSG_ERR, "Cannot open audio device.\n"); - return false; + int driver = -1; + if (player->settings->audioPipe) { + // using audio pipe + struct stat st; + if (stat (player->settings->audioPipe, &st)) { + BarUiMsg (player->settings, MSG_ERR, "Cannot stat audio pipe file.\n"); + return false; + } + if (!S_ISFIFO (st.st_mode)) { + BarUiMsg (player->settings, MSG_ERR, "File is not a pipe, error.\n"); + return false; + } + driver = ao_driver_id ("raw"); + if ((player->aoDev = ao_open_file(driver, player->settings->audioPipe, 1, &aoFmt, NULL)) == NULL) { + BarUiMsg (player->settings, MSG_ERR, "Cannot open audio pipe file.\n"); + return false; + } + } else { + // use driver from libao configuration + driver = ao_default_driver_id (); + if ((player->aoDev = ao_open_live (driver, &aoFmt, NULL)) == NULL) { + BarUiMsg (player->settings, MSG_ERR, "Cannot open audio device.\n"); + return false; + } } return true; diff --git a/src/settings.c b/src/settings.c index bcb5dfc..7518177 100644 --- a/src/settings.c +++ b/src/settings.c @@ -125,6 +125,7 @@ void BarSettingsDestroy (BarSettings_t *settings) { free (settings->npStationFormat); free (settings->listSongFormat); free (settings->fifo); + free (settings->audioPipe); free (settings->rpcHost); free (settings->rpcTlsPort); free (settings->partnerUser); @@ -182,6 +183,7 @@ void BarSettingsRead (BarSettings_t *settings) { settings->inkey = strdup ("R=U!LH$O2B#"); settings->outkey = strdup ("6#26FRL$ZWD"); settings->fifo = BarGetXdgConfigDir (PACKAGE "/ctl"); + settings->audioPipe = NULL; assert (settings->fifo != NULL); settings->sampleRate = 0; /* default to stream sample rate */ @@ -390,6 +392,9 @@ void BarSettingsRead (BarSettings_t *settings) { } else if (streq ("fifo", key)) { free (settings->fifo); settings->fifo = BarSettingsExpandTilde (val, userhome); + } else if (streq ("audio_pipe", key)) { + free (settings->audioPipe); + settings->audioPipe = BarSettingsExpandTilde (val, userhome); } else if (streq ("autoselect", key)) { settings->autoselect = atoi (val); } else if (streq ("sample_rate", key)) { diff --git a/src/settings.h b/src/settings.h index a4264a2..1a9b256 100644 --- a/src/settings.h +++ b/src/settings.h @@ -103,6 +103,7 @@ typedef struct { char *listSongFormat; char *fifo; char *rpcHost, *rpcTlsPort, *partnerUser, *partnerPassword, *device, *inkey, *outkey, *caBundle; + char *audioPipe; char keys[BAR_KS_COUNT]; int sampleRate; BarMsgFormatStr_t msgFormat[MSG_COUNT]; -- cgit v1.2.3