gestures.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:13k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * gestures.c: control vlc with mouse gestures
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 VideoLAN
  5.  * $Id: gestures.c 8672 2004-09-09 14:02:24Z gbazin $
  6.  *
  7.  * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  * 
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <stdlib.h>                                      /* malloc(), free() */
  27. #include <string.h>
  28. #include <vlc/vlc.h>
  29. #include <vlc/intf.h>
  30. #include <vlc/vout.h>
  31. #ifdef HAVE_UNISTD_H
  32. #    include <unistd.h>
  33. #endif
  34. /*****************************************************************************
  35.  * intf_sys_t: description and status of interface
  36.  *****************************************************************************/
  37. struct intf_sys_t
  38. {
  39.     vlc_object_t *      p_vout;
  40.     input_thread_t *    p_input;
  41.     vlc_bool_t          b_got_gesture;
  42.     vlc_bool_t          b_button_pressed;
  43.     int                 i_mouse_x, i_mouse_y;
  44.     int                 i_last_x, i_last_y;
  45.     unsigned int        i_pattern;
  46.     int                 i_num_gestures;
  47.     int                 i_threshold;
  48.     int                 i_button_mask;
  49. };
  50. /*****************************************************************************
  51.  * Local prototypes.
  52.  *****************************************************************************/
  53. #define UP 1
  54. #define DOWN 2
  55. #define LEFT 3
  56. #define RIGHT 4
  57. #define NONE 0
  58. #define GESTURE( a, b, c, d ) (a | ( b << 4 ) | ( c << 8 ) | ( d << 12 ))
  59. int  E_(Open)   ( vlc_object_t * );
  60. void E_(Close)  ( vlc_object_t * );
  61. static int  InitThread     ( intf_thread_t *p_intf );
  62. static int  MouseEvent     ( vlc_object_t *, char const *,
  63.                              vlc_value_t, vlc_value_t, void * );
  64. /* Exported functions */
  65. static void RunIntf        ( intf_thread_t *p_intf );
  66. /*****************************************************************************
  67.  * Module descriptor
  68.  *****************************************************************************/
  69. #define THRESHOLD_TEXT N_( "Motion threshold (10-100)" )
  70. #define THRESHOLD_LONGTEXT N_( 
  71.     "Amount of movement required for a mouse" 
  72.     " gesture to be recorded." )
  73. #define BUTTON_TEXT N_( "Trigger button" )
  74. #define BUTTON_LONGTEXT N_( 
  75.     "You can set the trigger button for mouse gestures here." )
  76. static char *button_list[] = { "left", "middle", "right" };
  77. static char *button_list_text[] = { N_("Left"), N_("Middle"), N_("Right") };
  78. vlc_module_begin();
  79.     add_integer( "gestures-threshold", 30, NULL, THRESHOLD_TEXT, THRESHOLD_LONGTEXT, VLC_TRUE );
  80.     add_string( "gestures-button", "right", NULL,
  81.                 BUTTON_TEXT, BUTTON_LONGTEXT, VLC_FALSE );
  82.         change_string_list( button_list, button_list_text, 0 );
  83.     set_description( _("Mouse gestures control interface") );
  84.     set_capability( "interface", 0 );
  85.     set_callbacks( E_(Open), E_(Close) );
  86. vlc_module_end();
  87. /*****************************************************************************
  88.  * OpenIntf: initialize interface
  89.  *****************************************************************************/
  90. int E_(Open) ( vlc_object_t *p_this )
  91. {
  92.     intf_thread_t *p_intf = (intf_thread_t *)p_this;
  93.     /* Allocate instance and initialize some members */
  94.     p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
  95.     if( p_intf->p_sys == NULL )
  96.     {
  97.         return( 1 );
  98.     };
  99.     p_intf->pf_run = RunIntf;
  100.     return( 0 );
  101. }
  102. /*****************************************************************************
  103.  * gesture: return a subpattern within a pattern
  104.  *****************************************************************************/
  105. static int gesture( int i_pattern, int i_num )
  106. {
  107.     return ( i_pattern >> ( i_num * 4 ) ) & 0xF;
  108. }
  109.         
  110. /*****************************************************************************
  111.  * CloseIntf: destroy dummy interface
  112.  *****************************************************************************/
  113. void E_(Close) ( vlc_object_t *p_this )
  114. {
  115.     intf_thread_t *p_intf = (intf_thread_t *)p_this;
  116.     /* Destroy structure */
  117.     free( p_intf->p_sys );
  118. }
  119. /*****************************************************************************
  120.  * RunIntf: main loop
  121.  *****************************************************************************/
  122. static void RunIntf( intf_thread_t *p_intf )
  123. {
  124.     playlist_t * p_playlist = NULL;
  125.     p_intf->p_sys->p_vout = NULL;
  126.     if( InitThread( p_intf ) < 0 )
  127.     {
  128.         msg_Err( p_intf, "can't initialize intf" );
  129.         return;
  130.     }
  131.     msg_Dbg( p_intf, "intf initialized" );
  132.     /* Main loop */
  133.     while( !p_intf->b_die )
  134.     {
  135.         vlc_mutex_lock( &p_intf->change_lock );
  136.         /* 
  137.          * mouse cursor
  138.          */
  139.         if( p_intf->p_sys->b_got_gesture )
  140.         {
  141.             /* Do something */
  142.             switch( p_intf->p_sys->i_pattern )
  143.             {
  144.             case LEFT:
  145.                 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
  146.                                               FIND_ANYWHERE );
  147.                 if( p_playlist == NULL )
  148.                 {
  149.                     break;
  150.                 }
  151.                 
  152.                 playlist_Prev( p_playlist );
  153.                 vlc_object_release( p_playlist );
  154.                 break;
  155.             case RIGHT:
  156.                 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
  157.                                               FIND_ANYWHERE );
  158.                 if( p_playlist == NULL )
  159.                 {
  160.                     break;
  161.                 }
  162.                 
  163.                 playlist_Next( p_playlist );
  164.                 vlc_object_release( p_playlist );
  165.                 break;
  166.             case GESTURE(UP,RIGHT,NONE,NONE):
  167.                 if (p_intf->p_sys->p_vout )
  168.                 {
  169.                     ((vout_thread_t *)p_intf->p_sys->p_vout)->i_changes |=
  170.                         VOUT_FULLSCREEN_CHANGE;
  171.                 }
  172.                 break;
  173.             case GESTURE(DOWN,RIGHT,NONE,NONE):
  174.                 /* FIXME: Should close the vout!"*/
  175.                 p_intf->p_vlc->b_die = VLC_TRUE;
  176.                 break;
  177.             case GESTURE(DOWN,LEFT,UP,RIGHT):
  178.                 msg_Dbg(p_intf, "a square!" );
  179.                 break;
  180.             default:
  181.                 break;
  182.             }
  183.             p_intf->p_sys->i_num_gestures = 0;
  184.             p_intf->p_sys->i_pattern = 0;
  185.             p_intf->p_sys->b_got_gesture = VLC_FALSE;
  186.         }
  187.                 
  188.         vlc_mutex_unlock( &p_intf->change_lock );
  189.         /* 
  190.          * video output
  191.          */
  192.         if( p_intf->p_sys->p_vout && p_intf->p_sys->p_vout->b_die )
  193.         {
  194.             var_DelCallback( p_intf->p_sys->p_vout, "mouse-moved",
  195.                              MouseEvent, p_intf );
  196.             var_DelCallback( p_intf->p_sys->p_vout, "mouse-button-down",
  197.                              MouseEvent, p_intf );
  198.             vlc_object_release( p_intf->p_sys->p_vout );
  199.             p_intf->p_sys->p_vout = NULL;
  200.         }
  201.         if( p_intf->p_sys->p_vout == NULL )
  202.         {
  203.             p_intf->p_sys->p_vout = vlc_object_find( p_intf,
  204.                                       VLC_OBJECT_VOUT, FIND_ANYWHERE );
  205.             if( p_intf->p_sys->p_vout )
  206.             {
  207.                 var_AddCallback( p_intf->p_sys->p_vout, "mouse-moved",
  208.                                  MouseEvent, p_intf );
  209.                 var_AddCallback( p_intf->p_sys->p_vout, "mouse-button-down",
  210.                                  MouseEvent, p_intf );
  211.             }
  212.         }
  213.         /* Wait a bit */
  214.         msleep( INTF_IDLE_SLEEP );
  215.     }
  216.     if( p_intf->p_sys->p_vout )
  217.     {
  218.         var_DelCallback( p_intf->p_sys->p_vout, "mouse-moved",
  219.                          MouseEvent, p_intf );
  220.         var_DelCallback( p_intf->p_sys->p_vout, "mouse-button-down",
  221.                          MouseEvent, p_intf );
  222.         vlc_object_release( p_intf->p_sys->p_vout );
  223.     }
  224. }
  225. /*****************************************************************************
  226.  * InitThread:
  227.  *****************************************************************************/
  228. static int InitThread( intf_thread_t * p_intf )
  229. {
  230.     char *psz_button;
  231.     /* we might need some locking here */
  232.     if( !p_intf->b_die )
  233.     {
  234.         input_thread_t * p_input;
  235.         p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_PARENT );
  236.         vlc_mutex_lock( &p_intf->change_lock );
  237.         p_intf->p_sys->p_input = p_input;
  238.         p_intf->p_sys->b_got_gesture = VLC_FALSE;
  239.         p_intf->p_sys->b_button_pressed = VLC_FALSE;
  240.         p_intf->p_sys->i_threshold = config_GetInt( p_intf, "gestures-threshold" );
  241.         psz_button = config_GetPsz( p_intf, "gestures-button" );
  242.         if ( !strcmp( psz_button, "left" ) )
  243.         {
  244.             p_intf->p_sys->i_button_mask = 1;
  245.         }
  246.         else if ( !strcmp( psz_button, "middle" ) )
  247.         {
  248.             p_intf->p_sys->i_button_mask = 2;
  249.         }
  250.         else if ( !strcmp( psz_button, "right" ) )
  251.         {
  252.             p_intf->p_sys->i_button_mask = 4;
  253.         }
  254.         p_intf->p_sys->i_pattern = 0;
  255.         p_intf->p_sys->i_num_gestures = 0;
  256.         vlc_mutex_unlock( &p_intf->change_lock );
  257.         return 0;
  258.     }
  259.     else
  260.     {
  261.         return -1;
  262.     }
  263. }
  264. /*****************************************************************************
  265.  * MouseEvent: callback for mouse events
  266.  *****************************************************************************/
  267. static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
  268.                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
  269. {
  270.     vlc_value_t val;
  271.     int pattern = 0;
  272.     
  273.     signed int i_horizontal, i_vertical;
  274.     intf_thread_t *p_intf = (intf_thread_t *)p_data;
  275.     /* don't process new gestures before the last events are processed */
  276.     if( p_intf->p_sys->b_got_gesture ) {
  277.         return VLC_SUCCESS;
  278.     }
  279.     vlc_mutex_lock( &p_intf->change_lock );
  280.     if( !strcmp(psz_var, "mouse-moved" ) && p_intf->p_sys->b_button_pressed ) {
  281.         var_Get( p_intf->p_sys->p_vout, "mouse-x", &val );
  282.         p_intf->p_sys->i_mouse_x = val.i_int;
  283.         var_Get( p_intf->p_sys->p_vout, "mouse-y", &val );
  284.         p_intf->p_sys->i_mouse_y = val.i_int;
  285.         i_horizontal = p_intf->p_sys->i_mouse_x -
  286.             p_intf->p_sys->i_last_x;
  287.         i_horizontal = i_horizontal / p_intf->p_sys->i_threshold;
  288.         i_vertical = p_intf->p_sys->i_mouse_y
  289.             - p_intf->p_sys->i_last_y;
  290.         i_vertical = i_vertical / p_intf->p_sys->i_threshold;
  291.         
  292.         if ( i_horizontal < 0 )
  293.         {
  294.             msg_Dbg( p_intf, "left gesture(%d)", i_horizontal );
  295.             pattern = LEFT;
  296.         }
  297.         else if ( i_horizontal > 0 )
  298.         {
  299.             msg_Dbg( p_intf, "right gesture(%d)", i_horizontal );
  300.             pattern = RIGHT;
  301.         }
  302.         if ( i_vertical < 0 )
  303.         {
  304.             msg_Dbg( p_intf, "up gesture(%d)", i_vertical );
  305.             pattern = UP;
  306.         }
  307.         else if ( i_vertical > 0 )
  308.         {
  309.             msg_Dbg( p_intf, "down gesture(%d)", i_vertical );
  310.             pattern = DOWN;
  311.         }
  312.         if (pattern )
  313.         {
  314.             p_intf->p_sys->i_last_y = p_intf->p_sys->i_mouse_y;
  315.             p_intf->p_sys->i_last_x = p_intf->p_sys->i_mouse_x;
  316.             if( gesture(p_intf->p_sys->i_pattern, p_intf->p_sys->i_num_gestures - 1 ) != pattern )
  317.             {
  318.                 p_intf->p_sys->i_pattern |= pattern << ( p_intf->p_sys->i_num_gestures * 4 );
  319.                 p_intf->p_sys->i_num_gestures++;
  320.             }
  321.         }
  322.     }
  323.     if( !strcmp( psz_var, "mouse-button-down" ) && newval.i_int & p_intf->p_sys->i_button_mask
  324.         && !p_intf->p_sys->b_button_pressed )
  325.     {
  326.         p_intf->p_sys->b_button_pressed = VLC_TRUE;
  327.         var_Get( p_intf->p_sys->p_vout, "mouse-x", &val );
  328.         p_intf->p_sys->i_last_x = val.i_int;
  329.         var_Get( p_intf->p_sys->p_vout, "mouse-y", &val );
  330.         p_intf->p_sys->i_last_y = val.i_int;
  331.     }
  332.     if( !strcmp( psz_var, "mouse-button-down" ) && !( newval.i_int & p_intf->p_sys->i_button_mask )
  333.         && p_intf->p_sys->b_button_pressed )
  334.     {
  335.         p_intf->p_sys->b_button_pressed = VLC_FALSE;
  336.         p_intf->p_sys->b_got_gesture = VLC_TRUE;
  337.     }
  338.     vlc_mutex_unlock( &p_intf->change_lock );
  339.     return VLC_SUCCESS;
  340. }