>From 30b30ed346f0e4e36bb8b4d06daaaf3535abbc07 Mon Sep 17 00:00:00 2001
From: Joseph Tulou <brezhoneg1@yahoo.fr>
Date: Fri, 30 Jan 2009 17:28:42 +0100
Subject: [PATCH] core implementation of --[no]-autoscale and --scale-factor with x11 vout support

---
 include/vlc_keys.h                 |    6 +++-
 include/vlc_vout.h                 |   10 ++++++-
 modules/control/hotkeys.c          |   40 +++++++++++++++++++++++++++++++--
 modules/video_output/x11/xcommon.c |   23 +++++++++++++++++++
 src/libvlc-module.c                |   43 ++++++++++++++++++++++++++---------
 src/video_output/video_output.c    |    3 +-
 src/video_output/vout_intf.c       |   33 ++++++++++++++++++++-------
 src/video_output/vout_pictures.c   |   18 +++++++++++++-
 8 files changed, 146 insertions(+), 30 deletions(-)

diff --git a/include/vlc_keys.h b/include/vlc_keys.h
index a5a3f94..8c9513d 100644
--- a/include/vlc_keys.h
+++ b/include/vlc_keys.h
@@ -339,7 +339,9 @@ typedef enum vlc_key {
     ACTIONID_ZOOM_DOUBLE,
     /* Cycle Through Audio Devices */
     ACTIONID_AUDIODEVICE_CYCLE,
-    /* Scaling in fullscreen */
-    ACTIONID_TOGGLE_SCALING,
+    /* scaling */
+    ACTIONID_TOGGLE_AUTOSCALE,
+    ACTIONID_INCR_SCALEFACTOR,
+    ACTIONID_DECR_SCALEFACTOR
 } vlc_key_t;
 #endif
diff --git a/include/vlc_vout.h b/include/vlc_vout.h
index adab0a6..034f0be 100644
--- a/include/vlc_vout.h
+++ b/include/vlc_vout.h
@@ -506,7 +506,8 @@ struct vout_thread_t
     /**@{*/
     uint16_t            i_changes;          /**< changes made to the thread.
                                                       \see \ref vout_changes */
-    bool                b_scale;                  /**< allow picture scaling */
+    bool                b_autoscale;        /**< auto scaling picture or not */
+    uint64_t            ll_zoom;            /**< scaling factor if no auto */
     bool                b_fullscreen;         /**< toogle fullscreen display */
     unsigned int        i_window_width;              /**< video window width */
     unsigned int        i_window_height;            /**< video window height */
@@ -566,12 +567,14 @@ struct vout_thread_t
 #define VOUT_INFO_CHANGE        0x0001
 /** b_interface changed */
 #define VOUT_INTF_CHANGE        0x0004
-/** b_scale changed */
+/** b_autoscale changed */
 #define VOUT_SCALE_CHANGE       0x0008
 /** b_cursor changed */
 #define VOUT_CURSOR_CHANGE      0x0020
 /** b_fullscreen changed */
 #define VOUT_FULLSCREEN_CHANGE  0x0040
+/** ll_zoom changed */
+#define VOUT_ZOOM_CHANGE        0x0080
 /** size changed */
 #define VOUT_SIZE_CHANGE        0x0200
 /** depth changed */
@@ -596,6 +599,9 @@ struct vout_thread_t
 
 #define MAX_JITTER_SAMPLES      20
 
+/* scaling factor (applied to ll_zoom in vout_thread_t) */
+#define ZOOM_FP_FACTOR          1000
+
 /*****************************************************************************
  * Prototypes
  *****************************************************************************/
diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c
index b11e8a6..19dd517 100644
--- a/modules/control/hotkeys.c
+++ b/modules/control/hotkeys.c
@@ -609,10 +609,44 @@ static void Run( intf_thread_t *p_intf )
                 }
                 free( val.psz_string );
             }
-            else if( i_action == ACTIONID_TOGGLE_SCALING && p_vout )
+            else if( i_action == ACTIONID_TOGGLE_AUTOSCALE && p_vout )
             {
-                bool b_scaling = var_GetBool( p_vout, "scaling" );
-                var_SetBool( p_vout, "scaling", !b_scaling );
+                float f_scalefactor = var_GetFloat( p_vout, "scale-factor" );
+                if ( f_scalefactor != 1.0 )
+                { 
+                    var_SetFloat( p_vout, "scale-factor", 1.0 );
+                    vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
+                                         _("Zooming reset") );
+                }
+                else
+                {
+                    bool b_autoscale = !var_GetBool( p_vout, "autoscale" );
+                    var_SetBool( p_vout, "autoscale", b_autoscale );
+                    if( b_autoscale )
+                        vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
+                                         _("Scaled to screen") );
+                    else
+                        vout_OSDMessage( VLC_OBJECT(p_input), DEFAULT_CHAN,
+                                         _("Original Size") );
+                }
+            }
+            else if( i_action == ACTIONID_INCR_SCALEFACTOR && p_vout )
+            {
+               float f_scalefactor;
+
+               f_scalefactor = var_GetFloat( p_vout, "scale-factor" ); 
+               if( f_scalefactor < 10. )
+                   f_scalefactor += .1;
+               var_SetFloat( p_vout, "scale-factor", f_scalefactor );
+            }
+            else if( i_action == ACTIONID_DECR_SCALEFACTOR && p_vout )
+            {
+               float f_scalefactor;
+
+               f_scalefactor = var_GetFloat( p_vout, "scale-factor" ); 
+               if( f_scalefactor > .3 )
+                   f_scalefactor -= .1;
+               var_SetFloat( p_vout, "scale-factor", f_scalefactor );
             }
             else if( i_action == ACTIONID_DEINTERLACE && p_vout )
             {
diff --git a/modules/video_output/x11/xcommon.c b/modules/video_output/x11/xcommon.c
index 5ba486d..abee7df 100644
--- a/modules/video_output/x11/xcommon.c
+++ b/modules/video_output/x11/xcommon.c
@@ -1478,6 +1478,29 @@ static int ManageVideo( vout_thread_t *p_vout )
         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
     }
 
+    /* autoscale toggle */
+    if( p_vout->i_changes & VOUT_SCALE_CHANGE )
+    {
+        p_vout->i_changes &= ~VOUT_SCALE_CHANGE;
+
+        p_vout->b_autoscale = var_GetBool( p_vout, "autoscale" );
+        p_vout->ll_zoom = (uint64_t) ZOOM_FP_FACTOR;
+
+        p_vout->i_changes |= VOUT_SIZE_CHANGE;
+    }
+
+    /* scaling factor */
+    if( p_vout->i_changes & VOUT_ZOOM_CHANGE )
+    {
+        p_vout->i_changes &= ~VOUT_ZOOM_CHANGE;
+
+        p_vout->b_autoscale = false;
+        p_vout->ll_zoom =
+            (uint64_t)( ZOOM_FP_FACTOR * var_GetFloat( p_vout, "scale-factor" ) );
+
+        p_vout->i_changes |= VOUT_SIZE_CHANGE;
+    }
+
     if( p_vout->i_changes & VOUT_CROP_CHANGE ||
         p_vout->i_changes & VOUT_ASPECT_CHANGE )
     {
diff --git a/src/libvlc-module.c b/src/libvlc-module.c
index 5f22915..1db3326 100644
--- a/src/libvlc-module.c
+++ b/src/libvlc-module.c
@@ -510,9 +510,14 @@ static const char *const ppsz_pos_descriptions[] =
     "aspect, or a float value (1.25, 1.3333, etc.) expressing pixel " \
     "squareness.")
 
-#define SCALING_TEXT N_("Video scaling")
-#define SCALING_LONGTEXT N_( \
-    "This enables upscaling a video in a given window.")
+#define AUTOSCALE_TEXT N_("Video auto scaling")
+#define AUTOSCALE_LONGTEXT N_( \
+    "This forces video scaling to fit a given window.")
+
+#define SCALEFACTOR_TEXT N_("Video scale factor")
+#define SCALEFACTOR_LONGTEXT N_( \
+    "scale factor used if --no-auto-scale is selected." \
+    "Default value is 1.0 (original video size).")
 
 #define CUSTOM_CROP_RATIOS_TEXT N_("Custom crop ratios list")
 #define CUSTOM_CROP_RATIOS_LONGTEXT N_( \
@@ -1348,8 +1353,12 @@ static const char *const ppsz_albumart_descriptions[] =
 #define ASPECT_RATIO_KEY_LONGTEXT N_("Cycle through a predefined list of source aspect ratios.")
 #define CROP_KEY_TEXT N_("Cycle video crop")
 #define CROP_KEY_LONGTEXT N_("Cycle through a predefined list of crop formats.")
-#define TOGGLE_SCALING_KEY_TEXT N_("Toggle upscaling")
-#define TOGGLE_SCALING_KEY_LONGTEXT N_("Activate or deactivate upscaling.")
+#define TOGGLE_AUTOSCALE_KEY_TEXT N_("Toggle autoscaling")
+#define TOGGLE_AUTOSCALE_KEY_LONGTEXT N_("Activate or deactivate autoscaling.")
+#define INCR_SCALEFACTOR_KEY_TEXT N_("Increase scale factor")
+#define INCR_SCALEFACTOR_KEY_LONGTEXT N_("Increase scale factor.")
+#define DECR_SCALEFACTOR_KEY_TEXT N_("Decrease scale factor")
+#define DECR_SCALEFACTOR_KEY_LONGTEXT N_("Decrease scale factor.")
 #define DEINTERLACE_KEY_TEXT N_("Cycle deinterlace modes")
 #define DEINTERLACE_KEY_LONGTEXT N_("Cycle through deinterlace modes.")
 #define INTF_SHOW_KEY_TEXT N_("Show interface")
@@ -1604,7 +1613,9 @@ vlc_module_begin ()
     add_string( "aspect-ratio", NULL, NULL,
                 ASPECT_RATIO_TEXT, ASPECT_RATIO_LONGTEXT, false )
         change_safe ()
-    add_bool( "scaling", true, NULL, SCALING_TEXT, SCALING_LONGTEXT, false )
+    add_bool( "autoscale", true, NULL, AUTOSCALE_TEXT, AUTOSCALE_LONGTEXT, false )
+        change_safe ()
+    add_float( "scale-factor", 1.0, NULL, SCALEFACTOR_TEXT, SCALEFACTOR_LONGTEXT, false )
         change_safe ()
     add_string( "monitor-par", NULL, NULL,
                 MASPECT_RATIO_TEXT, MASPECT_RATIO_LONGTEXT, true )
@@ -2133,7 +2144,9 @@ vlc_module_begin ()
 #   define KEY_SUBTITLE_TRACK     's'
 #   define KEY_ASPECT_RATIO       'a'
 #   define KEY_CROP               'c'
-#   define KEY_TOGGLE_SCALING     'o'
+#   define KEY_TOGGLE_AUTOSCALE   'o'
+#   define KEY_INCR_SCALEFACTOR   KEY_MODIFIER_COMMAND|KEY_MODIFIER_ALT|'o'
+#   define KEY_DECR_SCALEFACTOR   KEY_MODIFIER_SHIFT|KEY_MODIFIER_ALT|'o'
 #   define KEY_DEINTERLACE        'd'
 #   define KEY_INTF_SHOW          'i'
 #   define KEY_INTF_HIDE          KEY_MODIFIER_SHIFT|'i'
@@ -2245,7 +2258,9 @@ vlc_module_begin ()
 #   define KEY_SUBTITLE_TRACK     'v'
 #   define KEY_ASPECT_RATIO       'a'
 #   define KEY_CROP               'c'
-#   define KEY_TOGGLE_SCALING     'o'
+#   define KEY_TOGGLE_AUTOSCALE   'o'
+#   define KEY_INCR_SCALEFACTOR   KEY_MODIFIER_CTRL|KEY_MODIFIER_ALT|'o'
+#   define KEY_DECR_SCALEFACTOR   KEY_MODIFIER_SHIFT|KEY_MODIFIER_ALT|'o'
 #   define KEY_DEINTERLACE        'd'
 #   define KEY_INTF_SHOW          'i'
 #   define KEY_INTF_HIDE          KEY_MODIFIER_SHIFT|'i'
@@ -2403,8 +2418,12 @@ vlc_module_begin ()
              ASPECT_RATIO_KEY_TEXT, ASPECT_RATIO_KEY_LONGTEXT, false )
     add_key( "key-crop", KEY_CROP, NULL,
              CROP_KEY_TEXT, CROP_KEY_LONGTEXT, false )
-    add_key( "key-toggle-scaling", KEY_TOGGLE_SCALING, NULL,
-             TOGGLE_SCALING_KEY_TEXT, TOGGLE_SCALING_KEY_LONGTEXT, false )
+    add_key( "key-toggle-autoscale", KEY_TOGGLE_AUTOSCALE, NULL,
+             TOGGLE_AUTOSCALE_KEY_TEXT, TOGGLE_AUTOSCALE_KEY_LONGTEXT, false )
+    add_key( "key-incr-scalefactor", KEY_INCR_SCALEFACTOR, NULL,
+             INCR_SCALEFACTOR_KEY_TEXT, INCR_SCALEFACTOR_KEY_LONGTEXT, false )
+    add_key( "key-decr-scalefactor", KEY_DECR_SCALEFACTOR, NULL,
+             DECR_SCALEFACTOR_KEY_TEXT, DECR_SCALEFACTOR_KEY_LONGTEXT, false )
     add_key( "key-deinterlace", KEY_DEINTERLACE, NULL,
              DEINTERLACE_KEY_TEXT, DEINTERLACE_KEY_LONGTEXT, false )
     add_key( "key-intf-show", KEY_INTF_SHOW, NULL,
@@ -2744,7 +2763,9 @@ const struct hotkey libvlc_hotkeys[] =
     { "key-menu-down", ACTIONID_MENU_DOWN, 0, },
     { "key-menu-select", ACTIONID_MENU_SELECT, 0, },
     { "key-audiodevice-cycle", ACTIONID_AUDIODEVICE_CYCLE, 0, },
-    { "key-toggle-scaling", ACTIONID_TOGGLE_SCALING, 0, },
+    { "key-toggle-autoscale", ACTIONID_TOGGLE_AUTOSCALE, 0, },
+    { "key-incr-scalefactor", ACTIONID_INCR_SCALEFACTOR, 0, },
+    { "key-decr-scalefactor", ACTIONID_DECR_SCALEFACTOR, 0, },
     { NULL, 0, 0, }
 };
 
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index 27de388..39b6e78 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -374,7 +374,8 @@ vout_thread_t * __vout_Create( vlc_object_t *p_parent, video_format_t *p_fmt )
 
     /* Initialize misc stuff */
     p_vout->i_changes    = 0;
-    p_vout->b_scale      = 1;
+    p_vout->b_autoscale  = 1;
+    p_vout->ll_zoom      = ZOOM_FP_FACTOR;
     p_vout->b_fullscreen = 0;
     p_vout->i_alignment  = 0;
     p_vout->p->render_time  = 10;
diff --git a/src/video_output/vout_intf.c b/src/video_output/vout_intf.c
index 89cc527..4aa3094 100644
--- a/src/video_output/vout_intf.c
+++ b/src/video_output/vout_intf.c
@@ -399,14 +399,22 @@ void vout_IntfInit( vout_thread_t *p_vout )
         var_TriggerCallback( p_vout, "aspect-ratio" );
     free( old_val.psz_string );
 
-    /* Add a variable to indicate if scaling video is activated or not */
-    var_Create( p_vout, "scaling", VLC_VAR_BOOL | VLC_VAR_DOINHERIT
+    /* Add variables to manage scaling video */
+    var_Create( p_vout, "autoscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT
                 | VLC_VAR_ISCOMMAND );
-    text.psz_string = _("Scaling video");
-    var_Change( p_vout, "scaling", VLC_VAR_SETTEXT, &text, NULL );
-    var_AddCallback( p_vout, "scaling", ScalingCallback, NULL );
-    var_Get( p_vout, "scaling", &val );
-    p_vout->b_scale = val.b_bool;
+    text.psz_string = _("Autoscale video");
+    var_Change( p_vout, "autoscale", VLC_VAR_SETTEXT, &text, NULL );
+    var_AddCallback( p_vout, "autoscale", ScalingCallback, NULL );
+    var_Get( p_vout, "autoscale", &val );
+    p_vout->b_autoscale = val.b_bool;
+
+    var_Create( p_vout, "scale-factor", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT
+                | VLC_VAR_ISCOMMAND );
+    text.psz_string = _("Scale factor");
+    var_Change( p_vout, "scale-factor", VLC_VAR_SETTEXT, &text, NULL );
+    var_AddCallback( p_vout, "scale-factor", ScalingCallback, NULL );
+    var_Get( p_vout, "scale-factor", &val );
+    p_vout->ll_zoom = (uint64_t) ( ZOOM_FP_FACTOR * val.f_float );
 
     /* Initialize the dimensions of the video window */
     InitWindowSize( p_vout, &p_vout->i_window_width,
@@ -1214,11 +1222,18 @@ static int ScalingCallback( vlc_object_t *p_this, char const *psz_cmd,
                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
     vout_thread_t *p_vout = (vout_thread_t *)p_this;
+    (void)oldval; (void)newval; (void)p_data;
 
     vlc_mutex_lock( &p_vout->change_lock );
 
-    p_vout->b_scale = newval.b_bool;
-    p_vout->i_changes |= VOUT_SIZE_CHANGE;
+    if( !strcmp( psz_cmd, "autoscale" ) )
+    {
+        p_vout->i_changes |= VOUT_SCALE_CHANGE;
+    }
+    else if( !strcmp( psz_cmd, "scale-factor" ) )
+    {
+        p_vout->i_changes |= VOUT_ZOOM_CHANGE;
+    }
 
     vlc_mutex_unlock( &p_vout->change_lock );
 
diff --git a/src/video_output/vout_pictures.c b/src/video_output/vout_pictures.c
index ffb2c57..18719c5 100644
--- a/src/video_output/vout_pictures.c
+++ b/src/video_output/vout_pictures.c
@@ -461,16 +461,30 @@ void vout_PlacePicture( const vout_thread_t *p_vout,
         return;
     }
 
-    if( p_vout->b_scale )
+    bool b_autoscale = p_vout->b_autoscale;
+    uint64_t ll_zoom = p_vout->ll_zoom;
+
+    /* be realistic, scaling factor confined between .2 and 10. */
+    if( ll_zoom > 10 * ZOOM_FP_FACTOR  || ll_zoom <  ZOOM_FP_FACTOR / 5 )
+        ll_zoom = ZOOM_FP_FACTOR;
+
+    if( b_autoscale )
     {
         *pi_width = i_width;
         *pi_height = i_height;
     }
-    else
+    else if( ll_zoom == ZOOM_FP_FACTOR )  /* original size */
     {
         *pi_width = __MIN( i_width, p_vout->fmt_in.i_visible_width );
         *pi_height = __MIN( i_height, p_vout->fmt_in.i_visible_height );
     }
+    else 
+    {
+        *pi_width = 
+             p_vout->fmt_in.i_visible_width * ll_zoom / ZOOM_FP_FACTOR;
+        *pi_height =
+             p_vout->fmt_in.i_visible_height * ll_zoom / ZOOM_FP_FACTOR;
+    }
 
      int64_t i_scaled_width = p_vout->fmt_in.i_visible_width * (int64_t)p_vout->fmt_in.i_sar_num *
                               *pi_height / p_vout->fmt_in.i_visible_height / p_vout->fmt_in.i_sar_den;
-- 
1.5.2.5

