Package: tvtime
Version: 1.0.2-6
Severity: normal
Tags: patch
Justification: Policy 9.3.2
User: ubuntu-de...@lists.ubuntu.com
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 <quadris...@ubuntu.com>
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 <quadris...@ubuntu.com>
---
 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 <mrechber...@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;
+}
--- /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.
  */

Reply via email to