Package: tvtime
Version: 1.0.2-6
Severity: normal
Tags: patch
Justification: Policy 9.3.2
User: [email protected]
Usertags: origin-ubuntu maverick ubuntu-patch
Hi,
in ubuntu we applied the following changes:
- Add quilt support.
- debian/patches/tvtime-1.0.1-savematte.patch: tvtime does not rebember
matte settings (LP: #313570).
- debian/patches/desktop_file.patch: Fix docs/net-tvtime.desktop as
Freedesktop.org's per-spec.
- Add tvtime-1.0.2-alsa.patch to enable audio routing from external TV card;
- debian/control: Build-depend on autoconf, automake, libasound2-dev,
libtool.
- debian/rules: Call autoreconf to re-generate the configure script.
And we think you should too. Attaching the patches.
Description: Fix broken behaviour, tvtime doesn't remember matte settings.
Origin:
http://sourceforge.net/tracker/?func=detail&atid=506989&aid=1634306&group_id=64301
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/tvtime/+bug/313570
Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=526639
Reviewed-by: Alessio Treglia <[email protected]>
Last-Update: 2009-09-27
---
src/commands.c | 9 +
src/commands.h | 1
src/tvtime.c | 266 +++++++++++++++++++++++++------------------------------
src/tvtimeconf.c | 29 +++++
src/tvtimeconf.h | 1
src/videoinput.c | 17 +++
src/videoinput.h | 2
src/xvoutput.c | 2
8 files changed, 182 insertions(+), 145 deletions(-)
--- tvtime-1.0.2.orig/src/commands.c
+++ tvtime-1.0.2/src/commands.c
@@ -128,6 +128,7 @@ struct commands_s {
int togglepulldowndetection;
int togglematte;
int togglequiet;
+ int changedoverscan;
int framerate;
int scan_channels;
int pause;
@@ -2900,7 +2901,7 @@ void commands_handle( commands_t *cmd, i
case TVTIME_OVERSCAN_DOWN:
cmd->overscan = cmd->overscan + ( (tvtime_cmd == TVTIME_OVERSCAN_UP) ? 0.0025 : -0.0025 );
if( cmd->overscan > 0.4 ) cmd->overscan = 0.4; if( cmd->overscan < 0.0 ) cmd->overscan = 0.0;
-
+ cmd->changedoverscan = 1;
if( cmd->osd ) {
char message[ 200 ];
snprintf( message, sizeof( message ), _("Overscan: %.1f%%"),
@@ -3492,6 +3493,7 @@ void commands_next_frame( commands_t *cm
cmd->togglepulldowndetection = 0;
cmd->togglematte = 0;
cmd->togglequiet = 0;
+ cmd->changedoverscan = 0;
cmd->resizewindow = 0;
cmd->setdeinterlacer = 0;
cmd->setfreqtable = 0;
@@ -3539,6 +3541,11 @@ int commands_toggle_aspect( commands_t *
return cmd->toggleaspect;
}
+int commands_get_changed_overscan( commands_t *cmd )
+{
+ return cmd->changedoverscan;
+}
+
int commands_toggle_alwaysontop( commands_t *cmd )
{
return cmd->togglealwaysontop;
--- tvtime-1.0.2.orig/src/commands.h
+++ tvtime-1.0.2/src/commands.h
@@ -64,6 +64,7 @@ void commands_set_pulldown_alg( commands
int commands_quit( commands_t *cmd );
int commands_toggle_fullscreen( commands_t *cmd );
int commands_toggle_aspect( commands_t *cmd );
+int commands_get_changed_overscan( commands_t *cmd );
int commands_toggle_deinterlacer( commands_t *cmd );
int commands_toggle_pulldown_detection( commands_t *cmd );
int commands_toggle_matte( commands_t *cmd );
--- tvtime-1.0.2.orig/src/tvtime.c
+++ tvtime-1.0.2/src/tvtime.c
@@ -1062,84 +1062,55 @@ static void build_matte_menu( menu_t *me
char string[ 128 ];
menu_set_back_command( menu, TVTIME_SHOW_MENU, "output" );
- if( sixteennine ) {
- snprintf( string, sizeof( string ), (mode == 0) ?
- TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
- _("16:9 + Overscan") );
- menu_set_text( menu, 1, string );
- menu_set_enter_command( menu, 1, TVTIME_SET_MATTE, "16:9" );
- snprintf( string, sizeof( string ), (mode == 1) ?
- TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
- _("1.85:1") );
- menu_set_text( menu, 2, string );
- menu_set_enter_command( menu, 2, TVTIME_SET_MATTE, "1.85:1" );
- snprintf( string, sizeof( string ), (mode == 2) ?
- TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
- _("2.35:1") );
- menu_set_text( menu, 3, string );
- menu_set_enter_command( menu, 3, TVTIME_SET_MATTE, "2.35:1" );
- snprintf( string, sizeof( string ), (mode == 3) ?
- TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
- _("4:3 centre") );
- menu_set_text( menu, 4, string );
- menu_set_enter_command( menu, 4, TVTIME_SET_MATTE, "4:3" );
- snprintf( string, sizeof( string ), (mode == 4) ?
- TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
- _("16:10") );
- menu_set_text( menu, 5, string );
- menu_set_enter_command( menu, 5, TVTIME_SET_MATTE, "16:10" );
- } else {
- snprintf( string, sizeof( string ), (mode == 0) ?
- TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
- _("4:3 + Overscan") );
- menu_set_text( menu, 1, string );
- menu_set_enter_command( menu, 1, TVTIME_SET_MATTE, "4:3" );
- snprintf( string, sizeof( string ), (mode == 1) ?
- TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
- _("16:9") );
- menu_set_text( menu, 2, string );
- menu_set_enter_command( menu, 2, TVTIME_SET_MATTE, "16:9" );
- snprintf( string, sizeof( string ), (mode == 2) ?
- TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
- _("16:10") );
- menu_set_text( menu, 3, string );
- menu_set_enter_command( menu, 3, TVTIME_SET_MATTE, "16:10" );
- snprintf( string, sizeof( string ), (mode == 3) ?
- TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
- _("1.85:1") );
- menu_set_text( menu, 4, string );
- menu_set_enter_command( menu, 4, TVTIME_SET_MATTE, "1.85:1" );
- snprintf( string, sizeof( string ), (mode == 4) ?
- TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
- _("2.35:1") );
- menu_set_text( menu, 5, string );
- menu_set_enter_command( menu, 5, TVTIME_SET_MATTE, "2.35:1" );
- }
+
+ snprintf( string, sizeof( string ), (mode == 0) ?
+ TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
+ _("4:3") );
+ menu_set_text( menu, 1, string );
+ menu_set_enter_command( menu, 1, TVTIME_SET_MATTE, "4:3" );
+ snprintf( string, sizeof( string ), (mode == 1) ?
+ TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
+ _("16:10") );
+ menu_set_text( menu, 2, string );
+ menu_set_enter_command( menu, 2, TVTIME_SET_MATTE, "16:10" );
+ snprintf( string, sizeof( string ), (mode == 2) ?
+ TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
+ _("16:9") );
+ menu_set_text( menu, 3, string );
+ menu_set_enter_command( menu, 3, TVTIME_SET_MATTE, "16:9" );
+ snprintf( string, sizeof( string ), (mode == 3) ?
+ TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
+ _("1.85:1") );
+ menu_set_text( menu, 4, string );
+ menu_set_enter_command( menu, 4, TVTIME_SET_MATTE, "1.85:1" );
+ snprintf( string, sizeof( string ), (mode == 4) ?
+ TVTIME_ICON_RADIOON " %s" : TVTIME_ICON_RADIOOFF " %s",
+ _("2.35:1") );
+ menu_set_text( menu, 5, string );
+ menu_set_enter_command( menu, 5, TVTIME_SET_MATTE, "2.35:1" );
+
snprintf( string, sizeof( string ), TVTIME_ICON_PLAINLEFTARROW " %s",
_("Back") );
menu_set_text( menu, 6, string );
menu_set_enter_command( menu, 6, TVTIME_SHOW_MENU, "output" );
}
-
+
static void osd_list_matte( tvtime_osd_t *osd, int mode, int sixteennine )
{
tvtime_osd_list_set_lines( osd, 6 );
if( sixteennine ) {
tvtime_osd_list_set_text( osd, 0, _("Matte setting (Anamorphic input)") );
- tvtime_osd_list_set_text( osd, 1, _("16:9 + Overscan") );
- tvtime_osd_list_set_text( osd, 2, "1.85:1" );
- tvtime_osd_list_set_text( osd, 3, "2.35:1" );
- tvtime_osd_list_set_text( osd, 4, _("4:3 centre") );
- tvtime_osd_list_set_text( osd, 5, "16:10" );
+
} else {
tvtime_osd_list_set_text( osd, 0, _("Matte setting (4:3 input)") );
- tvtime_osd_list_set_text( osd, 1, _("4:3 + Overscan") );
- tvtime_osd_list_set_text( osd, 2, "16:9" );
- tvtime_osd_list_set_text( osd, 3, "16:10" );
- tvtime_osd_list_set_text( osd, 4, "1.85:1" );
- tvtime_osd_list_set_text( osd, 5, "2.35:1" );
}
+ tvtime_osd_list_set_text( osd, 1, "4:3" );
+ tvtime_osd_list_set_text( osd, 2, "16:10" );
+ tvtime_osd_list_set_text( osd, 3, "16:9" );
+ tvtime_osd_list_set_text( osd, 4, "1.85:1" );
+ tvtime_osd_list_set_text( osd, 5, "2.35:1" );
+
tvtime_osd_list_set_hilight( osd, mode + 1 );
tvtime_osd_show_list( osd, 1, 0 );
}
@@ -1204,6 +1175,7 @@ int tvtime_main( rtctimer_t *rtctimer, i
int matte_y = 0;
int matte_h = 0;
int matte_mode = 0;
+ int matte_changed = 0;
int restarttvtime = 0;
int return_value = 0;
int last_current_id = -1;
@@ -1241,6 +1213,7 @@ int tvtime_main( rtctimer_t *rtctimer, i
output = get_xv_output();
sixteennine = config_get_aspect( ct );
+ matte_mode = config_get_matte( ct );
if( !output || !output->init( config_get_geometry( ct ),
sixteennine, config_get_square_pixels( ct ),
@@ -1594,6 +1567,15 @@ int tvtime_main( rtctimer_t *rtctimer, i
build_fspos_menu( commands_get_menu( commands, "fspos" ),
config_get_fullscreen_position( ct ) );
+ matte_changed = 1;
+ double matte = 4.0/3.0;
+
+ /* initialize with safe values until matte is calculated later in the loop. */
+ matte_x = 0;
+ matte_y = 0;
+ matte_w = width;
+ matte_h = height;
+
/* Initialize our timestamps. */
for(;;) {
const char *fifo_args = 0;
@@ -1607,31 +1589,19 @@ int tvtime_main( rtctimer_t *rtctimer, i
int exposed = output->is_exposed();
int current_id;
+
if( vidin && videoinput_has_tuner( vidin ) ) {
current_id = station_get_current_id( stationmgr );
} else {
current_id = 0;
}
-
- if( matte_mode ) {
+ /* Since the matte/overscan calculations changed these could probably
+ be the same variables, but we'll leave it like this for now. */
output_x = matte_x;
output_w = matte_w;
output_y = matte_y;
output_h = matte_h;
- } else {
- output_x = (int) ((((double) width) *
- commands_get_overscan( commands )) + 0.5);
- output_w = (int) ((((double) width) -
- (((double) width) *
- commands_get_overscan( commands ) * 2.0)) +
- 0.5);
- output_y = (int) ((((double) height) *
- commands_get_overscan( commands )) + 0.5);
- output_h = (int) ((((double) height) -
- (((double) height) *
- commands_get_overscan( commands ) * 2.0)) +
- 0.5);
- }
+
if( fifo ) {
int cmd;
@@ -1766,11 +1736,14 @@ int tvtime_main( rtctimer_t *rtctimer, i
quiet_screenshots );
commands_refresh_menu( commands );
}
+
+
if( commands_toggle_aspect( commands ) ) {
- matte_mode = 0;
- output->set_matte( 0, 0 );
if( output->toggle_aspect() ) {
sixteennine = 1;
+ /* Matte is now always applied so we change it to 16:9 mode too so that
+ nothing other than overscan is cropped. */
+ matte_mode = 2;
if( osd ) {
tvtime_osd_show_message( osd,
_("16:9 display mode active.") );
@@ -1780,6 +1753,7 @@ int tvtime_main( rtctimer_t *rtctimer, i
( ( (double) height ) * (16.0 / 9.0) );
} else {
sixteennine = 0;
+ matte_mode = 0;
if( osd ) {
tvtime_osd_show_message( osd,
_("4:3 display mode active.") );
@@ -1800,9 +1774,7 @@ int tvtime_main( rtctimer_t *rtctimer, i
output->is_alwaysontop_supported(),
output->is_overscan_supported(),
quiet_screenshots );
- build_matte_menu( commands_get_menu( commands, "matte" ),
- matte_mode, sixteennine );
- commands_refresh_menu( commands );
+ matte_changed = 1;
}
if( commands_get_fs_pos( commands ) ) {
const char *fspos = commands_get_fs_pos( commands );
@@ -1839,84 +1811,92 @@ int tvtime_main( rtctimer_t *rtctimer, i
}
commands_refresh_menu( commands );
}
+
+ /* Overscan has been changed so it is calculated and applied with the matte.
+ So changing it now generated this event so that we can tell it to redo the matte. */
+ if( commands_get_changed_overscan( commands ) ) {
+ matte_changed = 1;
+ }
if( commands_toggle_matte( commands ) ||
commands_get_matte_mode( commands ) ) {
- double matte = 4.0 / 3.0;
- int sqwidth = sixteennine ?
- ((height * 16) / 9) : ((height * 4) / 3);
- int sqheight = sixteennine ?
- ((width * 9) / 16) : ((width * 3) / 4);
- matte_x = 0;
- matte_w = width;
if( commands_toggle_matte( commands ) ) {
matte_mode = (matte_mode + 1) % 5;
} else {
- if( !strcmp( commands_get_matte_mode( commands ), "16:9" ) ) {
- matte_mode = sixteennine ? 0 : 1;
- } else if( !strcmp( commands_get_matte_mode( commands ),
- "16:10" ) ) {
- matte_mode = sixteennine ? 4 : 2;
+ if( !strcmp( commands_get_matte_mode( commands ), "16:10" ) ) {
+ matte_mode = 1;
+ } else if( !strcmp( commands_get_matte_mode( commands ),
+ "16:9" ) ) {
+ matte_mode = 2;
} else if( !strcmp( commands_get_matte_mode( commands ),
"1.85:1" ) ) {
- matte_mode = sixteennine ? 1 : 3;
+ matte_mode = 3;
} else if( !strcmp( commands_get_matte_mode( commands ),
"2.35:1" ) ) {
- matte_mode = sixteennine ? 2 : 4;
+ matte_mode = 4;
} else {
- matte_mode = sixteennine ? 3 : 0;
+ matte_mode = 0;
}
}
-
- if( sixteennine ) {
- if( matte_mode == 0 ) {
- matte = 16.0 / 9.0;
- } else if( matte_mode == 1 ) {
- matte = 1.85;
- } else if( matte_mode == 2 ) {
- matte = 2.35;
- } else if( matte_mode == 3 ) {
- matte = 4.0 / 3.0;
- matte_w = (int) (((double) sqheight * matte) + 0.5);
- matte_x = (width - matte_w) / 2;
- /* We're cropping the sides off so we add overscan to avoid mess
- * at the top of the screen. */
- matte_y = commands_get_overscan( commands ) * height / 2;
- matte_h = height - matte_y;
- output->set_matte( (matte_h * 4) / 3, matte_h );
- } else if( matte_mode == 4 ) {
- matte = 1.6;
- matte_w = (int) (((double) sqheight * matte) + 0.5);
- matte_x = (width - matte_w) / 2;
- /* We're cropping the sides off so we add overscan to avoid mess
- * at the top of the screen. */
- matte_y = commands_get_overscan( commands ) * height / 2;
- matte_h = height - matte_y;
- output->set_matte( (matte_h * 16) / 10, matte_h );
- }
- } else {
- if( matte_mode == 1 ) {
- matte = 16.0 / 9.0;
- } else if( matte_mode == 2 ) {
- matte = 1.6;
- } else if( matte_mode == 3 ) {
- matte = 1.85;
- } else if( matte_mode == 4 ) {
- matte = 2.35;
- }
- }
- if( !matte_x ) {
- matte_h = (int) ((((double) sqwidth)/matte) + 0.5);
- matte_y = (height - matte_h) / 2;
- output->set_matte( sqwidth, matte_h );
- }
if( osd && !commands_menu_active( commands ) ) {
osd_list_matte( osd, matte_mode, sixteennine );
}
build_matte_menu( commands_get_menu( commands, "matte" ),
matte_mode, sixteennine );
commands_refresh_menu( commands );
+ matte_changed = 1;
}
+ if (matte_changed) {
+ matte_changed = 0;
+
+ /* start with overscan then apply matte */
+ matte_x = (int) ((((double) width) *
+ commands_get_overscan( commands )) + 0.5);
+ matte_w = (int) ((((double) width) -
+ (((double) width) *
+ commands_get_overscan( commands ) * 2.0)) +
+ 0.5);
+ matte_y = (int) ((((double) height) *
+ commands_get_overscan( commands )) + 0.5);
+ matte_h = (int) ((((double) height) -
+ (((double) height) *
+ commands_get_overscan( commands ) * 2.0)) +
+ 0.5);
+
+ int sqwidth = sixteennine ?
+ ((matte_h * 16) / 9) : ((matte_h * 4) / 3);
+ int sqheight = sixteennine ?
+ ((matte_w * 9) / 16) : ((matte_w * 3) / 4);
+
+ if( matte_mode == 0 ) {
+ matte = 4.0 / 3.0;
+ config_save( ct, "Matte", "4:3" );
+ } else if( matte_mode == 1 ) {
+ matte = 1.6;
+ config_save( ct, "Matte", "16:10" );
+ } else if( matte_mode == 2 ) {
+ matte = 16.0/9.0;
+ config_save( ct, "Matte", "16:9" );
+ } else if( matte_mode == 3 ) {
+ matte = 1.85;
+ config_save( ct, "Matte", "1.85:1" );
+ } else if( matte_mode == 4 ) {
+ matte = 2.35;
+ config_save( ct, "Matte", "2.35:1" );
+ }
+
+ if( sixteennine && matte < (16.0/9.0) )
+ {
+ matte_w = (int) (((double) sqheight * matte) + 0.5);
+ matte_x = (width - matte_w) / 2;
+ output->set_matte( matte_w, sqheight );
+ } else {
+ matte_h = (int) ((((double) sqwidth)/matte) + 0.5);
+ matte_y = (height - matte_h) / 2;
+ output->set_matte( sqwidth, matte_h );
+ }
+ }
+
if( commands_toggle_pulldown_detection( commands ) ) {
if( height == 480 ) {
tvtime->pulldown_alg =
--- tvtime-1.0.2.orig/src/tvtimeconf.c
+++ tvtime-1.0.2/src/tvtimeconf.c
@@ -56,6 +56,7 @@ struct config_s
char *geometry;
int verbose;
int aspect;
+ int matte;
int squarepixels;
int debug;
int fullscreen;
@@ -290,6 +291,22 @@ static void parse_option( config_t *ct,
ct->aspect = atoi( curval );
}
+ if( !xmlStrcasecmp( name, BAD_CAST "Matte" ) ) {
+ if(!strcmp( curval, "4:3")) {
+ ct->matte = 0;
+ } else if(!strcmp( curval, "16:10")) {
+ ct->matte = 1;
+ } else if(!strcmp( curval, "16:9")) {
+ ct->matte = 2;
+ } else if(!strcmp( curval, "1.85:1")) {
+ ct->matte = 3;
+ } else if(!strcmp( curval, "2.35:1")) {
+ ct->matte = 4;
+ }
+ /* No valid matte if found ct->matte will be -1 and config_get_matte will choose
+ a default based on the aspect ratio. */
+ }
+
if( !xmlStrcasecmp( name, BAD_CAST "DebugMode" ) ) {
ct->debug = atoi( curval );
}
@@ -712,6 +729,7 @@ config_t *config_new( void )
ct->geometry = strdup( "0x576" );
ct->verbose = 0;
ct->aspect = 0;
+ ct->matte = -1;
ct->squarepixels = 1;
ct->debug = 0;
ct->fullscreen = 0;
@@ -807,6 +825,10 @@ config_t *config_new( void )
ct->keymap[ 'a' ] = TVTIME_TOGGLE_ASPECT;
ct->keymap[ 'f' ] = TVTIME_TOGGLE_FULLSCREEN;
ct->keymap[ 'i' ] = TVTIME_TOGGLE_INPUT;
+ ct->keymap[ 'a' ] = TVTIME_TOGGLE_ASPECT;
+ ct->keymap[ I_INSERT ] = TVTIME_TOGGLE_MATTE;
+ ct->keymap[ ',' ] = TVTIME_OVERSCAN_DOWN;
+ ct->keymap[ '.' ] = TVTIME_OVERSCAN_DOWN;
ct->keymap[ 's' ] = TVTIME_SCREENSHOT;
ct->keymap[ ',' ] = TVTIME_MIXER_TOGGLE_MUTE;
ct->keymap[ 'e' ] = TVTIME_TOGGLE_AUDIO_MODE;
@@ -1451,6 +1473,13 @@ int config_get_aspect( config_t *ct )
return ct->aspect;
}
+int config_get_matte( config_t *ct )
+{
+ /* If matte is not set then default to 0 for normal or 2 for widescreen. */
+ if (ct->matte == -1) return ct->aspect * 2;
+ return ct->matte;
+}
+
int config_get_start_channel( config_t *ct )
{
return ct->start_channel;
--- tvtime-1.0.2.orig/src/tvtimeconf.h
+++ tvtime-1.0.2/src/tvtimeconf.h
@@ -151,6 +151,7 @@ int config_get_debug( config_t *ct );
const char *config_get_geometry( config_t *ct );
int config_get_inputwidth( config_t *ct );
int config_get_aspect( config_t *ct );
+int config_get_matte( config_t *ct );
int config_get_inputnum( config_t *ct );
const char *config_get_v4l_device( config_t *ct );
const char *config_get_v4l_norm( config_t *ct );
--- tvtime-1.0.2.orig/src/videoinput.c
+++ tvtime-1.0.2/src/videoinput.c
@@ -376,6 +376,7 @@ uint8_t *videoinput_next_frame( videoinp
wait_for_frame_v4l2( vidin );
+ videoinput_get_aspect( vidin );
cur_buf.type = vidin->capbuffers[ 0 ].vidbuf.type;
if( ioctl( vidin->grab_fd, VIDIOC_DQBUF, &cur_buf ) < 0 ) {
/* some drivers return EIO when there is no signal */
@@ -1148,6 +1149,22 @@ void videoinput_set_saturation_relative(
}
}
+float videoinput_get_aspect( videoinput_t *vidin )
+{
+ float aspect = 1.0;
+
+ if( vidin->isv4l2 ) {
+ struct v4l2_cropcap cropcap;
+ /* on success 0 is returned */
+ if( !ioctl( vidin->grab_fd, VIDIOC_CROPCAP, &cropcap ) ) {
+ aspect = (float)cropcap.pixelaspect.numerator / (float)cropcap.pixelaspect.denominator;
+ fprintf( stderr, "videoinput: Aspect ratio: %f\n", aspect);
+ }
+ }
+
+ return aspect;
+}
+
static void videoinput_do_mute( videoinput_t *vidin, int mute )
{
if( vidin->hasaudio && mute != vidin->hw_muted ) {
--- tvtime-1.0.2.orig/src/videoinput.h
+++ tvtime-1.0.2/src/videoinput.h
@@ -71,6 +71,8 @@ typedef struct videoinput_s videoinput_t
#define VIDEOINPUT_LANG1 4
#define VIDEOINPUT_LANG2 8
+float videoinput_get_aspect( videoinput_t *vidin );
+
/**
* Possible PAL audio modes, for the cx88 driver that cannot autodetect.
*/
--- tvtime-1.0.2.orig/src/xvoutput.c
+++ tvtime-1.0.2/src/xvoutput.c
@@ -233,7 +233,7 @@ static int xv_alloc_frame( void )
{
int size;
uint8_t *alloc;
-
+
size = input_width * input_height * 2;
if( use_shm ) {
alloc = create_shm( size );
Description: Fix desktop file as per Freedesktop.org spec.
Author: Alessio Treglia <[email protected]>
---
docs/net-tvtime.desktop | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
--- tvtime-1.0.2.orig/docs/net-tvtime.desktop
+++ tvtime-1.0.2/docs/net-tvtime.desktop
@@ -1,10 +1,9 @@
[Desktop Entry]
-Encoding=UTF-8
Comment=High quality video deinterlacer
-Icon=tvtime.png
+Icon=tvtime
Exec=tvtime
Name=TVtime Television Viewer
GenericName=Television Viewer
Terminal=false
Type=Application
-Categories=Application;AudioVideo;
+Categories=AudioVideo;
Origin: Ubuntu
Description: Add support for ALSA in combination with USB audio devices.
Bug: https://bugs.launchpad.net/bugs/340769
---
src/Makefile.am | 4
src/audiolib.c | 342 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/audiolib.h | 38 ++++++
src/tvtime.c | 30 ++++
src/videoinput.c | 19 +++
src/videoinput.h | 14 ++
6 files changed, 445 insertions(+), 2 deletions(-)
--- /dev/null
+++ tvtime-1.0.2/src/audiolib.c
@@ -0,0 +1,342 @@
+/*
+ Copyright 2008 Empia Technology Inc.
+ Copyright 2008 Markus Rechberger <[email protected]>
+
+ 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(¶ms);
+ 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;
+}
--- /dev/null
+++ tvtime-1.0.2/src/audiolib.h
@@ -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
--- tvtime-1.0.2.orig/src/Makefile.am
+++ tvtime-1.0.2/src/Makefile.am
@@ -40,7 +40,7 @@ COMMON_SRCS = mixer.c videoinput.c rtcti
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 audiolib.h audiolib.c
if ARCH_X86
DSCALER_SRCS = $(top_srcdir)/plugins/dscalerapi.h \
@@ -77,7 +77,7 @@ tvtime_CFLAGS = $(TTF_CFLAGS) $(PNG_CFLA
$(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) -lm -lstdc++ -lasound
tvtime_command_SOURCES = utils.h utils.c tvtimeconf.h tvtimeconf.c \
tvtime-command.c
--- tvtime-1.0.2.orig/src/tvtime.c
+++ tvtime-1.0.2/src/tvtime.c
@@ -77,6 +77,7 @@
#include "mm_accel.h"
#include "menu.h"
#include "tvtimeglyphs.h"
+#include "audiolib.h"
/**
* This is how many frames to wait until deciding if the pulldown phase
@@ -1181,6 +1182,7 @@ int tvtime_main( rtctimer_t *rtctimer, i
int last_current_id = -1;
int quiet_screenshots = 0;
char prevloc[ 256 ];
+ char *empia_device;
int i;
ct = config_new();
@@ -1576,6 +1578,8 @@ int tvtime_main( rtctimer_t *rtctimer, i
matte_w = width;
matte_h = height;
+ empia_device = get_empia_device();
+
/* Initialize our timestamps. */
for(;;) {
const char *fifo_args = 0;
@@ -2049,9 +2053,30 @@ int tvtime_main( rtctimer_t *rtctimer, i
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 );
@@ -2491,6 +2516,11 @@ int tvtime_main( rtctimer_t *rtctimer, i
/* 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 );
--- tvtime-1.0.2.orig/src/videoinput.c
+++ tvtime-1.0.2/src/videoinput.c
@@ -39,6 +39,7 @@
#include "videodev2.h"
#include "videoinput.h"
#include "mixer.h"
+#include "audiolib.h"
/**
* How long to wait when we lose a signal, or acquire a signal.
@@ -231,8 +232,25 @@ struct videoinput_s
/* V4L1 read-mode state. */
int grab_size;
uint8_t *grab_data;
+
+ 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;
+}
+
const char *videoinput_get_audio_mode_name( videoinput_t *vidin, int mode )
{
if( mode == VIDEO_SOUND_MONO ) {
@@ -456,6 +474,7 @@ videoinput_t *videoinput_new( const char
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;
--- tvtime-1.0.2.orig/src/videoinput.h
+++ tvtime-1.0.2/src/videoinput.h
@@ -280,6 +280,20 @@ int videoinput_get_pal_audio_mode( video
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.
*/