summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaansu2015-08-13 21:09:48 -0700
committerRaansu2015-08-13 21:09:48 -0700
commit0951f0454710ee13694eaa369cec88faf4737c4e (patch)
tree8672fa782f9f40a682b1c037c465c93339983518
downloadaur-tvtime-alsa.tar.gz
Initial upload to AUR4
-rw-r--r--.SRCINFO44
-rw-r--r--PKGBUILD75
-rw-r--r--tvtime-1.0.2-alsa-fixes.patch143
-rw-r--r--tvtime-1.0.2-alsa-r1.patch552
-rw-r--r--tvtime-1.0.2-alsamixer-r1.patch1165
-rw-r--r--tvtime-1.0.2-xinerama.patch32
-rw-r--r--tvtime-1.0.2_p20110131-autotools.patch69
-rw-r--r--tvtime-1.0.2_p20110131-gettext.patch71
-rw-r--r--tvtime-1.0.2_p20110131-libsupc++.patch12
-rw-r--r--tvtime-1.0.2_p20110131-underlinking.patch11
-rw-r--r--tvtime-libpng-1.5.patch14
-rw-r--r--tvtime-pic.patch11
12 files changed, 2199 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 000000000000..d39019b57ded
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,44 @@
+pkgbase = tvtime-alsa
+ pkgdesc = tvtime with ALSA patches from Gentoo
+ pkgver = 1.0.2_p20110131
+ pkgrel = 2
+ url = http://tvtime.sourceforge.net/
+ arch = i686
+ arch = x86_64
+ license = GPL
+ depends = libpng
+ depends = libxml2
+ depends = freetype2
+ depends = libxss
+ depends = libxinerama
+ depends = libxv
+ depends = libsm
+ depends = libxxf86vm
+ depends = alsa-lib
+ provides = tvtime
+ conflicts = tvtime
+ source = http://tvtime-fixed.googlecode.com/files/111b28cca42d.tar.bz2
+ source = tvtime-pic.patch
+ source = tvtime-1.0.2-xinerama.patch
+ source = tvtime-1.0.2_p20110131-libsupc++.patch
+ source = tvtime-1.0.2_p20110131-autotools.patch
+ source = tvtime-1.0.2_p20110131-gettext.patch
+ source = tvtime-libpng-1.5.patch
+ source = tvtime-1.0.2_p20110131-underlinking.patch
+ source = tvtime-1.0.2-alsamixer-r1.patch
+ source = tvtime-1.0.2-alsa-r1.patch
+ source = tvtime-1.0.2-alsa-fixes.patch
+ md5sums = 3f68ec60da6cc0d73339fb4ccc1b4a04
+ md5sums = 4bc08a98c7cc134accb89aea3018c2f6
+ md5sums = 7716009f7064bdae850d1464e33f455d
+ md5sums = 5546ca7925e090bf96e9bc39e7a3966b
+ md5sums = e5eba913001bd1818774214ba6b8d089
+ md5sums = 1d4da6032609e0c85decb7853f338eb3
+ md5sums = 2d450f35002c5da5f2591b59ab69a470
+ md5sums = e74e1b88af101a9e2091cee732b4025e
+ md5sums = 6c2f03bfc75a189cb73cba123696e442
+ md5sums = 906f46b391ac2d6e8b2c1d1cc501e122
+ md5sums = 482aee09364762cfa16bd7ece2af5c4b
+
+pkgname = tvtime-alsa
+
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 000000000000..434650f2e25d
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,75 @@
+# Maintainer: Raansu <Gero3977@gmail.com>
+# Contributor: Milos Pejovic (pejovic@gmail.com)
+
+pkgname=tvtime-alsa
+_tvtime_hgrev=111b28cca42d
+pkgver=1.0.2_p20110131
+pkgrel=2
+pkgdesc="tvtime with ALSA patches from Gentoo"
+depends=('libpng' 'libxml2' 'freetype2' 'libxss' 'libxinerama' 'libxv' 'libsm' 'libxxf86vm' 'alsa-lib')
+source=(http://tvtime-fixed.googlecode.com/files/${_tvtime_hgrev}.tar.bz2
+ tvtime-pic.patch
+ tvtime-1.0.2-xinerama.patch
+ tvtime-1.0.2_p20110131-libsupc++.patch
+ tvtime-1.0.2_p20110131-autotools.patch
+ tvtime-1.0.2_p20110131-gettext.patch
+ tvtime-libpng-1.5.patch
+ tvtime-1.0.2_p20110131-underlinking.patch
+ tvtime-1.0.2-alsamixer-r1.patch
+ tvtime-1.0.2-alsa-r1.patch
+ tvtime-1.0.2-alsa-fixes.patch)
+url='http://tvtime.sourceforge.net/'
+provides=('tvtime')
+conflicts=('tvtime')
+arch=('i686' 'x86_64')
+license=('GPL')
+build() {
+ cd $srcdir/tvtime-$_tvtime_hgrev
+
+ # Rename the desktop file
+ mv docs/net-tvtime.desktop docs/tvtime.desktop
+ sed -i -e "s/net-tvtime.desktop/tvtime.desktop/g" docs/Makefile.am
+
+ # use 'tvtime' for the application icon
+ sed -i -e "s/tvtime.png/tvtime/" docs/tvtime.desktop
+
+ # patch to adapt to PIC or __PIC__ for pic support
+ patch -Np1 -i "${startdir}/tvtime-pic.patch"
+
+ patch -Np1 -i "${startdir}/tvtime-1.0.2-xinerama.patch"
+
+ patch -Np1 -i "${startdir}/tvtime-1.0.2_p20110131-libsupc++.patch"
+
+ patch -Np1 -i "${startdir}/tvtime-1.0.2_p20110131-autotools.patch"
+ patch -Np1 -i "${startdir}/tvtime-1.0.2_p20110131-gettext.patch"
+ patch -Np1 -i "${startdir}/tvtime-libpng-1.5.patch"
+ patch -Np0 -i "${startdir}/tvtime-1.0.2_p20110131-underlinking.patch"
+
+ patch -Np1 -i "${startdir}/tvtime-1.0.2-alsa-r1.patch"
+ patch -Np1 -i "${startdir}/tvtime-1.0.2-alsamixer-r1.patch"
+ patch -Np1 -i "${startdir}/tvtime-1.0.2-alsa-fixes.patch"
+
+ autoreconf -i -f
+ ./configure --prefix=/usr --mandir=/usr/share/man --localstatedir=/var --sysconfdir=/etc
+ make
+}
+
+package() {
+ cd $srcdir/tvtime-$_tvtime_hgrev
+ make DESTDIR=$pkgdir install
+ install -D -m644 docs/html/default.tvtime.xml $pkgdir/usr/share/tvtime/default.tvtime.xml
+}
+
+md5sums=('3f68ec60da6cc0d73339fb4ccc1b4a04'
+ '4bc08a98c7cc134accb89aea3018c2f6'
+ '7716009f7064bdae850d1464e33f455d'
+ '5546ca7925e090bf96e9bc39e7a3966b'
+ 'e5eba913001bd1818774214ba6b8d089'
+ '1d4da6032609e0c85decb7853f338eb3'
+ '2d450f35002c5da5f2591b59ab69a470'
+ 'e74e1b88af101a9e2091cee732b4025e'
+ '6c2f03bfc75a189cb73cba123696e442'
+ '906f46b391ac2d6e8b2c1d1cc501e122'
+ '482aee09364762cfa16bd7ece2af5c4b')
+
+
diff --git a/tvtime-1.0.2-alsa-fixes.patch b/tvtime-1.0.2-alsa-fixes.patch
new file mode 100644
index 000000000000..b9f4351b2d4a
--- /dev/null
+++ b/tvtime-1.0.2-alsa-fixes.patch
@@ -0,0 +1,143 @@
+diff -Naur a/src/audiolib.c b/src/audiolib.c
+--- a/src/audiolib.c 2010-05-06 12:07:34.000000000 +0200
++++ b/src/audiolib.c 2010-05-06 12:08:06.000000000 +0200
+@@ -74,6 +74,7 @@
+ struct alsa_device *alsa_open(char *input, char *output, unsigned long format, int channels, unsigned int rate)
+ {
+ int result;
++ int rv;
+ struct alsa_device *dev = malloc(sizeof(struct alsa_device));
+
+ dev->fmt.format = format;
+@@ -93,17 +94,27 @@
+
+ // snd_pcm_nonblock( dev->playback, 1);
+
+- alsa_set_params(dev->playback, &dev->fmt, 0);
++ rv = alsa_set_params(dev->playback, &dev->fmt, 0);
++ if (rv == -1) {
++ snd_pcm_close(dev->playback);
++ return NULL;
++ }
+
+ if ((result = snd_pcm_open( &dev->capture, input, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK))<0)
+ {
++ snd_pcm_close(dev->playback);
+ free(dev);
+ return NULL;
+ }
+
+ // snd_pcm_nonblock(dev->playback, 1);
+
+- alsa_set_params(dev->capture, &dev->fmt, 1);
++ rv = alsa_set_params(dev->capture, &dev->fmt, 1);
++ if (rv == -1) {
++ snd_pcm_close(dev->playback);
++ snd_pcm_close(dev->capture);
++ return NULL;
++ }
+
+ return dev;
+ }
+@@ -212,8 +223,8 @@
+ 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);
++ printf("Broken configuration for this PCM: no configurations available\n");
++ return -1;
+ }
+
+
+@@ -223,18 +234,18 @@
+ err = snd_pcm_hw_params_set_access_mask(handle, params, mask);
+
+ if (err < 0) {
+- printf("Access type not available");
+- exit(EXIT_FAILURE);
++ printf("Access type not available\n");
++ return -1;
+ }
+ err = snd_pcm_hw_params_set_format(handle, params, fmt->format);
+ if (err < 0) {
+- printf("Sample format non available");
+- exit(EXIT_FAILURE);
++ printf("Sample format non available\n");
++ return -1;
+ }
+ err = snd_pcm_hw_params_set_channels(handle, params, fmt->channels);
+ if (err < 0) {
+- printf("Channels count non available");
+- exit(EXIT_FAILURE);
++ printf("Channels count non available\n");
++ return -1;
+ }
+
+ rate = fmt->rate;
+@@ -277,22 +288,22 @@
+ assert(err >= 0);
+ err = snd_pcm_hw_params(handle, params);
+ if (err < 0) {
+- printf("Unable to install hw params");
+- return -EINVAL;
++ printf("Unable to install hw params\n");
++ return -1;
+ }
+ 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;
++ printf("Can't use period equal to buffer size (%lu == %lu)\n", chunk_size, buffer_size);
++ return -1;
+ }
+
+ 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);
++ return -1;
+ }
+
+ err = snd_pcm_sw_params_set_sleep_min(handle, swparams, 0);
+@@ -331,8 +342,8 @@
+ assert(err >= 0);
+
+ if (snd_pcm_sw_params(handle, swparams) < 0) {
+- printf("unable to install sw params");
+- return -EINVAL;
++ printf("unable to install sw params\n");
++ return -1;
+ }
+
+ fmt->bits_per_sample = snd_pcm_format_physical_width(fmt->format);
+diff -Naur a/src/tvtime.c b/src/tvtime.c
+--- a/src/tvtime.c 2010-05-06 12:07:34.000000000 +0200
++++ b/src/tvtime.c 2010-05-06 12:08:06.000000000 +0200
+@@ -1184,6 +1184,7 @@
+ char prevloc[ 256 ];
+ char *empia_device;
+ int i;
++ int audio_state = 0;
+
+ ct = config_new();
+ if( !ct ) {
+@@ -2061,10 +2062,14 @@
+ session.
+ */
+
+- if (empia_device && videoinput_get_audio(vidin) == NULL) {
++ if (empia_device && audio_state == 0 && 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)) {
++ audio_state = 0;
++ printf("starting alsa transfer\n");
+ alsa_start_threaded_loop(videoinput_get_audio(vidin));
++ } else {
++ audio_state = -1;
+ }
+ }
+
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.
+ */
diff --git a/tvtime-1.0.2-alsamixer-r1.patch b/tvtime-1.0.2-alsamixer-r1.patch
new file mode 100644
index 000000000000..ab248b411cdd
--- /dev/null
+++ b/tvtime-1.0.2-alsamixer-r1.patch
@@ -0,0 +1,1165 @@
+Enable Alsamixer controls, bug 323797
+Patch from Fedora, via Ubuntu, rebased to our upstream
+
+diff -Naur tvtime-111b28cca42d.orig/configure.ac tvtime-111b28cca42d/configure.ac
+--- tvtime-111b28cca42d.orig/configure.ac 2011-08-14 11:52:43.404917552 +0200
++++ tvtime-111b28cca42d/configure.ac 2011-08-14 12:16:49.241866116 +0200
+@@ -73,30 +73,38 @@
+ dnl libxml2
+ dnl ---------------------------------------------
+ dnl Test for libxml2
+-
+ AC_PATH_PROG(LIBXML2_CONFIG,xml2-config,no)
+ if test "$LIBXML2_CONFIG" = "no" ; then
+ AC_MSG_ERROR(libxml2 needed and xml2-config not found)
+ else
+ XML2_LIBS="`$LIBXML2_CONFIG --libs`"
+ XML2_FLAG="`$LIBXML2_CONFIG --cflags`"
+- AC_DEFINE(HAVE_LIBXML2,,[LIBXML2 support])
++ AC_DEFINE(HAVE_LIBXML2,,[LIBXML2 support])
+ fi
+ AC_SUBST(XML2_LIBS)
+ AC_SUBST(XML2_FLAG)
+
++dnl ---------------------------------------------
++dnl libasound2
++dnl ---------------------------------------------
++dnl Test for ALSA
++AM_PATH_ALSA(1.0.9,
++ [ AC_DEFINE(HAVE_ALSA,1,[Define this if you have Alsa (libasound) installed]) ],
++ AC_MSG_RESULT(libasound needed and not found))
++AM_CONDITIONAL(HAVE_ALSA, test x"$no_alsa" != "yes")
++
+
+ dnl ---------------------------------------------
+ dnl asound
+ dnl ---------------------------------------------
+ dnl Test for libasound
+-AC_CHECK_LIB(asound, snd_pcm_open,
+- [ AC_CHECK_HEADER(alsa/asoundlib.h,
+- have_asound=yes
+- ASOUND_LIBS="-lasound",)], AC_MSG_ERROR(asound needed))
+-
+-AM_CONDITIONAL(HAVE_ASOUND, [test x"$have_asound" = "xyes"])
+-AC_SUBST(ASOUND_LIBS)
++dnl AC_CHECK_LIB(asound, snd_pcm_open,
++dnl [ AC_CHECK_HEADER(alsa/asoundlib.h,
++dnl have_asound=yes
++dnl ASOUND_LIBS="-lasound",)], AC_MSG_ERROR(asound needed))
++dnl
++dnl AM_CONDITIONAL(HAVE_ASOUND, [test x"$have_asound" = "xyes"])
++dnl AC_SUBST(ASOUND_LIBS)
+
+ dnl ---------------------------------------------
+ dnl check for gtk+-2.0
+diff -Naur tvtime-111b28cca42d.orig/docs/html/default.tvtime.xml tvtime-111b28cca42d/docs/html/default.tvtime.xml
+--- tvtime-111b28cca42d.orig/docs/html/default.tvtime.xml 2011-02-01 02:35:26.000000000 +0100
++++ tvtime-111b28cca42d/docs/html/default.tvtime.xml 2011-08-14 12:07:46.561885421 +0200
+@@ -116,13 +116,15 @@
+ <option name="VBIDevice" value="/dev/vbi0"/>
+
+ <!--
+- This sets the mixer device and channel to use. The format is device
+- name:channel name. Valid channels are:
++ This sets the mixer device and channel to use. The format for OSS
++ is device name:channel name. Valid OSS channels are:
+ vol, bass, treble, synth, pcm, speaker, line, mic, cd, mix, pcm2,
+ rec, igain, ogain, line1, line2, line3, dig1, dig2, dig3, phin,
+ phout, video, radio, monitor
++ The format for ALSA mixer is device/channel (e.g., "default/Line"
++ or "hw:0/CD")
+ -->
+- <option name="MixerDevice" value="/dev/mixer:line"/>
++ <option name="MixerDevice" value="default/Line"/>
+
+ <!--
+ This option enables 16:9 aspect ratio mode by default on startup.
+diff -Naur tvtime-111b28cca42d.orig/docs/man/en/tvtime.xml.5 tvtime-111b28cca42d/docs/man/en/tvtime.xml.5
+--- tvtime-111b28cca42d.orig/docs/man/en/tvtime.xml.5 2011-02-01 02:35:26.000000000 +0100
++++ tvtime-111b28cca42d/docs/man/en/tvtime.xml.5 2011-08-14 12:07:46.562885421 +0200
+@@ -234,7 +234,10 @@
+ .TP
+ <option name="MixerDevice" value="/dev/mixer:line"/>
+ This sets the mixer device and channel to use. The format is device
+-name:channel name. Valid channels are:
++name:channel name for OSS mixer (e.g., "/dev/mixer:Line") or device/channel
++for ALSA (e.g., "hw:0/CD").
++
++Valid OSS channels are:
+
+ .nh
+ .IR vol ", " bass ", " treble ", " synth ", " pcm ", " speaker ", "
+diff -Naur tvtime-111b28cca42d.orig/src/commands.c tvtime-111b28cca42d/src/commands.c
+--- tvtime-111b28cca42d.orig/src/commands.c 2011-02-01 02:35:26.000000000 +0100
++++ tvtime-111b28cca42d/src/commands.c 2011-08-14 12:07:46.555885420 +0200
+@@ -3012,10 +3012,10 @@
+ break;
+
+ case TVTIME_MIXER_TOGGLE_MUTE:
+- mixer_mute( !mixer_ismute() );
++ mixer->mute( !mixer->ismute() );
+
+ if( cmd->osd ) {
+- tvtime_osd_show_data_bar( cmd->osd, _("Volume"), (mixer_get_volume()) & 0xff );
++ tvtime_osd_show_data_bar( cmd->osd, _("Volume"), (mixer->get_volume()) & 0xff );
+ }
+ break;
+
+@@ -3029,9 +3029,9 @@
+ /* Check to see if an argument was passed, if so, use it. */
+ if (atoi(arg) > 0) {
+ int perc = atoi(arg);
+- volume = mixer_set_volume( ( (tvtime_cmd == TVTIME_MIXER_UP) ? perc : -perc ) );
++ volume = mixer->set_volume( ( (tvtime_cmd == TVTIME_MIXER_UP) ? perc : -perc ) );
+ } else {
+- volume = mixer_set_volume( ( (tvtime_cmd == TVTIME_MIXER_UP) ? 1 : -1 ) );
++ volume = mixer->set_volume( ( (tvtime_cmd == TVTIME_MIXER_UP) ? 1 : -1 ) );
+ }
+
+ if( cmd->osd ) {
+diff -Naur tvtime-111b28cca42d.orig/src/Makefile.am tvtime-111b28cca42d/src/Makefile.am
+--- tvtime-111b28cca42d.orig/src/Makefile.am 2011-08-14 11:56:09.243910228 +0200
++++ tvtime-111b28cca42d/src/Makefile.am 2011-08-14 12:14:09.128871820 +0200
+@@ -26,6 +26,11 @@
+ -DCONFDIR="\"$(pkgsysconfdir)\"" -DFIFODIR="\"$(tmpdir)\"" \
+ -D_LARGEFILE64_SOURCE -DLOCALEDIR="\"$(localedir)\""
+
++if HAVE_ALSA
++ALSA_SRCS = mixer-alsa.c
++else
++ALSA_SRCS =
++endif
+ COMMON_SRCS = mixer.c videoinput.c rtctimer.c leetft.c osdtools.c tvtimeconf.c \
+ pngoutput.c tvtimeosd.c input.c cpu_accel.c speedy.c pnginput.c \
+ deinterlace.c videotools.c attributes.h deinterlace.h leetft.h \
+@@ -37,7 +42,8 @@
+ 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 audiolib.h audiolib.c
++ copyfunctions.h copyfunctions.c alsa_stream.c audiolib.h audiolib.c \
++ mixer-oss.c $(ALSA_SRCS)
+
+ if ARCH_X86
+ DSCALER_SRCS = $(top_srcdir)/plugins/dscalerapi.h \
+@@ -72,9 +78,9 @@
+ tvtime_SOURCES = $(COMMON_SRCS) $(OUTPUT_SRCS) $(PLUGIN_SRCS) tvtime.c
+ tvtime_CFLAGS = $(TTF_CFLAGS) $(PNG_CFLAGS) $(OPT_CFLAGS) \
+ $(PLUGIN_CFLAGS) $(X11_CFLAGS) $(XML2_FLAG) \
+- $(FONT_CFLAGS) $(AM_CFLAGS)
++ $(FONT_CFLAGS) $(AM_CFLAGS) $(ALSA_CFLAGS)
+ tvtime_LDADD = $(TTF_LIBS) $(ZLIB_LIBS) $(PNG_LIBS) \
+- $(X11_LIBS) $(XML2_LIBS) $(ASOUND_LIBS) -lm -lsupc++ -lpthread -lasound
++ $(X11_LIBS) $(XML2_LIBS) $(ALSA_LIBS) -lm -lsupc++ -lpthread -lasound
+
+ tvtime_command_SOURCES = utils.h utils.c tvtimeconf.h tvtimeconf.c \
+ tvtime-command.c
+@@ -87,6 +93,6 @@
+ tvtime_scanner_SOURCES = utils.h utils.c videoinput.h videoinput.c \
+ tvtimeconf.h tvtimeconf.c station.h station.c tvtime-scanner.c \
+ mixer.h mixer.c
+-tvtime_scanner_CFLAGS = $(OPT_CFLAGS) $(XML2_FLAG) $(AM_CFLAGS)
+-tvtime_scanner_LDADD = $(ZLIB_LIBS) $(XML2_LIBS)
++tvtime_scanner_CFLAGS = $(OPT_CFLAGS) $(XML2_FLAG) $(ALSA_CFLAGS) $(AM_CFLAGS)
++tvtime_scanner_LDADD = $(ZLIB_LIBS) $(XML2_LIBS) $(ALSA_LIBS)
+
+diff -Naur tvtime-111b28cca42d.orig/src/mixer-alsa.c tvtime-111b28cca42d/src/mixer-alsa.c
+--- tvtime-111b28cca42d.orig/src/mixer-alsa.c 1970-01-01 01:00:00.000000000 +0100
++++ tvtime-111b28cca42d/src/mixer-alsa.c 2011-08-14 12:07:46.556885421 +0200
+@@ -0,0 +1,240 @@
++/**
++ * Copyright (C) 2006 Philipp Hahn <pmhahn@users.sourceforge.net>
++ *
++ * 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, 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 <sys/types.h>
++#include <string.h>
++#include <math.h>
++#include <alsa/asoundlib.h>
++#include "utils.h"
++#include "mixer.h"
++
++static const char alsa_core_devnames[] = "default";
++static char *card, *channel;
++static int muted = 0;
++static int mutecount = 0;
++static snd_mixer_t *handle = NULL;
++static snd_mixer_elem_t *elem = NULL;
++
++static long alsa_min, alsa_max, alsa_vol;
++
++static void alsa_open_mixer( void )
++{
++ int err;
++ static snd_mixer_selem_id_t *sid = NULL;
++ if ((err = snd_mixer_open (&handle, 0)) < 0) {
++ fprintf(stderr, "mixer: open error: %s\n", snd_strerror(err));
++ return;
++ }
++ if ((err = snd_mixer_attach (handle, card)) < 0) {
++ fprintf(stderr, "mixer: attach error: %s\n", snd_strerror(err));
++ goto error;
++ }
++ if ((err = snd_mixer_selem_register (handle, NULL, NULL)) < 0) {
++ fprintf(stderr, "mixer: register error: %s\n", snd_strerror(err));
++ goto error;
++ }
++ if ((err = snd_mixer_load (handle)) < 0) {
++ fprintf(stderr, "mixer: load error: %s\n", snd_strerror(err));
++ goto error;
++ }
++ snd_mixer_selem_id_malloc(&sid);
++ if (sid == NULL)
++ goto error;
++ snd_mixer_selem_id_set_name(sid, channel);
++ if (!(elem = snd_mixer_find_selem(handle, sid))) {
++ fprintf(stderr, "mixer: find error: %s\n", snd_strerror(err));
++ goto error;
++ }
++ if (!snd_mixer_selem_has_playback_volume(elem)) {
++ fprintf(stderr, "mixer: no playback\n");
++ goto error;
++ }
++ snd_mixer_selem_get_playback_volume_range(elem, &alsa_min, &alsa_max);
++ if ((alsa_max - alsa_min) <= 0) {
++ fprintf(stderr, "mixer: no valid playback range\n");
++ goto error;
++ }
++ snd_mixer_selem_id_free(sid);
++ return;
++
++error:
++ if (sid)
++ snd_mixer_selem_id_free(sid);
++ if (handle) {
++ snd_mixer_close(handle);
++ handle = NULL;
++ }
++ return;
++}
++
++/* Volume saved to file */
++static int alsa_get_unmute_volume( void )
++{
++ long val;
++ assert (elem);
++
++ if (snd_mixer_selem_is_playback_mono(elem)) {
++ snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_MONO, &val);
++ return val;
++ } else {
++ int c, n = 0;
++ long sum = 0;
++ for (c = 0; c <= SND_MIXER_SCHN_LAST; c++) {
++ if (snd_mixer_selem_has_playback_channel(elem, c)) {
++ snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &val);
++ sum += val;
++ n++;
++ }
++ }
++ if (! n) {
++ return 0;
++ }
++
++ val = sum / n;
++ sum = (long)((double)(alsa_vol * (alsa_max - alsa_min)) / 100. + 0.5);
++
++ if (sum != val) {
++ alsa_vol = (long)(((val * 100.) / (alsa_max - alsa_min)) + 0.5);
++ }
++ return alsa_vol;
++ }
++}
++
++static int alsa_get_volume( void )
++{
++ if (muted)
++ return 0;
++ else
++ return alsa_get_unmute_volume();
++}
++
++static int alsa_set_volume( int percentdiff )
++{
++ long volume;
++
++ alsa_get_volume();
++
++ alsa_vol += percentdiff;
++ if( alsa_vol > 100 ) alsa_vol = 100;
++ if( alsa_vol < 0 ) alsa_vol = 0;
++
++ volume = (long)((alsa_vol * (alsa_max - alsa_min) / 100.) + 0.5);
++
++ snd_mixer_selem_set_playback_volume_all(elem, volume + alsa_min);
++ snd_mixer_selem_set_playback_switch_all(elem, 1);
++ muted = 0;
++ mutecount = 0;
++
++ return alsa_vol;
++}
++
++static void alsa_mute( int mute )
++{
++ /**
++ * Make sure that if multiple users mute the card,
++ * we only honour the last one.
++ */
++ if( !mute && mutecount ) mutecount--;
++ if( mutecount ) return;
++
++ if( mute ) {
++ mutecount++;
++ muted = 1;
++ if (snd_mixer_selem_has_playback_switch(elem))
++ snd_mixer_selem_set_playback_switch_all(elem, 0);
++ else
++ fprintf(stderr, "mixer: mute not implemented\n");
++ } else {
++ muted = 0;
++ if (snd_mixer_selem_has_playback_switch(elem))
++ snd_mixer_selem_set_playback_switch_all(elem, 1);
++ else
++ fprintf(stderr, "mixer: mute not implemented\n");
++ }
++}
++
++static int alsa_ismute( void )
++{
++ return muted;
++}
++
++static int alsa_set_device( const char *devname )
++{
++ int i;
++
++ if (card) free(card);
++ card = strdup( devname );
++ if( !card ) return -1;
++
++ i = strcspn( card, "/" );
++ if( i == strlen( card ) ) {
++ channel = "Line";
++ } else {
++ card[i] = 0;
++ channel = card + i + 1;
++ }
++ alsa_open_mixer();
++ if (!handle) {
++ fprintf( stderr, "mixer: Can't open mixer %s, "
++ "mixer volume and mute unavailable.\n", card );
++ return -1;
++ }
++ return 0;
++}
++
++static void alsa_set_state( int ismuted, int unmute_volume )
++{
++ /**
++ * 1. we come back unmuted: Don't touch anything
++ * 2. we don't have a saved volume: Don't touch anything
++ * 3. we come back muted and we have a saved volume:
++ * - if tvtime muted it, unmute to old volume
++ * - if user did it, remember that we're muted and old volume
++ */
++ if( alsa_get_volume() == 0 && unmute_volume > 0 ) {
++ snd_mixer_selem_set_playback_volume_all(elem, unmute_volume);
++ muted = 1;
++
++ if( !ismuted ) {
++ alsa_mute( 0 );
++ }
++ }
++}
++
++static void alsa_close_device( void )
++{
++ elem = NULL;
++ if (handle)
++ snd_mixer_close(handle);
++ handle = NULL;
++ muted = 0;
++ mutecount = 0;
++}
++
++struct mixer alsa_mixer = {
++ .set_device = alsa_set_device,
++ .set_state = alsa_set_state,
++ .get_volume = alsa_get_volume,
++ .get_unmute_volume = alsa_get_unmute_volume,
++ .set_volume = alsa_set_volume,
++ .mute = alsa_mute,
++ .ismute = alsa_ismute,
++ .close_device = alsa_close_device,
++};
++// vim: ts=4 sw=4 et foldmethod=marker
+diff -Naur tvtime-111b28cca42d.orig/src/mixer.c tvtime-111b28cca42d/src/mixer.c
+--- tvtime-111b28cca42d.orig/src/mixer.c 2011-02-01 02:35:26.000000000 +0100
++++ tvtime-111b28cca42d/src/mixer.c 2011-08-14 12:07:46.557885421 +0200
+@@ -19,230 +19,104 @@
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+-#include <stdio.h>
+-#include <fcntl.h>
+-#include <unistd.h>
+-#include <sys/types.h>
+-#include <sys/stat.h>
+-#include <sys/ioctl.h>
+-#include <sys/soundcard.h>
+-#include <sys/mman.h>
+-#include <string.h>
+-#include "utils.h"
+ #include "mixer.h"
+
+-static char *mixer_device = "/dev/mixer";
+-static int saved_volume = (50 << 8 & 0xFF00) | (50 & 0x00FF);
+-static int mixer_channel = SOUND_MIXER_LINE;
+-static int mixer_dev_mask = 1 << SOUND_MIXER_LINE;
+-static int muted = 0;
+-static int mutecount = 0;
+-static int fd = -1;
+-
+-int mixer_get_volume( void )
+-{
+- int v, cmd, devs;
+- int curvol = 0;
+-
+- if( fd < 0 ) fd = open( mixer_device, O_RDONLY );
+- if( fd != -1 ) {
+-
+- ioctl( fd, SOUND_MIXER_READ_DEVMASK, &devs );
+- if( devs & mixer_dev_mask ) {
+- cmd = MIXER_READ( mixer_channel );
+- } else {
+- return curvol;
+- }
+-
+- ioctl( fd, cmd, &v );
+- curvol = ( v & 0xFF00 ) >> 8;
+- }
+-
+- return curvol;
++/**
++ * Sets the mixer device and channel.
++ */
++static int null_set_device( const char *devname )
++{
++ return 0;
+ }
+
+-int mixer_get_unmute_volume( void )
++/**
++ * Sets the initial state of the mixer device.
++ */
++static void null_set_state( int ismuted, int unmute_volume )
+ {
+- if( muted ) {
+- return saved_volume;
+- } else {
+- int v, cmd, devs;
+-
+- if( fd < 0 ) fd = open( mixer_device, O_RDONLY );
+- if( fd != -1 ) {
+-
+- ioctl( fd, SOUND_MIXER_READ_DEVMASK, &devs );
+- if( devs & mixer_dev_mask ) {
+- cmd = MIXER_READ( mixer_channel );
+- } else {
+- return -1;
+- }
+-
+- ioctl( fd, cmd, &v );
+- return v;
+- }
+- }
+-
+- return -1;
+ }
+
+-int mixer_set_volume( int percentdiff )
++/**
++ * Returns the current volume setting.
++ */
++static int null_get_volume( void )
+ {
+- int v, cmd, devs, levelpercentage;
+-
+- levelpercentage = mixer_get_volume();
+-
+- levelpercentage += percentdiff;
+- if( levelpercentage > 100 ) levelpercentage = 100;
+- if( levelpercentage < 0 ) levelpercentage = 0;
+-
+- if( fd < 0 ) fd = open( mixer_device, O_RDONLY );
+- if( fd != -1 ) {
+- ioctl( fd, SOUND_MIXER_READ_DEVMASK, &devs );
+- if( devs & mixer_dev_mask ) {
+- cmd = MIXER_WRITE( mixer_channel );
+- } else {
+- return 0;
+- }
+-
+- v = ( levelpercentage << 8 ) | levelpercentage;
+- ioctl( fd, cmd, &v );
+- muted = 0;
+- mutecount = 0;
+- return v;
+- }
+-
+ return 0;
+ }
+
+-void mixer_mute( int mute )
++/**
++ * Returns the volume that would be used to restore the unmute state.
++ */
++static int null_get_unmute_volume( void )
+ {
+- int v, cmd, devs;
+-
+- /**
+- * Make sure that if multiple users mute the card,
+- * we only honour the last one.
+- */
+- if( !mute && mutecount ) mutecount--;
+- if( mutecount ) return;
+-
+- if( fd < 0 ) fd = open( mixer_device, O_RDONLY );
+-
+- if( mute ) {
+- mutecount++;
+- if( fd != -1 ) {
+-
+- /* Save volume */
+- ioctl( fd, SOUND_MIXER_READ_DEVMASK, &devs );
+- if( devs & mixer_dev_mask ) {
+- cmd = MIXER_READ( mixer_channel );
+- } else {
+- return;
+- }
+-
+- ioctl( fd,cmd,&v );
+- saved_volume = v;
+-
+- /* Now set volume to 0 */
+- ioctl( fd, SOUND_MIXER_READ_DEVMASK, &devs );
+- if( devs & mixer_dev_mask ) {
+- cmd = MIXER_WRITE( mixer_channel );
+- } else {
+- return;
+- }
+-
+- v = 0;
+- ioctl( fd, cmd, &v );
+-
+- muted = 1;
+- return;
+- }
+- } else {
+- if( fd != -1 ) {
+- ioctl( fd, SOUND_MIXER_READ_DEVMASK, &devs );
+- if( devs & mixer_dev_mask ) {
+- cmd = MIXER_WRITE( mixer_channel );
+- } else {
+- return;
+- }
+-
+- v = saved_volume;
+- ioctl( fd, cmd, &v );
+- muted = 0;
+- return;
+- }
+- }
++ return 0;
+ }
+
+-int mixer_ismute( void )
++/**
++ * Tunes the relative volume.
++ */
++static int null_set_volume( int percentdiff )
+ {
+- return muted;
++ return 0;
+ }
+
+-static char *oss_core_devnames[] = SOUND_DEVICE_NAMES;
+-
+-void mixer_set_device( const char *devname )
++/**
++ * Sets the mute state.
++ */
++static void null_mute( int mute )
+ {
+- const char *channame;
+- int found = 0;
+- int i;
+-
+- mixer_device = strdup( devname );
+- if( !mixer_device ) return;
+-
+- i = strcspn( mixer_device, ":" );
+- if( i == strlen( mixer_device ) ) {
+- channame = "line";
+- } else {
+- mixer_device[ i ] = 0;
+- channame = mixer_device + i + 1;
+- }
+- if( !file_is_openable_for_read( mixer_device ) ) {
+- fprintf( stderr, "mixer: Can't open device %s, "
+- "mixer volume and mute unavailable.\n", mixer_device );
+- }
+-
+- mixer_channel = SOUND_MIXER_LINE;
+- for( i = 0; i < SOUND_MIXER_NRDEVICES; i++ ) {
+- if( !strcasecmp( channame, oss_core_devnames[ i ] ) ) {
+- mixer_channel = i;
+- found = 1;
+- break;
+- }
+- }
+- if( !found ) {
+- fprintf( stderr, "mixer: No such mixer channel '%s', using channel 'line'.\n", channame );
+- }
+- mixer_dev_mask = 1 << mixer_channel;
+ }
+
+-void mixer_set_state( int ismuted, int unmute_volume )
++/**
++ * Returns true if the mixer is muted.
++ */
++static int null_ismute( void )
+ {
+- /**
+- * 1. we come back unmuted: Don't touch anything
+- * 2. we don't have a saved volume: Don't touch anything
+- * 3. we come back muted and we have a saved volume:
+- * - if tvtime muted it, unmute to old volume
+- * - if user did it, remember that we're muted and old volume
+- */
+- if( mixer_get_volume() == 0 && unmute_volume > 0 ) {
+- saved_volume = unmute_volume;
+- muted = 1;
+-
+- if( !ismuted ) {
+- mixer_mute( 0 );
+- }
+- }
++ return 0;
+ }
+
+-void mixer_close_device( void )
++/**
++ * Closes the mixer device if it is open.
++ */
++static void null_close_device( void )
+ {
+- if( fd >= 0 ) close( fd );
+- saved_volume = (50 << 8 & 0xFF00) | (50 & 0x00FF);
+- mixer_channel = SOUND_MIXER_LINE;
+- mixer_dev_mask = 1 << SOUND_MIXER_LINE;
+- muted = 0;
+- mutecount = 0;
+- fd = -1;
+ }
+
++/* The null device, which always works. */
++static struct mixer null_mixer = {
++ .set_device = null_set_device,
++ .set_state = null_set_state,
++ .get_volume = null_get_volume,
++ .get_unmute_volume = null_get_unmute_volume,
++ .set_volume = null_set_volume,
++ .mute = null_mute,
++ .ismute = null_ismute,
++ .close_device = null_close_device,
++};
++
++/* List of all available access methods.
++ * Uses weak symbols: NULL is not linked in. */
++static struct mixer *mixers[] = {
++ &alsa_mixer,
++ &oss_mixer,
++ &null_mixer /* LAST */
++};
++/* The actual access method. */
++struct mixer *mixer = &null_mixer;
++
++/**
++ * Sets the mixer device and channel.
++ * Try each access method until one succeeds.
++ */
++void mixer_set_device( const char *devname )
++{
++ int i;
++ mixer->close_device();
++ for (i = 0; i < sizeof(mixers)/sizeof(mixers[0]); i++) {
++ mixer = mixers[i];
++ if (!mixer)
++ continue;
++ if (mixer->set_device(devname) == 0)
++ break;
++ }
++}
+diff -Naur tvtime-111b28cca42d.orig/src/mixer.h tvtime-111b28cca42d/src/mixer.h
+--- tvtime-111b28cca42d.orig/src/mixer.h 2011-02-01 02:35:26.000000000 +0100
++++ tvtime-111b28cca42d/src/mixer.h 2011-08-14 12:07:46.557885421 +0200
+@@ -27,45 +27,58 @@
+ #endif
+
+ /**
+- * Sets the mixer device and channel. The device name is of the form
+- * devicename:channelname. The default is /dev/mixer:line.
++ * Sets the mixer device and channel.
++ * All interfaces are scanned until one succeeds.
+ */
+ void mixer_set_device( const char *devname );
+
++struct mixer {
++/**
++ * Sets the mixer device and channel.
++ */
++int (* set_device)( const char *devname );
++
+ /**
+ * Sets the initial state of the mixer device.
+ */
+-void mixer_set_state( int ismuted, int unmute_volume );
++void (* set_state)( int ismuted, int unmute_volume );
+
+ /**
+ * Returns the current volume setting.
+ */
+-int mixer_get_volume( void );
++int (* get_volume)( void );
+
+ /**
+ * Returns the volume that would be used to restore the unmute state.
+ */
+-int mixer_get_unmute_volume( void );
++int (* get_unmute_volume)( void );
+
+ /**
+ * Tunes the relative volume.
+ */
+-int mixer_set_volume( int percentdiff );
++int (* set_volume)( int percentdiff );
+
+ /**
+ * Sets the mute state.
+ */
+-void mixer_mute( int mute );
++void (* mute)( int mute );
+
+ /**
+ * Returns true if the mixer is muted.
+ */
+-int mixer_ismute( void );
++int (* ismute)( void );
+
+ /**
+ * Closes the mixer device if it is open.
+ */
+-void mixer_close_device( void );
++void (* close_device)( void );
++};
++
++#pragma weak alsa_mixer
++extern struct mixer alsa_mixer;
++#pragma weak oss_mixer
++extern struct mixer oss_mixer;
++extern struct mixer *mixer;
+
+ #ifdef __cplusplus
+ };
+diff -Naur tvtime-111b28cca42d.orig/src/mixer-oss.c tvtime-111b28cca42d/src/mixer-oss.c
+--- tvtime-111b28cca42d.orig/src/mixer-oss.c 1970-01-01 01:00:00.000000000 +0100
++++ tvtime-111b28cca42d/src/mixer-oss.c 2011-08-14 12:07:46.558885421 +0200
+@@ -0,0 +1,261 @@
++/**
++ * Copyright (C) 2002, 2003 Doug Bell <drbell@users.sourceforge.net>
++ *
++ * Some mixer routines from mplayer, http://mplayer.sourceforge.net.
++ * Copyright (C) 2000-2002. by A'rpi/ESP-team & others
++ *
++ * 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, 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 <fcntl.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/ioctl.h>
++#include <sys/soundcard.h>
++#include <sys/mman.h>
++#include <string.h>
++#include "utils.h"
++#include "mixer.h"
++
++static char *mixer_device = "/dev/mixer";
++static int saved_volume = (50 << 8 & 0xFF00) | (50 & 0x00FF);
++static int mixer_channel = SOUND_MIXER_LINE;
++static int mixer_dev_mask = 1 << SOUND_MIXER_LINE;
++static int muted = 0;
++static int mutecount = 0;
++static int fd = -1;
++
++static int oss_get_volume( void )
++{
++ int v, cmd, devs;
++ int curvol = 0;
++
++ if( fd < 0 ) fd = open( mixer_device, O_RDONLY );
++ if( fd != -1 ) {
++
++ ioctl( fd, SOUND_MIXER_READ_DEVMASK, &devs );
++ if( devs & mixer_dev_mask ) {
++ cmd = MIXER_READ( mixer_channel );
++ } else {
++ return curvol;
++ }
++
++ ioctl( fd, cmd, &v );
++ curvol = ( v & 0xFF00 ) >> 8;
++ }
++
++ return curvol;
++}
++
++static int oss_get_unmute_volume( void )
++{
++ if( muted ) {
++ return saved_volume;
++ } else {
++ int v, cmd, devs;
++
++ if( fd < 0 ) fd = open( mixer_device, O_RDONLY );
++ if( fd != -1 ) {
++
++ ioctl( fd, SOUND_MIXER_READ_DEVMASK, &devs );
++ if( devs & mixer_dev_mask ) {
++ cmd = MIXER_READ( mixer_channel );
++ } else {
++ return -1;
++ }
++
++ ioctl( fd, cmd, &v );
++ return v;
++ }
++ }
++
++ return -1;
++}
++
++static int oss_set_volume( int percentdiff )
++{
++ int v, cmd, devs, levelpercentage;
++
++ levelpercentage = oss_get_volume();
++
++ levelpercentage += percentdiff;
++ if( levelpercentage > 100 ) levelpercentage = 100;
++ if( levelpercentage < 0 ) levelpercentage = 0;
++
++ if( fd < 0 ) fd = open( mixer_device, O_RDONLY );
++ if( fd != -1 ) {
++ ioctl( fd, SOUND_MIXER_READ_DEVMASK, &devs );
++ if( devs & mixer_dev_mask ) {
++ cmd = MIXER_WRITE( mixer_channel );
++ } else {
++ return 0;
++ }
++
++ v = ( levelpercentage << 8 ) | levelpercentage;
++ ioctl( fd, cmd, &v );
++ muted = 0;
++ mutecount = 0;
++ return v;
++ }
++
++ return 0;
++}
++
++static void oss_mute( int mute )
++{
++ int v, cmd, devs;
++
++ /**
++ * Make sure that if multiple users mute the card,
++ * we only honour the last one.
++ */
++ if( !mute && mutecount ) mutecount--;
++ if( mutecount ) return;
++
++ if( fd < 0 ) fd = open( mixer_device, O_RDONLY );
++
++ if( mute ) {
++ mutecount++;
++ if( fd != -1 ) {
++
++ /* Save volume */
++ ioctl( fd, SOUND_MIXER_READ_DEVMASK, &devs );
++ if( devs & mixer_dev_mask ) {
++ cmd = MIXER_READ( mixer_channel );
++ } else {
++ return;
++ }
++
++ ioctl( fd,cmd,&v );
++ saved_volume = v;
++
++ /* Now set volume to 0 */
++ ioctl( fd, SOUND_MIXER_READ_DEVMASK, &devs );
++ if( devs & mixer_dev_mask ) {
++ cmd = MIXER_WRITE( mixer_channel );
++ } else {
++ return;
++ }
++
++ v = 0;
++ ioctl( fd, cmd, &v );
++
++ muted = 1;
++ return;
++ }
++ } else {
++ if( fd != -1 ) {
++ ioctl( fd, SOUND_MIXER_READ_DEVMASK, &devs );
++ if( devs & mixer_dev_mask ) {
++ cmd = MIXER_WRITE( mixer_channel );
++ } else {
++ return;
++ }
++
++ v = saved_volume;
++ ioctl( fd, cmd, &v );
++ muted = 0;
++ return;
++ }
++ }
++}
++
++static int oss_ismute( void )
++{
++ return muted;
++}
++
++static char *oss_core_devnames[] = SOUND_DEVICE_NAMES;
++
++static int oss_set_device( const char *devname )
++{
++ const char *channame;
++ int found = 0;
++ int i;
++
++ mixer_device = strdup( devname );
++ if( !mixer_device ) return -1;
++
++ i = strcspn( mixer_device, ":" );
++ if( i == strlen( mixer_device ) ) {
++ channame = "line";
++ } else {
++ mixer_device[ i ] = 0;
++ channame = mixer_device + i + 1;
++ }
++ if( !file_is_openable_for_read( mixer_device ) ) {
++ fprintf( stderr, "mixer: Can't open device %s, "
++ "mixer volume and mute unavailable.\n", mixer_device );
++ return -1;
++ }
++
++ mixer_channel = SOUND_MIXER_LINE;
++ for( i = 0; i < SOUND_MIXER_NRDEVICES; i++ ) {
++ if( !strcasecmp( channame, oss_core_devnames[ i ] ) ) {
++ mixer_channel = i;
++ found = 1;
++ break;
++ }
++ }
++ if( !found ) {
++ fprintf( stderr, "mixer: No such mixer channel '%s', using channel 'line'.\n", channame );
++ return -1;
++ }
++ mixer_dev_mask = 1 << mixer_channel;
++ return 0;
++}
++
++static void oss_set_state( int ismuted, int unmute_volume )
++{
++ /**
++ * 1. we come back unmuted: Don't touch anything
++ * 2. we don't have a saved volume: Don't touch anything
++ * 3. we come back muted and we have a saved volume:
++ * - if tvtime muted it, unmute to old volume
++ * - if user did it, remember that we're muted and old volume
++ */
++ if( oss_get_volume() == 0 && unmute_volume > 0 ) {
++ saved_volume = unmute_volume;
++ muted = 1;
++
++ if( !ismuted ) {
++ oss_mute( 0 );
++ }
++ }
++}
++
++static void oss_close_device( void )
++{
++ if( fd >= 0 ) close( fd );
++ saved_volume = (50 << 8 & 0xFF00) | (50 & 0x00FF);
++ mixer_channel = SOUND_MIXER_LINE;
++ mixer_dev_mask = 1 << SOUND_MIXER_LINE;
++ muted = 0;
++ mutecount = 0;
++ fd = -1;
++}
++
++struct mixer oss_mixer = {
++ .set_device = oss_set_device,
++ .set_state = oss_set_state,
++ .get_volume = oss_get_volume,
++ .get_unmute_volume = oss_get_unmute_volume,
++ .set_volume = oss_set_volume,
++ .mute = oss_mute,
++ .ismute = oss_ismute,
++ .close_device = oss_close_device,
++};
+diff -Naur tvtime-111b28cca42d.orig/src/tvtime.c tvtime-111b28cca42d/src/tvtime.c
+--- tvtime-111b28cca42d.orig/src/tvtime.c 2011-08-14 11:56:35.443909297 +0200
++++ tvtime-111b28cca42d/src/tvtime.c 2011-08-14 12:07:46.559885421 +0200
+@@ -1430,7 +1430,7 @@
+
+ /* Set the mixer device. */
+ mixer_set_device( config_get_mixer_device( ct ) );
+- mixer_set_state( config_get_muted( ct ), config_get_unmute_volume( ct ) );
++ mixer->set_state( config_get_muted( ct ), config_get_unmute_volume( ct ) );
+
+ /* Setup OSD stuff. */
+ pixel_aspect = ( (double) width ) /
+@@ -2583,14 +2583,14 @@
+ snprintf( number, 4, "%d", quiet_screenshots );
+ config_save( ct, "QuietScreenshots", number );
+
+- snprintf( number, 6, "%d", mixer_get_unmute_volume() );
++ snprintf( number, 6, "%d", mixer->get_unmute_volume() );
+ config_save( ct, "UnmuteVolume", number );
+
+- snprintf( number, 4, "%d", mixer_ismute() );
++ snprintf( number, 4, "%d", mixer->ismute() );
+ config_save( ct, "Muted", number );
+
+ if( config_get_mute_on_exit( ct ) ) {
+- mixer_mute( 1 );
++ mixer->mute( 1 );
+ }
+
+ if( vidin ) {
+@@ -2627,7 +2627,7 @@
+ if( osd ) {
+ tvtime_osd_delete( osd );
+ }
+- mixer_close_device();
++ mixer->close_device();
+
+ /* Free temporary memory. */
+ free( colourbars );
+diff -Naur tvtime-111b28cca42d.orig/src/tvtimeconf.c tvtime-111b28cca42d/src/tvtimeconf.c
+--- tvtime-111b28cca42d.orig/src/tvtimeconf.c 2011-02-01 02:35:26.000000000 +0100
++++ tvtime-111b28cca42d/src/tvtimeconf.c 2011-08-14 12:07:46.562885421 +0200
+@@ -643,9 +643,11 @@
+ lfputs( _(" -l, --xmltvlanguage=LANG Use XMLTV data in given language, if available.\n"), stderr );
+ lfputs( _(" -v, --verbose Print debugging messages to stderr.\n"), stderr );
+ lfputs( _(" -X, --display=DISPLAY Use the given X display to connect to.\n"), stderr );
+- lfputs( _(" -x, --mixer=DEVICE[:CH] The mixer device and channel to control.\n"
+- " (defaults to /dev/mixer:line)\n\n"
+- " Valid channels are:\n"
++ lfputs( _(" -x, --mixer=<DEVICE[:CH]>|<DEVICE/CH>\n"
++ " The mixer device and channel to control. The first\n"
++ " variant sets the OSS mixer the second one ALSA.\n"
++ " (defaults to default/Line)\n\n"
++ " Valid channels for OSS are:\n"
+ " vol, bass, treble, synth, pcm, speaker, line,\n"
+ " mic, cd, mix, pcm2, rec, igain, ogain, line1,\n"
+ " line2, line3, dig1, dig2, dig3, phin, phout,\n"
+@@ -691,9 +693,11 @@
+ lfputs( _(" -R, --priority=PRI Sets the process priority to run tvtime at.\n"), stderr );
+ lfputs( _(" -t, --xmltv=FILE Read XMLTV listings from the given file.\n"), stderr );
+ lfputs( _(" -l, --xmltvlanguage=LANG Use XMLTV data in given language, if available.\n"), stderr );
+- lfputs( _(" -x, --mixer=DEVICE[:CH] The mixer device and channel to control.\n"
+- " (defaults to /dev/mixer:line)\n\n"
+- " Valid channels are:\n"
++ lfputs( _(" -x, --mixer=<DEVICE[:CH]>|<DEVICE/CH>\n"
++ " The mixer device and channel to control. The first\n"
++ " variant sets the OSS mixer the second one ALSA.\n"
++ " (defaults to default/Line)\n\n"
++ " Valid channels for OSS are:\n"
+ " vol, bass, treble, synth, pcm, speaker, line,\n"
+ " mic, cd, mix, pcm2, rec, igain, ogain, line1,\n"
+ " line2, line3, dig1, dig2, dig3, phin, phout,\n"
+@@ -786,7 +790,7 @@
+
+ ct->uid = getuid();
+
+- ct->mixerdev = strdup( "/dev/mixer:line" );
++ ct->mixerdev = strdup( "default/Line" );
+
+ ct->deinterlace_method = strdup( "GreedyH" );
+ ct->check_freq_present = 1;
+diff -Naur tvtime-111b28cca42d.orig/src/videoinput.c tvtime-111b28cca42d/src/videoinput.c
+--- tvtime-111b28cca42d.orig/src/videoinput.c 2011-08-14 12:03:39.783894207 +0200
++++ tvtime-111b28cca42d/src/videoinput.c 2011-08-14 12:07:46.560885421 +0200
+@@ -779,7 +779,7 @@
+ }
+
+ vidin->change_muted = 1;
+- mixer_mute( 1 );
++ mixer->mute( 1 );
+ videoinput_do_mute( vidin, vidin->user_muted || vidin->change_muted );
+ vidin->cur_tuner_state = TUNER_STATE_SIGNAL_DETECTED;
+ vidin->signal_acquire_wait = SIGNAL_ACQUIRE_DELAY;
+@@ -950,7 +950,7 @@
+ if( vidin->change_muted ) {
+ vidin->change_muted = 0;
+ videoinput_do_mute( vidin, vidin->user_muted || vidin->change_muted );
+- mixer_mute( 0 );
++ mixer->mute( 0 );
+ }
+ break;
+ }
+@@ -961,7 +961,7 @@
+ vidin->cur_tuner_state = TUNER_STATE_SIGNAL_LOST;
+ vidin->signal_recover_wait = SIGNAL_RECOVER_DELAY;
+ vidin->change_muted = 1;
+- mixer_mute( 1 );
++ mixer->mute( 1 );
+ videoinput_do_mute( vidin, vidin->user_muted || vidin->change_muted );
+ case TUNER_STATE_SIGNAL_LOST:
+ if( vidin->signal_recover_wait ) {
diff --git a/tvtime-1.0.2-xinerama.patch b/tvtime-1.0.2-xinerama.patch
new file mode 100644
index 000000000000..0964d055768d
--- /dev/null
+++ b/tvtime-1.0.2-xinerama.patch
@@ -0,0 +1,32 @@
+Index: tvtime-1.0.2/configure.ac
+===================================================================
+--- tvtime-1.0.2.orig/configure.ac
++++ tvtime-1.0.2/configure.ac
+@@ -99,6 +99,8 @@ dnl ------------------------------------
+ dnl check for X11, Xv and XF86VidModeExtension
+ dnl ---------------------------------------------
+ AC_PATH_XTRA
++AC_ARG_WITH([xinerama],
++ [AS_HELP_STRING([--without-xinerama], [Disable Xinerama extension support (default: check)])])
+ if test x"$no_x" != x"yes"; then
+ dnl check for Xshm
+ AC_CHECK_LIB([Xext],[XShmCreateImage],
+@@ -112,11 +114,13 @@ if test x"$no_x" != x"yes"; then
+ X11_LIBS="$X11_LIBS -lXv"],,
+ [$X_PRE_LIBS $X_LIBS -lX11 $X_EXTRA_LIBS -lXext])
+
+- dnl check for Xinerama
+- AC_CHECK_LIB([Xinerama],[XineramaQueryScreens],
+- [AC_DEFINE([HAVE_XINERAMA],,[Xinerama support])
+- X11_LIBS="$X11_LIBS -lXinerama"],,
+- [$X_PRE_LIBS $X_LIBS -lX11 $X_EXTRA_LIBS -lXext])
++ if test "x$with_xinerama" != "xno"; then
++ dnl check for Xinerama
++ AC_CHECK_LIB([Xinerama],[XineramaQueryScreens],
++ [AC_DEFINE([HAVE_XINERAMA],,[Xinerama support])
++ X11_LIBS="$X11_LIBS -lXinerama"],,
++ [$X_PRE_LIBS $X_LIBS -lX11 $X_EXTRA_LIBS -lXext])
++ fi
+
+ dnl check for XTest
+ AC_CHECK_LIB([Xtst],[XTestFakeKeyEvent],
diff --git a/tvtime-1.0.2_p20110131-autotools.patch b/tvtime-1.0.2_p20110131-autotools.patch
new file mode 100644
index 000000000000..81afa786afc1
--- /dev/null
+++ b/tvtime-1.0.2_p20110131-autotools.patch
@@ -0,0 +1,69 @@
+diff -Naur tvtime.orig/configure.ac tvtime/configure.ac
+--- tvtime.orig/configure.ac 2011-02-01 02:35:26.000000000 +0100
++++ tvtime/configure.ac 2011-05-29 21:45:16.825993007 +0200
+@@ -10,6 +10,7 @@
+
+ # Check for compilers.
+ AC_PROG_CC
++AM_PROG_CC_C_O
+ AC_CHECK_PROG(found_cc, "$CC", yes, no)
+ test "x$found_cc" = "xyes" || exit 1
+
+@@ -18,7 +19,6 @@
+ test "x$found_cxx" = "xyes" || exit 1
+
+ # Check for libtool.
+-AC_PROG_LIBTOOL
+
+ # Checks for header files.
+ AC_HEADER_STDC
+@@ -67,10 +67,7 @@
+ dnl freetype
+ dnl ---------------------------------------------
+ dnl Test for freetype
+-AC_PATH_PROG(FREETYPE_CONFIG, freetype-config, no)
+-if test "$FREETYPE_CONFIG" = "no" ; then
+- AC_MSG_ERROR(freetype2 needed and freetype-config not found)
+-fi
++PKG_CHECK_MODULES([TTF], [freetype2])
+
+ dnl ---------------------------------------------
+ dnl libxml2
+diff -Naur tvtime.orig/src/Makefile.am tvtime/src/Makefile.am
+--- tvtime.orig/src/Makefile.am 2011-02-01 02:35:26.000000000 +0100
++++ tvtime/src/Makefile.am 2011-05-29 21:42:32.156993111 +0200
+@@ -19,9 +19,6 @@
+ tmpdir = /tmp
+ localedir = $(datadir)/locale
+
+-TTF_CFLAGS = `$(FREETYPE_CONFIG) --cflags`
+-TTF_LIBS = `$(FREETYPE_CONFIG) --libs`
+-
+ # Set the following if you want to specify an additional font directory
+ # FONT_CFLAGS = -DFONTDIR='/usr/share/fonts/truetype/freefont/'
+
+@@ -76,20 +73,20 @@
+ 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) \
++tvtime_LDADD = $(TTF_LIBS) $(ZLIB_LIBS) $(PNG_LIBS) \
+ $(X11_LIBS) $(XML2_LIBS) $(ASOUND_LIBS) -lm -lsupc++
+
+ tvtime_command_SOURCES = utils.h utils.c tvtimeconf.h tvtimeconf.c \
+ tvtime-command.c
+ tvtime_command_CFLAGS = $(OPT_CFLAGS) $(XML2_FLAG) $(AM_CFLAGS)
+-tvtime_command_LDFLAGS = $(ZLIB_LIBS) $(XML2_LIBS)
++tvtime_command_LDADD = $(ZLIB_LIBS) $(XML2_LIBS)
+ tvtime_configure_SOURCES = utils.h utils.c tvtimeconf.h tvtimeconf.c \
+ tvtime-configure.c
+ tvtime_configure_CFLAGS = $(OPT_CFLAGS) $(XML2_FLAG) $(AM_CFLAGS)
+-tvtime_configure_LDFLAGS = $(ZLIB_LIBS) $(XML2_LIBS)
++tvtime_configure_LDADD = $(ZLIB_LIBS) $(XML2_LIBS)
+ tvtime_scanner_SOURCES = utils.h utils.c videoinput.h videoinput.c \
+ tvtimeconf.h tvtimeconf.c station.h station.c tvtime-scanner.c \
+ mixer.h mixer.c
+ tvtime_scanner_CFLAGS = $(OPT_CFLAGS) $(XML2_FLAG) $(AM_CFLAGS)
+-tvtime_scanner_LDFLAGS = $(ZLIB_LIBS) $(XML2_LIBS)
++tvtime_scanner_LDADD = $(ZLIB_LIBS) $(XML2_LIBS)
+
diff --git a/tvtime-1.0.2_p20110131-gettext.patch b/tvtime-1.0.2_p20110131-gettext.patch
new file mode 100644
index 000000000000..8a3de541a5aa
--- /dev/null
+++ b/tvtime-1.0.2_p20110131-gettext.patch
@@ -0,0 +1,71 @@
+Quick fix for building with newer autoconf where mkinstalldirs is no longer
+available.
+
+Upstream: no
+Author: Alex Legler <a3li@gentoo.org>
+
+diff -Naur tvtime.orig/po/Makefile.in.in tvtime/po/Makefile.in.in
+--- tvtime.orig/po/Makefile.in.in 2011-02-01 02:35:26.000000000 +0100
++++ tvtime/po/Makefile.in.in 2011-05-29 22:16:54.093991811 +0200
+@@ -26,8 +26,11 @@
+
+ INSTALL = @INSTALL@
+ INSTALL_DATA = @INSTALL_DATA@
+-MKINSTALLDIRS = @MKINSTALLDIRS@
+-mkinstalldirs = $(SHELL) $(MKINSTALLDIRS)
++
++mkdir_p = $(SHELL) @install_sh@ -d
++install_sh = $(SHELL) @install_sh@
++MKDIR_P = @MKDIR_P@
++mkdir_p = @mkdir_p@
+
+ GMSGFMT = @GMSGFMT@
+ MSGFMT = @MSGFMT@
+@@ -137,7 +140,7 @@
+ install-exec:
+ install-data: install-data-@USE_NLS@
+ if test "$(PACKAGE)" = "gettext-tools"; then \
+- $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \
++ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
+ for file in $(DISTFILES.common) Makevars.template; do \
+ $(INSTALL_DATA) $(srcdir)/$$file \
+ $(DESTDIR)$(gettextsrcdir)/$$file; \
+@@ -150,13 +153,13 @@
+ fi
+ install-data-no: all
+ install-data-yes: all
+- $(mkinstalldirs) $(DESTDIR)$(datadir)
++ $(mkdir_p) $(DESTDIR)$(datadir)
+ @catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
+ dir=$(localedir)/$$lang/LC_MESSAGES; \
+- $(mkinstalldirs) $(DESTDIR)$$dir; \
++ $(mkdir_p) $(DESTDIR)$$dir; \
+ if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \
+ $(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \
+ echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \
+@@ -196,19 +199,19 @@
+ installdirs-exec:
+ installdirs-data: installdirs-data-@USE_NLS@
+ if test "$(PACKAGE)" = "gettext-tools"; then \
+- $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \
++ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
+ else \
+ : ; \
+ fi
+ installdirs-data-no:
+ installdirs-data-yes:
+- $(mkinstalldirs) $(DESTDIR)$(datadir)
++ $(mkdir_p) $(DESTDIR)$(datadir)
+ @catalogs='$(CATALOGS)'; \
+ for cat in $$catalogs; do \
+ cat=`basename $$cat`; \
+ lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
+ dir=$(localedir)/$$lang/LC_MESSAGES; \
+- $(mkinstalldirs) $(DESTDIR)$$dir; \
++ $(mkdir_p) $(DESTDIR)$$dir; \
+ for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
+ if test -n "$$lc"; then \
+ if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
diff --git a/tvtime-1.0.2_p20110131-libsupc++.patch b/tvtime-1.0.2_p20110131-libsupc++.patch
new file mode 100644
index 000000000000..00043eabc541
--- /dev/null
+++ b/tvtime-1.0.2_p20110131-libsupc++.patch
@@ -0,0 +1,12 @@
+diff -Naur tvtime.orig/src/Makefile.am tvtime/src/Makefile.am
+--- tvtime.orig/src/Makefile.am 2011-02-01 02:35:26.000000000 +0100
++++ tvtime/src/Makefile.am 2011-05-29 21:39:08.739993239 +0200
+@@ -77,7 +77,7 @@
+ $(PLUGIN_CFLAGS) $(X11_CFLAGS) $(XML2_FLAG) \
+ $(FONT_CFLAGS) $(AM_CFLAGS)
+ tvtime_LDFLAGS = $(TTF_LIBS) $(ZLIB_LIBS) $(PNG_LIBS) \
+- $(X11_LIBS) $(XML2_LIBS) $(ASOUND_LIBS) -lm -lstdc++
++ $(X11_LIBS) $(XML2_LIBS) $(ASOUND_LIBS) -lm -lsupc++
+
+ tvtime_command_SOURCES = utils.h utils.c tvtimeconf.h tvtimeconf.c \
+ tvtime-command.c
diff --git a/tvtime-1.0.2_p20110131-underlinking.patch b/tvtime-1.0.2_p20110131-underlinking.patch
new file mode 100644
index 000000000000..eed4beac34d5
--- /dev/null
+++ b/tvtime-1.0.2_p20110131-underlinking.patch
@@ -0,0 +1,11 @@
+--- src/Makefile.am.orig 2011-10-14 22:21:20.897781921 +0200
++++ src/Makefile.am 2011-10-14 22:21:30.368781581 +0200
+@@ -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++
++ $(X11_LIBS) $(XML2_LIBS) $(ASOUND_LIBS) -lm -lsupc++ -lpthread
+
+ tvtime_command_SOURCES = utils.h utils.c tvtimeconf.h tvtimeconf.c \
+ tvtime-command.c
diff --git a/tvtime-libpng-1.5.patch b/tvtime-libpng-1.5.patch
new file mode 100644
index 000000000000..bfa22ed98d02
--- /dev/null
+++ b/tvtime-libpng-1.5.patch
@@ -0,0 +1,14 @@
+Include zlib.h which is no longer implicitly included with libpng-1.5
+Bug 369663
+
+diff -ru tvtime-111b28cca42d.orig/src/pngoutput.c tvtime-111b28cca42d/src/pngoutput.c
+--- tvtime-111b28cca42d.orig/src/pngoutput.c 2011-02-01 02:35:26.000000000 +0100
++++ tvtime-111b28cca42d/src/pngoutput.c 2011-06-02 13:36:55.965999463 +0200
+@@ -18,6 +18,7 @@
+
+ #include <stdio.h>
+ #include <stdlib.h>
++#include <zlib.h>
+ #include <png.h>
+ #include "pngoutput.h"
+
diff --git a/tvtime-pic.patch b/tvtime-pic.patch
new file mode 100644
index 000000000000..00b040e60af9
--- /dev/null
+++ b/tvtime-pic.patch
@@ -0,0 +1,11 @@
+--- tvtime/src/cpu_accel.c
++++ tvtime/src/cpu_accel.c
+@@ -35,7 +35,7 @@
+ int AMD;
+ uint32_t caps;
+
+-#ifndef PIC
++#if !defined(__PIC__) || defined(__x86_64__)
+ #define cpuid(op,eax,ebx,ecx,edx) \
+ __asm__ ("cpuid" \
+ : "=a" (eax), \