[vlc-devel] [PATCH/RFC] Add hotkey to rotate video.

Matthias Keiser matthias at tristan-inc.com
Tue Apr 1 10:40:25 CEST 2014


I'm not sure this is the right way to do this, however this:
- works with all video output modules
- can be applied on the fly

---
 include/vlc_keys.h        |   1 +
 modules/control/hotkeys.c | 171 +++++++++++++++++++++++++++++++++++++++++++++-
 src/config/keys.c         |   1 +
 src/libvlc-module.c       |   7 ++
 4 files changed, 179 insertions(+), 1 deletion(-)

diff --git a/include/vlc_keys.h b/include/vlc_keys.h
index aafa589..c95d8aa 100644
--- a/include/vlc_keys.h
+++ b/include/vlc_keys.h
@@ -200,6 +200,7 @@ typedef enum vlc_action {
     ACTIONID_UNCROP_BOTTOM,
     ACTIONID_CROP_RIGHT,
     ACTIONID_UNCROP_RIGHT,
+    ACTIONID_ROTATE_90,
     ACTIONID_RANDOM,
     ACTIONID_LOOP,
     ACTIONID_WALLPAPER,
diff --git a/modules/control/hotkeys.c b/modules/control/hotkeys.c
index 1e7fcdf..fc5dce1 100644
--- a/modules/control/hotkeys.c
+++ b/modules/control/hotkeys.c
@@ -840,8 +840,177 @@ static int PutAction( intf_thread_t *p_intf, int i_action )
             if( p_vout )
                 var_DecInteger( p_vout, "crop-right" );
             break;
+        case ACTIONID_ROTATE_90:
+        {
+
+            typedef struct {
+                char           *name;
+                config_chain_t *cfg;
+            } module_cfg_t;
+
+            const char *psz_cfg = var_InheritString( p_vout, "video-filter" );
+
+            vlc_array_t filter_array;
+            vlc_array_init( &filter_array );
+
+            bool b_prev_hotkey = false;
+            const char *psz_needed_transform;
+
+            char *current = psz_cfg ? strdup( psz_cfg ) : NULL;
+
+            // Create a module_cfg_t for every existing filter
+
+            while( current )
+            {
+                config_chain_t *cfg;
+                char *name;
+                char *next = config_ChainCreate( &name, &cfg, current );
+
+                if( name && *name )
+                {
+                    bool b_is_hotkey = false;
+
+                    if( !strcmp( name, "transform" ) && cfg ) {
+
+                        config_chain_t *cfg_elem = cfg;
+
+                        while( cfg_elem )
+                        {
+                            // Check if it is "our" transform filter
+                            if( !strcmp( cfg_elem->psz_name, "hotkey" ))
+                            {
+                                b_is_hotkey = true;
+                                break;
+                            }
+                            cfg_elem = cfg_elem->p_next;
+                        }
+                    }
+
+                    if( b_is_hotkey )
+                    {
+                        b_prev_hotkey = true;
+
+                        if( !strcmp( cfg->psz_value, "90" ))
+                            psz_needed_transform = "180";
+                        else if( !strcmp( cfg->psz_value, "180" ))
+                            psz_needed_transform = "270";
+                        else if( !strcmp( cfg->psz_value, "270" ))
+                            psz_needed_transform = NULL;
+                    }
+                    else
+                    {
+                        module_cfg_t *e = malloc( sizeof( *e ));
+                        e->name = name;
+                        e->cfg  = cfg;
+                        vlc_array_append(&filter_array, e);
+                    }
+                }
+                else if( cfg )
+                {
+                    config_ChainDestroy( cfg );
+                    free(name);
+                }
+
+                free( current );
+                current = next;
+            }
+            
+            const char *type = b_prev_hotkey ? psz_needed_transform : "90";
+
+            // Create the module_cfg_t for our transform filter if necessary
+            
+            if( type )
+            {
+                module_cfg_t *e = xmalloc( sizeof( *e ));
+
+                char config[100];
+                snprintf( config, 100, "transform{type=%s, hotkey=1}", type );
 
-         case ACTIONID_TOGGLE_AUTOSCALE:
+                char *next = config_ChainCreate( &e->name, &e->cfg, config );
+                vlc_array_append( &filter_array, e );
+
+                free( next );
+            }
+
+            // Reconstruct the "video-filter" config string.
+            // FIXME: This is painful, I'm pretty sure I'm doing this wrong...
+
+            int i_count = vlc_array_count( &filter_array );
+
+            char *psz_cfg_new = NULL;
+            size_t i_offset = 0;
+
+            for( int i = 0; i < i_count; i++ )
+            {
+                module_cfg_t *p_mc = vlc_array_item_at_index( &filter_array, i );
+
+                size_t i_buff_size = ( psz_cfg_new ? strlen( psz_cfg_new ) : 0 ) +
+                                     ( i > 0 ? 1 : 0 ) + /*:*/
+                                       strlen( p_mc->name ) + 1;
+
+                psz_cfg_new = realloc( psz_cfg_new, i_buff_size );
+
+                if( i == 0 )
+                {
+                    i_offset += sprintf(psz_cfg_new + i_offset, "%s", p_mc->name);
+                }
+                else
+                {
+                    i_offset += sprintf(psz_cfg_new + i_offset, ":%s", p_mc->name);
+                }
+
+                size_t i_cfg_count = 0;
+
+                config_chain_t *p_cfg = p_mc->cfg;
+
+                while( p_cfg )
+                {
+                    if( i_cfg_count == 0 )
+                    {
+                        i_buff_size = strlen( psz_cfg_new ) +
+                                      1 + /*"{"*/
+                                      strlen( p_cfg->psz_name ) +
+                                      1 + /*"="*/
+                                      strlen( p_cfg->psz_value ) +
+                                      2 ); /*"}\0"*/
+
+                        psz_cfg_new = realloc( psz_cfg_new, i_buff_size );
+                        i_offset += sprintf( psz_cfg_new + i_offset, "{%s=%s", p_cfg->psz_name, p_cfg->psz_value );
+                    }
+                    else
+                    {
+                        i_buff_size = strlen( psz_cfg_new ) +
+                                      2 + /*", "*/
+                                      strlen( p_cfg->psz_name ) +
+                                      1 + /*"="*/
+                                      strlen( p_cfg->psz_value ) +
+                                      2 ); /*"}\0"*/
+
+                        psz_cfg_new = realloc( psz_cfg_new, i_buff_size );
+                        i_offset += sprintf( psz_cfg_new + i_offset, ", %s=%s", p_cfg->psz_name, p_cfg->psz_value );
+                    }
+
+                    i_cfg_count++;
+                    p_cfg = p_cfg->p_next;
+                }
+
+                if( i_cfg_count )
+                {
+                    // realloced above
+                    i_offset += sprintf( psz_cfg_new + i_offset, "}" );
+                }
+
+                config_ChainDestroy( p_cfg );
+                free( p_mc->name );
+                free( p_mc );
+            }
+
+            vlc_array_destroy( filter_array );
+
+            var_SetString( p_vout, "video-filter", psz_cfg_new );
+            free( psz_cfg_new );
+        }
+        case ACTIONID_TOGGLE_AUTOSCALE:
             if( p_vout )
             {
                 float f_scalefactor = var_GetFloat( p_vout, "scale" );
diff --git a/src/config/keys.c b/src/config/keys.c
index 07c0d75..3e4761e 100644
--- a/src/config/keys.c
+++ b/src/config/keys.c
@@ -332,6 +332,7 @@ static const struct action actions[] =
     { "rate-normal", ACTIONID_RATE_NORMAL, },
     { "rate-slower-fine", ACTIONID_RATE_SLOWER_FINE, },
     { "record", ACTIONID_RECORD, },
+    { "rotate-90", ACTIONID_ROTATE_90, },
     { "set-bookmark1", ACTIONID_SET_BOOKMARK1, },
     { "set-bookmark10", ACTIONID_SET_BOOKMARK10, },
     { "set-bookmark2", ACTIONID_SET_BOOKMARK2, },
diff --git a/src/libvlc-module.c b/src/libvlc-module.c
index 85637bd..d216fcd 100644
--- a/src/libvlc-module.c
+++ b/src/libvlc-module.c
@@ -1424,6 +1424,9 @@ static const char *const mouse_wheel_texts[] =
 #define UNCROP_RIGHT_KEY_TEXT N_("Uncrop one pixel from the right of the video")
 #define UNCROP_RIGHT_KEY_LONGTEXT N_("Uncrop one pixel from the right of the video")
 
+#define ROTATE_90_KEY_TEXT N_("Rotate clockwise 90 degrees")
+#define ROTATE_90_KEY_LONGTEXT N_("Rotate clockwise 90 degrees")
+
 #define WALLPAPER_KEY_TEXT N_("Toggle wallpaper mode in video output")
 #define WALLPAPER_KEY_LONGTEXT N_( \
     "Toggle wallpaper mode in video output." )
@@ -2218,6 +2221,7 @@ vlc_module_begin ()
 #   define KEY_UNCROP_BOTTOM      "Alt+Shift+k"
 #   define KEY_CROP_RIGHT         "Alt+l"
 #   define KEY_UNCROP_RIGHT       "Alt+Shift+l"
+#   define KEY_ROTATE_90          "Command+Shift+Alt+r"
 
 /* the macosx-interface already has bindings */
 #   define KEY_ZOOM_QUARTER       NULL
@@ -2357,6 +2361,7 @@ vlc_module_begin ()
 #   define KEY_UNCROP_BOTTOM      "Alt+Shift+c"
 #   define KEY_CROP_RIGHT         "Alt+f"
 #   define KEY_UNCROP_RIGHT       "Alt+Shift+f"
+#   define KEY_ROTATE_90          "Ctrl+Alt+Shift+r"
 
 /* Zooming */
 #   define KEY_ZOOM_QUARTER       "Alt+1"
@@ -2544,6 +2549,8 @@ vlc_module_begin ()
              CROP_RIGHT_KEY_TEXT, CROP_RIGHT_KEY_LONGTEXT, true )
     add_key( "key-uncrop-right", KEY_UNCROP_RIGHT,
              UNCROP_RIGHT_KEY_TEXT, UNCROP_RIGHT_KEY_LONGTEXT, true )
+    add_key( "key-rotate-90", KEY_ROTATE_90,
+            ROTATE_90_KEY_TEXT, ROTATE_90_KEY_LONGTEXT, true )
     add_key( "key-random", KEY_RANDOM,
              RANDOM_KEY_TEXT, RANDOM_KEY_LONGTEXT, false )
     add_key( "key-loop", KEY_LOOP,
-- 
1.8.5.2 (Apple Git-48)




More information about the vlc-devel mailing list