summarylogtreecommitdiffstats
path: root/tvtime-1.0.2-alsa-r1.patch
diff options
context:
space:
mode:
authorRaansu2015-08-13 21:09:48 -0700
committerRaansu2015-08-13 21:09:48 -0700
commit0951f0454710ee13694eaa369cec88faf4737c4e (patch)
tree8672fa782f9f40a682b1c037c465c93339983518 /tvtime-1.0.2-alsa-r1.patch
downloadaur-tvtime-alsa.tar.gz
Initial upload to AUR4
Diffstat (limited to 'tvtime-1.0.2-alsa-r1.patch')
-rw-r--r--tvtime-1.0.2-alsa-r1.patch552
1 files changed, 552 insertions, 0 deletions
diff --git a/tvtime-1.0.2-alsa-r1.patch b/tvtime-1.0.2-alsa-r1.patch
new file mode 100644
index 000000000000..113fb9f591d6
--- /dev/null
+++ b/tvtime-1.0.2-alsa-r1.patch
@@ -0,0 +1,552 @@
+Add support for ALSA in combination with USB audio devices, bug #323797
+Patch from Ubuntu, rebased to our upstream
+
+diff -Naur tvtime-111b28cca42d.orig/src/audiolib.c tvtime-111b28cca42d/src/audiolib.c
+--- tvtime-111b28cca42d.orig/src/audiolib.c 1970-01-01 01:00:00.000000000 +0100
++++ tvtime-111b28cca42d/src/audiolib.c 2011-08-14 11:53:47.726915264 +0200
+@@ -0,0 +1,342 @@
++/*
++ Copyright 2008 Empia Technology Inc.
++ Copyright 2008 Markus Rechberger <mrechberger@empiatech.com>
++
++ alsa_set_params is derived from aplay.c
++
++ TODO:
++ more sysfs hacking for determining the empia audio device
++
++*/
++
++#include <stdio.h>
++#include "audiolib.h"
++
++static int alsa_set_params(snd_pcm_t *handle, struct alsa_stream_format *fmt, int start_delay);
++
++char *get_empia_device() {
++ int err;
++ int card = -1;
++ char dev[64];
++ int pcm_device = -1;
++ snd_ctl_t *ctl;
++ snd_pcm_info_t *pcm_info;
++ char *card_name;
++ do {
++ err = snd_card_next(&card);
++ if (card > -1) {
++ sprintf(dev, "hw:%i", card);
++ snd_ctl_open(&ctl, dev, 0);
++ snd_card_get_name(card, &card_name);
++ snd_pcm_info_alloca(&pcm_info);
++
++ for (;;)
++ {
++ char device[500], descr[1024];
++
++ if ((err = snd_ctl_pcm_next_device(ctl, &pcm_device)) < 0)
++ pcm_device = -1;
++
++ if (pcm_device < 0)
++ break;
++
++ snd_pcm_info_set_subdevice(pcm_info, 0);
++ snd_pcm_info_set_device(pcm_info, pcm_device);
++ snd_pcm_info_set_stream(pcm_info, SND_PCM_STREAM_CAPTURE);
++ if ((err = snd_ctl_pcm_info(ctl, pcm_info))==0) {
++ sprintf(device,"hw:%d,%d", card, pcm_device);
++ sprintf(descr,"%s : %s (%s)", card_name, snd_pcm_info_get_name(pcm_info),device);
++ if(strcmp(snd_pcm_info_get_name(pcm_info), "USB Audio") == 0) {
++ printf("Found \"%s\"\n", descr);
++ snd_ctl_close(ctl);
++ return strdup(device);
++
++ }
++ }
++ }
++ snd_ctl_close(ctl);
++ }
++
++ } while(card > -1);
++ return NULL;
++}
++
++int alsa_get_state(struct alsa_device *dev)
++{
++ return dev->state;
++}
++
++void alsa_set_state(struct alsa_device *dev, enum alsa_state state)
++{
++ dev->state = state;
++}
++
++struct alsa_device *alsa_open(char *input, char *output, unsigned long format, int channels, unsigned int rate)
++{
++ int result;
++ struct alsa_device *dev = malloc(sizeof(struct alsa_device));
++
++ dev->fmt.format = format;
++ dev->fmt.channels = channels;
++ dev->fmt.rate = rate;
++ dev->state = ALSA_STATE_STOPPED;
++
++ if (dev == NULL)
++ return NULL;
++
++
++ if ((result = snd_pcm_open( &dev->playback, output, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK))<0)
++ {
++ free(dev);
++ return NULL;
++ }
++
++// snd_pcm_nonblock( dev->playback, 1);
++
++ alsa_set_params(dev->playback, &dev->fmt, 0);
++
++ if ((result = snd_pcm_open( &dev->capture, input, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK))<0)
++ {
++ free(dev);
++ return NULL;
++ }
++
++// snd_pcm_nonblock(dev->playback, 1);
++
++ alsa_set_params(dev->capture, &dev->fmt, 1);
++
++ return dev;
++}
++
++void alsa_close(struct alsa_device **dev)
++{
++ struct alsa_device *cdev = *dev;
++ snd_pcm_drain(cdev->playback);
++ snd_pcm_close(cdev->playback);
++ snd_pcm_drain(cdev->capture);
++ snd_pcm_close(cdev->capture);
++ free(*dev);
++ snd_config_update_free_global();
++ *dev = NULL;
++}
++
++#define TRANSFER_BUFSIZE 256
++
++void *alsa_start_thread(void *data)
++{
++ struct alsa_device *dev = data;
++ alsa_loop(dev);
++ return NULL;
++}
++
++int alsa_start_threaded_loop(struct alsa_device *dev)
++{
++ int pret = 0;
++ if (dev->state == ALSA_STATE_STOPPED)
++ {
++ dev->state = ALSA_STATE_RUNNING;
++ pthread_create(&dev->athread, NULL, alsa_start_thread, dev);
++ }
++ return pret;
++}
++
++int alsa_join_threaded_loop(struct alsa_device *dev)
++{
++ if (dev->state == ALSA_STATE_RUNNING)
++ {
++ dev->state = ALSA_STATE_STOPPED;
++ pthread_join(dev->athread, NULL);
++ }
++ return 0;
++}
++
++int alsa_loop(struct alsa_device *dev)
++{
++ int length, ret;
++ unsigned char buf[TRANSFER_BUFSIZE];
++ snd_pcm_uframes_t frames = TRANSFER_BUFSIZE/dev->fmt.bits_per_sample;
++ dev->state = ALSA_STATE_RUNNING;
++ while (dev->state == ALSA_STATE_RUNNING) {
++ length = snd_pcm_readi(dev->capture, buf, frames);
++ switch(length) {
++ case -EAGAIN:
++ snd_pcm_wait(dev->capture, 5);
++ continue;
++ case -EPIPE:
++ snd_pcm_drain(dev->capture);
++ snd_pcm_prepare(dev->capture);
++ continue;
++ default:
++ break;
++ }
++ if (length>0) {
++ ret = snd_pcm_writei(dev->playback, buf, length);
++ switch (ret) {
++ case -EPIPE:
++ snd_pcm_drain(dev->playback);
++ snd_pcm_prepare(dev->playback);
++ continue;
++ default:
++ break;
++ }
++ }
++ }
++ snd_pcm_drain(dev->capture);
++ snd_pcm_drain(dev->playback);
++ return 0;
++}
++
++/* set start_delay to 1 for capture */
++/* taken from aplay.c */
++static int alsa_set_params(snd_pcm_t *handle, struct alsa_stream_format *fmt, int start_delay)
++{
++ snd_pcm_uframes_t chunk_size = 0;
++ snd_pcm_hw_params_t *params;
++ snd_pcm_sw_params_t *swparams;
++ snd_pcm_uframes_t buffer_size;
++
++ unsigned buffer_time = 0;
++ unsigned period_time = 0;
++ snd_pcm_uframes_t buffer_frames = 0;
++ snd_pcm_uframes_t period_frames = 0;
++
++ int err;
++ size_t n;
++ snd_pcm_uframes_t xfer_align;
++ unsigned int rate;
++ int avail_min = -1;
++ int stop_delay = 0;
++
++ snd_pcm_uframes_t start_threshold, stop_threshold;
++ snd_pcm_hw_params_alloca(&params);
++ snd_pcm_sw_params_alloca(&swparams);
++ err = snd_pcm_hw_params_any(handle, params);
++ if (err < 0) {
++ printf("Broken configuration for this PCM: no configurations available");
++ exit(EXIT_FAILURE);
++ }
++
++
++ snd_pcm_access_mask_t *mask = alloca(snd_pcm_access_mask_sizeof());
++ snd_pcm_access_mask_none(mask);
++ snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_RW_INTERLEAVED);
++ err = snd_pcm_hw_params_set_access_mask(handle, params, mask);
++
++ if (err < 0) {
++ printf("Access type not available");
++ exit(EXIT_FAILURE);
++ }
++ err = snd_pcm_hw_params_set_format(handle, params, fmt->format);
++ if (err < 0) {
++ printf("Sample format non available");
++ exit(EXIT_FAILURE);
++ }
++ err = snd_pcm_hw_params_set_channels(handle, params, fmt->channels);
++ if (err < 0) {
++ printf("Channels count non available");
++ exit(EXIT_FAILURE);
++ }
++
++ rate = fmt->rate;
++ err = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0);
++
++ assert(err >= 0);
++
++ rate = fmt->rate;
++
++ if (buffer_time == 0 && buffer_frames == 0) {
++ err = snd_pcm_hw_params_get_buffer_time_max(params,
++ &buffer_time, 0);
++ assert(err >= 0);
++ if (buffer_time > 500000)
++ buffer_time = 500000;
++ }
++
++ if (period_time == 0 && period_frames == 0) {
++ if (buffer_time > 0)
++ period_time = buffer_time / 4;
++ else
++ period_frames = buffer_frames / 4;
++ }
++
++ if (period_time > 0)
++ err = snd_pcm_hw_params_set_period_time_near(handle, params,
++ &period_time, 0);
++ else
++ err = snd_pcm_hw_params_set_period_size_near(handle, params,
++ &period_frames, 0);
++
++ assert(err >= 0);
++ if (buffer_time > 0)
++ err = snd_pcm_hw_params_set_buffer_time_near(handle, params,
++ &buffer_time, 0);
++ else
++ err = snd_pcm_hw_params_set_buffer_size_near(handle, params,
++ &buffer_frames);
++
++ assert(err >= 0);
++ err = snd_pcm_hw_params(handle, params);
++ if (err < 0) {
++ printf("Unable to install hw params");
++ return -EINVAL;
++ }
++ snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
++ snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
++
++ if (chunk_size == buffer_size) {
++ printf("Can't use period equal to buffer size (%lu == %lu)", chunk_size, buffer_size);
++ return -EINVAL;
++ }
++
++ snd_pcm_sw_params_current(handle, swparams);
++ err = snd_pcm_sw_params_get_xfer_align(swparams, &xfer_align);
++ if (err < 0) {
++ printf("Unable to obtain xfer align\n");
++ exit(EXIT_FAILURE);
++ }
++
++ err = snd_pcm_sw_params_set_sleep_min(handle, swparams, 0);
++
++ assert(err >= 0);
++ if (avail_min < 0)
++ n = chunk_size;
++ else
++ n = (double) rate * avail_min / 1000000;
++
++ err = snd_pcm_sw_params_set_avail_min(handle, swparams, n);
++
++ /* round up to closest transfer boundary */
++ n = (buffer_size / xfer_align) * xfer_align;
++ if (start_delay <= 0) {
++ start_threshold = n + (double) rate * start_delay / 1000000;
++ } else
++ start_threshold = (double) rate * start_delay / 1000000;
++ if (start_threshold < 1)
++ start_threshold = 1;
++ if (start_threshold > n)
++ start_threshold = n;
++
++ err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
++ assert(err >= 0);
++
++ if (stop_delay <= 0)
++ stop_threshold = buffer_size + (double) rate * stop_delay / 1000000;
++ else
++ stop_threshold = (double) rate * stop_delay / 1000000;
++
++ err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
++ assert(err >= 0);
++
++ err = snd_pcm_sw_params_set_xfer_align(handle, swparams, xfer_align);
++ assert(err >= 0);
++
++ if (snd_pcm_sw_params(handle, swparams) < 0) {
++ printf("unable to install sw params");
++ return -EINVAL;
++ }
++
++ fmt->bits_per_sample = snd_pcm_format_physical_width(fmt->format);
++ fmt->bits_per_frame = fmt->bits_per_sample * fmt->channels;
++ fmt->chunk_bytes = chunk_size * fmt->bits_per_frame / 8;
++ return 0;
++}
+diff -Naur tvtime-111b28cca42d.orig/src/audiolib.h tvtime-111b28cca42d/src/audiolib.h
+--- tvtime-111b28cca42d.orig/src/audiolib.h 1970-01-01 01:00:00.000000000 +0100
++++ tvtime-111b28cca42d/src/audiolib.h 2011-08-14 11:53:47.771915261 +0200
+@@ -0,0 +1,38 @@
++#ifndef _AUDIO_LIB_H
++#define _AUDIO_LIB_H
++#include <alsa/asoundlib.h>
++#include <pthread.h>
++
++struct alsa_stream_format {
++ unsigned long format;
++ int channels;
++ unsigned int rate;
++ size_t bits_per_sample;
++ size_t bits_per_frame;
++ size_t chunk_bytes;
++};
++
++enum alsa_state {
++ ALSA_STATE_STOPPED,
++ ALSA_STATE_RUNNING
++};
++
++struct alsa_device {
++ snd_pcm_t *capture;
++ snd_pcm_t *playback;
++ enum alsa_state state;
++ struct alsa_stream_format fmt;
++ pthread_t athread;
++};
++
++struct alsa_device *alsa_open(char *input, char *output, unsigned long format, int channels, unsigned int rate);
++char *get_empia_device();
++int alsa_loop(struct alsa_device *dev);
++int alsa_get_state(struct alsa_device *dev);
++void alsa_close(struct alsa_device **dev);
++int alsa_get_state(struct alsa_device *dev);
++void alsa_set_state(struct alsa_device *dev, enum alsa_state state);
++int alsa_start_threaded_loop(struct alsa_device *dev);
++int alsa_join_threaded_loop(struct alsa_device *dev);
++
++#endif // _AUDIO_LIB_H
+diff -Naur tvtime-111b28cca42d.orig/src/Makefile.am tvtime-111b28cca42d/src/Makefile.am
+--- tvtime-111b28cca42d.orig/src/Makefile.am 2011-08-14 11:52:43.404917552 +0200
++++ tvtime-111b28cca42d/src/Makefile.am 2011-08-14 11:56:09.243910228 +0200
+@@ -37,7 +37,7 @@
+ utils.h utils.c pulldown.h pulldown.c hashtable.h hashtable.c \
+ cpuinfo.h cpuinfo.c videodev2.h menu.c menu.h \
+ outputfilter.h outputfilter.c xmltv.h xmltv.c gettext.h tvtimeglyphs.h \
+- copyfunctions.h copyfunctions.c alsa_stream.c
++ copyfunctions.h copyfunctions.c alsa_stream.c audiolib.h audiolib.c
+
+ if ARCH_X86
+ DSCALER_SRCS = $(top_srcdir)/plugins/dscalerapi.h \
+@@ -74,7 +74,7 @@
+ $(PLUGIN_CFLAGS) $(X11_CFLAGS) $(XML2_FLAG) \
+ $(FONT_CFLAGS) $(AM_CFLAGS)
+ tvtime_LDADD = $(TTF_LIBS) $(ZLIB_LIBS) $(PNG_LIBS) \
+- $(X11_LIBS) $(XML2_LIBS) $(ASOUND_LIBS) -lm -lsupc++ -lpthread
++ $(X11_LIBS) $(XML2_LIBS) $(ASOUND_LIBS) -lm -lsupc++ -lpthread -lasound
+
+ tvtime_command_SOURCES = utils.h utils.c tvtimeconf.h tvtimeconf.c \
+ tvtime-command.c
+diff -Naur tvtime-111b28cca42d.orig/src/tvtime.c tvtime-111b28cca42d/src/tvtime.c
+--- tvtime-111b28cca42d.orig/src/tvtime.c 2011-02-01 02:35:26.000000000 +0100
++++ tvtime-111b28cca42d/src/tvtime.c 2011-08-14 11:56:35.443909297 +0200
+@@ -78,6 +78,7 @@
+ #include "menu.h"
+ #include "tvtimeglyphs.h"
+ #include "alsa_stream.h"
++#include "audiolib.h"
+
+ /**
+ * This is how many frames to wait until deciding if the pulldown phase
+@@ -1210,6 +1211,7 @@
+ int last_current_id = -1;
+ int quiet_screenshots = 0;
+ char prevloc[ 256 ];
++ char *empia_device;
+ int i;
+
+ ct = config_new();
+@@ -1581,6 +1583,8 @@
+ build_fspos_menu( commands_get_menu( commands, "fspos" ),
+ config_get_fullscreen_position( ct ) );
+
++ empia_device = get_empia_device();
++
+ /* Initialize our timestamps. */
+ for(;;) {
+ const char *fifo_args = 0;
+@@ -2056,9 +2060,30 @@
+
+ if( tuner_state == TUNER_STATE_HAS_SIGNAL ) {
+ has_signal = 1;
++ /* reopen the device for now, there are several issues which don't allow pausing the
++ audio data transfer.
++
++ TODO:
++ The driver(?) seems to crash when setting up the alsa parameters again during the same
++ session.
++ */
++
++ if (empia_device && videoinput_get_audio(vidin) == NULL) {
++ videoinput_set_audio(vidin, alsa_open(empia_device, "default", SND_PCM_FORMAT_S16_LE, 2 /* 2 channels */, 48000 /* rate */));
++ if (videoinput_get_audio(vidin)) {
++ alsa_start_threaded_loop(videoinput_get_audio(vidin));
++ }
++ }
++
+ if( osd ) tvtime_osd_signal_present( osd, 1 );
+ } else if( tuner_state == TUNER_STATE_NO_SIGNAL ) {
+ if( osd ) tvtime_osd_signal_present( osd, 0 );
++ if (videoinput_get_audio(vidin)) {
++ alsa_join_threaded_loop(videoinput_get_audio(vidin));
++ alsa_close(videoinput_get_audio_p(vidin));
++ videoinput_set_audio(vidin, NULL);
++ }
++
+ if( fadepos < 256 ) {
+ crossfade_frame( fadeframe, saveframe, blueframe, width,
+ height, width*2, width*2, width*2, fadepos );
+@@ -2499,6 +2524,11 @@
+ /* Return to normal scheduling. */
+ set_default_priority();
+
++ if (videoinput_get_audio(vidin)) {
++ alsa_join_threaded_loop(videoinput_get_audio(vidin));
++ alsa_close(videoinput_get_audio_p(vidin));
++ }
++
+ /* Remember to save our settings if we were scanning. */
+ if( scanning ) {
+ station_writeconfig( stationmgr );
+diff -Naur tvtime-111b28cca42d.orig/src/videoinput.c tvtime-111b28cca42d/src/videoinput.c
+--- tvtime-111b28cca42d.orig/src/videoinput.c 2011-02-01 02:35:26.000000000 +0100
++++ tvtime-111b28cca42d/src/videoinput.c 2011-08-14 12:03:39.783894207 +0200
+@@ -38,6 +38,7 @@
+ #include <linux/videodev2.h>
+ #include "videoinput.h"
+ #include "mixer.h"
++#include "audiolib.h"
+
+ /**
+ * How long to wait when we lose a signal, or acquire a signal.
+@@ -198,8 +199,25 @@
+ /* V4L2 capture state. */
+ capture_buffer_t capbuffers[ MAX_CAPTURE_BUFFERS ];
+ int is_streaming;
++
++ struct alsa_device *adev;
+ };
+
++struct alsa_device *videoinput_get_audio( videoinput_t *vidin )
++{
++ return vidin->adev;
++}
++
++struct alsa_device **videoinput_get_audio_p( videoinput_t *vidin )
++{
++ return &vidin->adev;
++}
++
++void videoinput_set_audio( videoinput_t *vidin, struct alsa_device *dev )
++{
++ vidin->adev = dev;
++}
++
+ static void videoinput_start_capture_v4l2( videoinput_t *vidin )
+ {
+ if( !vidin->is_streaming ) {
+@@ -347,6 +365,7 @@
+ vidin->norm = norm;
+ vidin->volume = volume;
+ vidin->amode = 0;
++ vidin->adev = NULL;
+ vidin->height = videoinput_get_norm_height( norm );
+ vidin->cur_tuner_state = TUNER_STATE_NO_SIGNAL;
+
+diff -Naur tvtime-111b28cca42d.orig/src/videoinput.h tvtime-111b28cca42d/src/videoinput.h
+--- tvtime-111b28cca42d.orig/src/videoinput.h 2011-02-01 02:35:26.000000000 +0100
++++ tvtime-111b28cca42d/src/videoinput.h 2011-08-14 11:53:47.775915262 +0200
+@@ -278,6 +278,20 @@
+ const char *videoinput_get_driver_name( videoinput_t *vidin );
+
+ /**
++ * Returns the audio handle of the device struct.
++ */
++struct alsa_device *videoinput_get_audio( videoinput_t *vidin );
++
++/**
++ * Returns a pointer to the alsa_device pointer, used for cleaning up
++ */
++struct alsa_device **videoinput_get_audio_p (videoinput_t *vidin );
++
++/**
++ * Set adev for vidin
++ */
++void videoinput_set_audio( videoinput_t *vidin, struct alsa_device *dev);
++/**
+ * Sets the capture card volume to use as a percentage from 0-100.
+ * If the value is negative, the capture card volume will remain unset.
+ */