aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDevin Heitmueller <dheitmueller@kernellabs.com>2009-12-28 04:16:47 (GMT)
committerDevin Heitmueller <dheitmueller@kernellabs.com>2009-12-28 04:16:47 (GMT)
commit7c1db62277c19dffc4fc77cc5a3af5733e335110 (patch)
tree45ffe1c49612f70074434eb9f3b17b0dcef5dc68 /src
parentaf27137adc35f92cb11288642afa1a13e2089b81 (diff)
djh - first cut at including support for reading on an ALSA device during playback. Currently only tested with the HVR-950q.
Also, there is currently no GUI option to set the device - users must run "./tvtime-configure --alsainputdev=hw:1,0" and "./tvtime-configure --alsaoutputdev=hw:0,0" to set the input and output devices.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am4
-rw-r--r--src/alsa_stream.c501
-rw-r--r--src/alsa_stream.h1
-rw-r--r--src/tvtime.c5
-rw-r--r--src/tvtimeconf.c60
-rw-r--r--src/tvtimeconf.h2
6 files changed, 570 insertions, 3 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index ff1d3e7..7655e9e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -40,7 +40,7 @@ COMMON_SRCS = mixer.c videoinput.c rtctimer.c leetft.c osdtools.c tvtimeconf.c \
utils.h utils.c pulldown.h pulldown.c hashtable.h hashtable.c \
cpuinfo.h cpuinfo.c videodev.h videodev2.h menu.c menu.h \
outputfilter.h outputfilter.c xmltv.h xmltv.c gettext.h tvtimeglyphs.h \
- copyfunctions.h copyfunctions.c
+ copyfunctions.h copyfunctions.c alsa_stream.c
if ARCH_X86
DSCALER_SRCS = $(top_srcdir)/plugins/dscalerapi.h \
@@ -77,7 +77,7 @@ tvtime_CFLAGS = $(TTF_CFLAGS) $(PNG_CFLAGS) $(OPT_CFLAGS) \
$(PLUGIN_CFLAGS) $(X11_CFLAGS) $(XML2_FLAG) \
$(FONT_CFLAGS) $(AM_CFLAGS)
tvtime_LDFLAGS = $(TTF_LIBS) $(ZLIB_LIBS) $(PNG_LIBS) \
- $(X11_LIBS) $(XML2_LIBS) -lm -lstdc++
+ $(X11_LIBS) $(XML2_LIBS) $(ASOUND_LIBS) -lm -lstdc++
tvtime_command_SOURCES = utils.h utils.c tvtimeconf.h tvtimeconf.c \
tvtime-command.c
diff --git a/src/alsa_stream.c b/src/alsa_stream.c
new file mode 100644
index 0000000..2243b02
--- /dev/null
+++ b/src/alsa_stream.c
@@ -0,0 +1,501 @@
+/*
+ * tvtime ALSA device support
+ *
+ * Copyright (c) by Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ * Derived from the alsa-driver test tool latency.c:
+ * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sched.h>
+#include <errno.h>
+#include <getopt.h>
+#include <pthread.h>
+#include <alsa/asoundlib.h>
+#include <sys/time.h>
+#include <math.h>
+
+snd_output_t *output = NULL;
+
+struct final_params {
+ int bufsize;
+ int rate;
+ int latency;
+ int channels;
+};
+
+int setparams_stream(snd_pcm_t *handle,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_format_t format,
+ int channels,
+ int rate,
+ const char *id)
+{
+ int err;
+ unsigned int rrate;
+
+ err = snd_pcm_hw_params_any(handle, params);
+ if (err < 0) {
+ printf("Broken configuration for %s PCM: no configurations available: %s\n", snd_strerror(err), id);
+ return err;
+ }
+ err = snd_pcm_hw_params_set_rate_resample(handle, params, 1);
+ if (err < 0) {
+ printf("Resample setup failed for %s: %s\n", id, snd_strerror(err));
+ return err;
+ }
+ err = snd_pcm_hw_params_set_access(handle, params,
+ SND_PCM_ACCESS_RW_INTERLEAVED);
+ if (err < 0) {
+ printf("Access type not available for %s: %s\n", id,
+ snd_strerror(err));
+ return err;
+ }
+
+ err = snd_pcm_hw_params_set_format(handle, params, format);
+ if (err < 0) {
+ printf("Sample format not available for %s: %s\n", id,
+ snd_strerror(err));
+ return err;
+ }
+ err = snd_pcm_hw_params_set_channels(handle, params, channels);
+ if (err < 0) {
+ printf("Channels count (%i) not available for %s: %s\n", channels, id,
+ snd_strerror(err));
+ return err;
+ }
+ rrate = rate;
+ err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
+ if (err < 0) {
+ printf("Rate %iHz not available for %s: %s\n", rate, id,
+ snd_strerror(err));
+ return err;
+ }
+ if ((int)rrate != rate) {
+ printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int setparams_bufsize(snd_pcm_t *handle,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_hw_params_t *tparams,
+ snd_pcm_uframes_t bufsize,
+ int period_size,
+ const char *id)
+{
+ int err;
+ snd_pcm_uframes_t periodsize;
+
+ snd_pcm_hw_params_copy(params, tparams);
+ periodsize = bufsize * 2;
+ err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &periodsize);
+ if (err < 0) {
+ printf("Unable to set buffer size %li for %s: %s\n",
+ bufsize * 2, id, snd_strerror(err));
+ return err;
+ }
+ if (period_size > 0)
+ periodsize = period_size;
+ else
+ periodsize /= 2;
+ err = snd_pcm_hw_params_set_period_size_near(handle, params, &periodsize,
+ 0);
+ if (err < 0) {
+ printf("Unable to set period size %li for %s: %s\n", periodsize, id,
+ snd_strerror(err));
+ return err;
+ }
+ return 0;
+}
+
+int setparams_set(snd_pcm_t *handle,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_sw_params_t *swparams,
+ const char *id)
+{
+ int err;
+
+ err = snd_pcm_hw_params(handle, params);
+ if (err < 0) {
+ printf("Unable to set hw params for %s: %s\n", id, snd_strerror(err));
+ return err;
+ }
+ err = snd_pcm_sw_params_current(handle, swparams);
+ if (err < 0) {
+ printf("Unable to determine current swparams for %s: %s\n", id,
+ snd_strerror(err));
+ return err;
+ }
+ err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0x7fffffff);
+ if (err < 0) {
+ printf("Unable to set start threshold mode for %s: %s\n", id,
+ snd_strerror(err));
+ return err;
+ }
+
+ err = snd_pcm_sw_params_set_avail_min(handle, swparams, 4);
+ if (err < 0) {
+ printf("Unable to set avail min for %s: %s\n", id, snd_strerror(err));
+ return err;
+ }
+ err = snd_pcm_sw_params(handle, swparams);
+ if (err < 0) {
+ printf("Unable to set sw params for %s: %s\n", id, snd_strerror(err));
+ return err;
+ }
+ return 0;
+}
+
+int setparams(snd_pcm_t *phandle, snd_pcm_t *chandle, snd_pcm_format_t format,
+ struct final_params *negotiated)
+{
+ int rate = 48000;
+ int latency_min = 600; /* in frames / 2 */
+ int channels = 2;
+ int latency = latency_min - 4;
+ int bufsize = latency;
+ int err, last_bufsize = bufsize;
+ snd_pcm_hw_params_t *pt_params, *ct_params;
+ snd_pcm_hw_params_t *p_params, *c_params;
+ snd_pcm_sw_params_t *p_swparams, *c_swparams;
+ snd_pcm_uframes_t p_size, c_size, p_psize, c_psize;
+ unsigned int p_time, c_time;
+
+ snd_pcm_hw_params_alloca(&p_params);
+ snd_pcm_hw_params_alloca(&c_params);
+ snd_pcm_hw_params_alloca(&pt_params);
+ snd_pcm_hw_params_alloca(&ct_params);
+ snd_pcm_sw_params_alloca(&p_swparams);
+ snd_pcm_sw_params_alloca(&c_swparams);
+ if ((err = setparams_stream(phandle, pt_params, format, channels, rate,
+ "playback")) < 0) {
+ printf("Unable to set parameters for playback stream: %s\n", snd_strerror(err));
+ return 1;
+ }
+ if ((err = setparams_stream(chandle, ct_params, format, channels, rate,
+ "capture")) < 0) {
+ printf("Unable to set parameters for playback stream: %s\n", snd_strerror(err));
+ return 1;
+ }
+
+ __again:
+ if (last_bufsize == bufsize)
+ bufsize += 4;
+ last_bufsize = bufsize;
+
+ if ((err = setparams_bufsize(phandle, p_params, pt_params, bufsize, 0,
+ "playback")) < 0) {
+ printf("Unable to set sw parameters for playback stream: %s\n",
+ snd_strerror(err));
+ return -1;
+ }
+ if ((err = setparams_bufsize(chandle, c_params, ct_params, bufsize, 0,
+ "capture")) < 0) {
+ printf("Unable to set sw parameters for playback stream: %s\n",
+ snd_strerror(err));
+ return -1;
+ }
+
+ snd_pcm_hw_params_get_period_size(p_params, &p_psize, NULL);
+ if (p_psize > (unsigned int)bufsize)
+ bufsize = p_psize;
+
+ snd_pcm_hw_params_get_period_size(c_params, &c_psize, NULL);
+ if (c_psize > (unsigned int)bufsize)
+ bufsize = c_psize;
+
+ snd_pcm_hw_params_get_period_time(p_params, &p_time, NULL);
+ snd_pcm_hw_params_get_period_time(c_params, &c_time, NULL);
+
+ if (p_time != c_time)
+ goto __again;
+
+ snd_pcm_hw_params_get_buffer_size(p_params, &p_size);
+ if (p_psize * 2 < p_size)
+ goto __again;
+ snd_pcm_hw_params_get_buffer_size(c_params, &c_size);
+ if (c_psize * 2 < c_size)
+ goto __again;
+
+ if ((err = setparams_set(phandle, p_params, p_swparams, "playback")) < 0) {
+ printf("Unable to set sw parameters for playback stream: %s\n",
+ snd_strerror(err));
+ return -1;
+ }
+ if ((err = setparams_set(chandle, c_params, c_swparams, "capture")) < 0) {
+ printf("Unable to set sw parameters for playback stream: %s\n",
+ snd_strerror(err));
+ return -1;
+ }
+
+ if ((err = snd_pcm_prepare(phandle)) < 0) {
+ printf("Prepare error: %s\n", snd_strerror(err));
+ return -1;
+ }
+
+#ifdef SHOW_ALSA_DEBUG
+ printf("final config\n");
+ snd_pcm_dump_setup(phandle, output);
+ snd_pcm_dump_setup(chandle, output);
+ printf("Parameters are %iHz, %s, %i channels\n", rate,
+ snd_pcm_format_name(format), channels);
+ fflush(stdout);
+#endif
+
+ negotiated->bufsize = bufsize;
+ negotiated->rate = rate;
+ negotiated->channels = channels;
+ negotiated->latency = bufsize;
+ return 0;
+}
+
+void setscheduler(void)
+{
+ struct sched_param sched_param;
+
+ if (sched_getparam(0, &sched_param) < 0) {
+ printf("Scheduler getparam failed...\n");
+ return;
+ }
+ sched_param.sched_priority = sched_get_priority_max(SCHED_RR);
+ if (!sched_setscheduler(0, SCHED_RR, &sched_param)) {
+ printf("Scheduler set to Round Robin with priority %i...\n", sched_param.sched_priority);
+ fflush(stdout);
+ return;
+ }
+ printf("!!!Scheduler set to Round Robin with priority %i FAILED!!!\n", sched_param.sched_priority);
+}
+
+snd_pcm_sframes_t readbuf(snd_pcm_t *handle, char *buf, long len,
+ size_t *frames, size_t *max)
+{
+ snd_pcm_sframes_t r;
+
+ r = snd_pcm_readi(handle, buf, len);
+ if (r < 0) {
+ return r;
+ }
+
+ if (r > 0) {
+ *frames += r;
+ if ((long)*max < r)
+ *max = r;
+ }
+
+ return r;
+}
+
+snd_pcm_sframes_t writebuf(snd_pcm_t *handle, char *buf, long len,
+ size_t *frames)
+{
+ snd_pcm_sframes_t r;
+
+ while (len > 0) {
+ r = snd_pcm_writei(handle, buf, len);
+ if (r < 0) {
+ return r;
+ }
+
+ buf += r * 4;
+ len -= r;
+ *frames += r;
+ }
+ return 0;
+}
+
+int startup_capture(snd_pcm_t *phandle, snd_pcm_t *chandle,
+ snd_pcm_format_t format, char *buffer, int latency,
+ int channels)
+{
+ size_t frames_out;
+ int err;
+
+ frames_out = 0;
+ if (snd_pcm_format_set_silence(format, buffer, latency*channels) < 0) {
+ fprintf(stderr, "silence error\n");
+ return 1;
+ }
+ if (writebuf(phandle, buffer, latency, &frames_out) < 0) {
+ fprintf(stderr, "write error\n");
+ return 1;
+ }
+ if (writebuf(phandle, buffer, latency, &frames_out) < 0) {
+ fprintf(stderr, "write error\n");
+ return 1;
+ }
+
+ if ((err = snd_pcm_start(chandle)) < 0) {
+ printf("Go error: %s\n", snd_strerror(err));
+ return 1;
+ }
+ return 0;
+}
+
+int tvtime_alsa_stream(const char *pdevice, const char *cdevice)
+{
+ snd_pcm_t *phandle, *chandle;
+ char *buffer;
+ int err;
+ ssize_t r;
+ size_t frames_in, frames_out, in_max;
+ struct final_params negotiated;
+ int ret = 0;
+ snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
+
+ err = snd_output_stdio_attach(&output, stdout, 0);
+ if (err < 0) {
+ printf("Output failed: %s\n", snd_strerror(err));
+ return 0;
+ }
+
+// setscheduler();
+
+ printf("Playback device is %s\n", pdevice);
+ printf("Capture device is %s\n", cdevice);
+
+ /* Open the devices */
+ if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK,
+ SND_PCM_NONBLOCK)) < 0) {
+ printf("Cannot open ALSA Playback device %s: %s\n", pdevice,
+ snd_strerror(err));
+ return 0;
+ }
+ if ((err = snd_pcm_open(&chandle, cdevice, SND_PCM_STREAM_CAPTURE,
+ SND_PCM_NONBLOCK)) < 0) {
+ printf("Cannot open ALSA Capture device %s: %s\n",
+ cdevice, snd_strerror(err));
+ return 0;
+ }
+
+ frames_in = frames_out = 0;
+ if (setparams(phandle, chandle, format, &negotiated) < 0) {
+ printf("setparams failed\n");
+ return 1;
+ }
+
+ buffer = malloc((negotiated.bufsize * snd_pcm_format_width(format) / 8)
+ * negotiated.channels);
+ if (buffer == NULL) {
+ printf("Failed allocating buffer for audio\n");
+ return 0;
+
+ }
+ if ((err = snd_pcm_link(chandle, phandle)) < 0) {
+ printf("Streams link error: %d %s\n", err, snd_strerror(err));
+ return 1;
+ }
+
+ startup_capture(phandle, chandle, format, buffer, negotiated.latency,
+ negotiated.channels);
+
+ while (1) {
+ in_max = 0;
+
+ /* use poll to wait for next event */
+ ret = snd_pcm_wait(chandle, 1000);
+ if (ret < 0) {
+ if ((err = snd_pcm_recover(chandle, ret, 0)) < 0) {
+ fprintf(stderr, "xrun: recover error: %s",
+ snd_strerror(err));
+ break;
+ }
+
+ /* Restart capture */
+ startup_capture(phandle, chandle, format, buffer,
+ negotiated.latency, negotiated.channels);
+ continue;
+ } else if (ret == 0) {
+ /* Timed out */
+ continue;
+ }
+
+ if ((r = readbuf(chandle, buffer, negotiated.latency, &frames_in,
+ &in_max)) > 0) {
+ if (writebuf(phandle, buffer, r, &frames_out) < 0) {
+ startup_capture(phandle, chandle, format, buffer,
+ negotiated.latency, negotiated.channels);
+ }
+ } else if (r < 0) {
+ startup_capture(phandle, chandle, format, buffer,
+ negotiated.latency, negotiated.channels);
+ }
+ }
+
+ snd_pcm_drop(chandle);
+ snd_pcm_nonblock(phandle, 0);
+ snd_pcm_drain(phandle);
+
+ snd_pcm_unlink(chandle);
+ snd_pcm_hw_free(phandle);
+ snd_pcm_hw_free(chandle);
+
+ snd_pcm_close(phandle);
+ snd_pcm_close(chandle);
+ return 0;
+}
+
+struct input_params {
+ const char *pdevice;
+ const char *cdevice;
+};
+
+void *tvtime_alsa_thread_entry(void *whatever)
+{
+ struct input_params *inputs = (struct input_params *) whatever;
+ tvtime_alsa_stream(inputs->pdevice, inputs->cdevice);
+}
+
+int tvtime_alsa_thread_startup(const char *pdevice, const char *cdevice)
+{
+ int ret;
+ pthread_t thread;
+ struct input_params *inputs = malloc(sizeof(struct input_params));
+
+ if (inputs == NULL) {
+ printf("failed allocating memory for ALSA inputs\n");
+ return 0;
+ }
+
+ if ((strcasecmp(pdevice, "disabled") == 0) ||
+ (strcasecmp(cdevice, "disabled") == 0)) {
+ free(inputs);
+ return 0;
+ }
+
+ inputs->pdevice = strdup(pdevice);
+ inputs->cdevice = strdup(cdevice);
+
+ ret = pthread_create(&thread, NULL,
+ &tvtime_alsa_thread_entry, (void *) inputs);
+ return ret;
+}
+
+#ifdef TVTIME_ALSA_DEBUGGING
+/* This allows the alsa_stream.c to be a standalone binary for debugging */
+ int main(int argc, char *argv[])
+{
+ char *pdevice = "hw:0,0";
+ char *cdevice = "hw:1,0";
+ tvtime_alsa_stream(pdevice, cdevice);
+}
+#endif
diff --git a/src/alsa_stream.h b/src/alsa_stream.h
new file mode 100644
index 0000000..8572c8b
--- /dev/null
+++ b/src/alsa_stream.h
@@ -0,0 +1 @@
+int tvtime_alsa_thread_startup(char *pdevice, char *cdevice);
diff --git a/src/tvtime.c b/src/tvtime.c
index bdc0986..4c8b2b4 100644
--- a/src/tvtime.c
+++ b/src/tvtime.c
@@ -77,6 +77,7 @@
#include "mm_accel.h"
#include "menu.h"
#include "tvtimeglyphs.h"
+#include "alsa_stream.h"
/**
* This is how many frames to wait until deciding if the pulldown phase
@@ -1254,6 +1255,10 @@ int tvtime_main( rtctimer_t *rtctimer, int read_stdin, int realtime,
return 1;
}
+ /* Setup the ALSA streaming device */
+ tvtime_alsa_thread_startup(config_get_alsa_outputdev( ct ),
+ config_get_alsa_inputdev( ct ) );
+
/* Setup the speedy calls. */
setup_speedy_calls( mm_accel(), verbose );
diff --git a/src/tvtimeconf.c b/src/tvtimeconf.c
index 4f6a447..5db6325 100644
--- a/src/tvtimeconf.c
+++ b/src/tvtimeconf.c
@@ -120,6 +120,9 @@ struct config_s
char *config_filename;
xmlDocPtr doc;
+
+ char *alsa_inputdev;
+ char *alsa_outputdev;
};
static unsigned int parse_colour( const char *str )
@@ -402,6 +405,17 @@ static void parse_option( config_t *ct, xmlNodePtr node )
if( ct->mixerdev ) free( ct->mixerdev );
ct->mixerdev = strdup( curval );
}
+
+ if( !xmlStrcasecmp( name, BAD_CAST "AlsaInputDev" ) ) {
+ if( ct->alsa_inputdev ) free( ct->alsa_inputdev );
+ ct->alsa_inputdev = strdup( curval );
+ }
+
+ if( !xmlStrcasecmp( name, BAD_CAST "AlsaOutputDev" ) ) {
+ if( ct->alsa_outputdev ) free( ct->alsa_outputdev );
+ ct->alsa_outputdev = strdup( curval );
+ }
+
}
if( name ) xmlFree( name );
@@ -684,6 +698,14 @@ static void print_config_usage( char **argv )
" mic, cd, mix, pcm2, rec, igain, ogain, line1,\n"
" line2, line3, dig1, dig2, dig3, phin, phout,\n"
" video, radio, monitor\n"), stderr );
+ lfputs( _(" -p, --alsainputdev=DEV Specifies an ALSA device to read input on\n"
+ " Examples:\n"
+ " hw:1,0\n"
+ " disabled\n"), stderr );
+ lfputs( _(" -P, --alsaoutputdev=DEV Specifies an ALSA device to write output to\n"
+ " Examples:\n"
+ " hw:0,0\n"
+ " disabled\n"), stderr );
}
static void print_scanner_usage( char **argv )
@@ -782,6 +804,9 @@ config_t *config_new( void )
ct->config_filename = 0;
ct->doc = 0;
+ ct->alsa_inputdev = strdup( "hw:1,0" );
+ ct->alsa_outputdev = strdup( "hw:0,0" );
+
/* Default key bindings. */
ct->keymap[ 0 ] = TVTIME_NOCOMMAND;
ct->keymap[ I_ESCAPE ] = TVTIME_QUIT;
@@ -1038,6 +1063,8 @@ int config_parse_tvtime_config_command_line( config_t *ct, int argc, char **argv
{ "xmltv", 2, 0, 't' },
{ "xmltvlanguage", 2, 0, 'l' },
{ "priority", 2, 0, 'R' },
+ { "alsainputdev", 2, 0, 'p' },
+ { "alsaoutputdev", 2, 0, 'P' },
{ 0, 0, 0, 0 }
};
int option_index = 0;
@@ -1049,7 +1076,8 @@ int config_parse_tvtime_config_command_line( config_t *ct, int argc, char **argv
return 0;
}
- while( (c = getopt_long( argc, argv, "aAhmMF:g:I:d:b:i:c:n:D:f:x:t:l:R:",
+ while( (c = getopt_long( argc, argv,
+ "aAhmMF:g:I:d:b:i:c:n:D:f:x:t:l:R:p:P",
long_options, &option_index )) != -1 ) {
switch( c ) {
case 'a': ct->aspect = 1; break;
@@ -1134,6 +1162,22 @@ int config_parse_tvtime_config_command_line( config_t *ct, int argc, char **argv
ct->priority = atoi( optarg );
}
break;
+ case 'p': if( !optarg ) {
+ fprintf( stdout, "AlsaInputDevice:%s\n",
+ config_get_alsa_inputdev( ct ) );
+ } else {
+ free( ct->alsa_inputdev );
+ ct->alsa_inputdev = strdup( optarg );
+ }
+ break;
+ case 'P': if( !optarg ) {
+ fprintf( stdout, "AlsaOutputDevice:%s\n",
+ config_get_alsa_outputdev( ct ) );
+ } else {
+ free( ct->alsa_outputdev );
+ ct->alsa_outputdev = strdup( optarg );
+ }
+ break;
default:
print_config_usage( argv );
return 0;
@@ -1199,6 +1243,9 @@ int config_parse_tvtime_config_command_line( config_t *ct, int argc, char **argv
snprintf( tempstring, sizeof( tempstring ), "%d", ct->priority );
config_save( ct, "ProcessPriority", tempstring );
+
+ config_save( ct, "AlsaInputDev", ct->alsa_inputdev );
+ config_save( ct, "AlsaOutputDev", ct->alsa_outputdev );
}
return 1;
@@ -1261,6 +1308,8 @@ void config_free_data( config_t *ct )
if( ct->vbidev ) free( ct->vbidev );
if( ct->config_filename ) free( ct->config_filename );
if( ct->deinterlace_method ) free( ct->deinterlace_method );
+ if( ct->alsa_inputdev ) free( ct->alsa_inputdev );
+ if( ct->alsa_outputdev ) free( ct->alsa_outputdev );
}
void config_delete( config_t *ct )
@@ -1661,3 +1710,12 @@ int config_get_square_pixels( config_t *ct )
return ct->squarepixels;
}
+const char *config_get_alsa_inputdev( config_t *ct )
+{
+ return ct->alsa_inputdev;
+}
+
+const char *config_get_alsa_outputdev( config_t *ct )
+{
+ return ct->alsa_outputdev;
+}
diff --git a/src/tvtimeconf.h b/src/tvtimeconf.h
index a451450..91a7b1b 100644
--- a/src/tvtimeconf.h
+++ b/src/tvtimeconf.h
@@ -192,6 +192,8 @@ int config_get_muted( config_t *ct );
int config_get_mute_on_exit( config_t *ct );
int config_get_show_taglines( config_t *ct );
int config_get_square_pixels( config_t *ct );
+const char *config_get_alsa_inputdev( config_t *ct );
+const char *config_get_alsa_outputdev( config_t *ct );
#ifdef __cplusplus
};

Privacy Policy