* joystick.c: control vlc with a joystick
*****************************************************************************
* Copyright (C) 2002 VideoLAN
- * $Id: joystick.c,v 1.1 2003/07/20 08:30:41 zorglub Exp $
+ * $Id: joystick.c,v 1.2 2003/07/31 08:18:30 zorglub Exp $
*
* Authors: Clément Stenac <zorglub@via.ecp.fr>
*
/* Default values for parameters */
#define DEFAULT_MAX_SEEK 10 /* seconds */
-#define DEFAULT_REPEAT 100000
-#define DEFAULT_WAIT 500000
+#define DEFAULT_REPEAT 100
+#define DEFAULT_WAIT 500
#define DEFAULT_DEVICE "/dev/input/js0"
#define DEFAULT_THRESHOLD 12000 /* 0 -> 32767 */
-/* Actions
+#define DEFAULT_MAPPING \
+ "{axis-0-up=forward,axis-0-down=back," \
+ "axis-1-up=next,axis-1-down=prev," \
+ "butt-1-down=play,butt-2-down=fullscreen}"
+
+/* Default Actions (used if there are missing actions in the default
* Available actions are: Next,Prev, Forward,Back,Play,Fullscreen,dummy */
#define AXE_0_UP_ACTION Forward
#define AXE_0_DOWN_ACTION Back
* Local prototypes.
*****************************************************************************/
-int Open ( vlc_object_t * );
-void Close ( vlc_object_t * );
-static int Init ( intf_thread_t *p_intf );
-int handle_event ( intf_thread_t *p_intf, struct js_event event);
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+static int Init ( intf_thread_t *p_intf );
+
+static int handle_event ( intf_thread_t *p_intf, struct js_event event );
/* Actions */
-int Next (intf_thread_t *p_intf);
-int Prev (intf_thread_t *p_intf);
-int Back (intf_thread_t *p_intf);
-int Forward (intf_thread_t *p_intf);
-int Play (intf_thread_t *p_intf);
-int Fullscreen (intf_thread_t *p_intf);
+static int Next (intf_thread_t *p_intf);
+static int Prev (intf_thread_t *p_intf);
+static int Back (intf_thread_t *p_intf);
+static int Forward (intf_thread_t *p_intf);
+static int Play (intf_thread_t *p_intf);
+static int Fullscreen (intf_thread_t *p_intf);
-int dummy (intf_thread_t *p_intf);
+static int dummy (intf_thread_t *p_intf);
/* Exported functions */
static void Run ( intf_thread_t *p_intf );
*****************************************************************************/
#define THRESHOLD_TEXT N_( "Motion threshold" )
#define THRESHOLD_LONGTEXT N_( \
- "the amount of joystick movement required for a movement to be" \
- "recorded" )
+ "The amount of joystick movement required for a movement to be " \
+ "recorded (0->32767)" )
#define DEVICE_TEXT N_( "Joystick device" )
#define DEVICE_LONGTEXT N_( \
- "the device for the joystick (usually /dev/jsX or /dev/input/jsX" \
- "with X the number of the joystick" )
+ "The joystick device (usually /dev/js0 or /dev/input/js0)")
#define REPEAT_TEXT N_( "Repeat time" )
#define REPEAT_LONGTEXT N_( \
- "the time waited before the action is repeated if it is still trigered" \
- "in miscroseconds" )
+ "The time waited before the action is repeated if it is still trigered, " \
+ "in milliseconds" )
-#define WAIT_TEXT N_( "Wait before repeat time")
+#define WAIT_TEXT N_( "Wait time")
#define WAIT_LONGTEXT N_(\
- " the time waited before the repeat starts, in microseconds")
+ "The time waited before the repeat starts, in milliseconds ")
#define SEEK_TEXT N_( "Max seek interval")
#define SEEK_LONGTEXT N_(\
- " the number of seconds that will be seeked if the axis "\
- "is pushed at its maximum" )
+ "The maximum number of seconds that will be seeked at a time." )
+
+#define MAP_TEXT N_( "Action mapping")
+#define MAP_LONGTEXT N_(\
+ "Allows you to remap the actions. For details," \
+ " please have a look at http://wiki.videolan.org/index.php/Joystick" )
vlc_module_begin();
add_category_hint( N_( "Joystick" ), NULL, VLC_FALSE );
- add_integer( "motion-threshold", 15000, NULL,
+ add_integer( "motion-threshold", DEFAULT_THRESHOLD , NULL,
THRESHOLD_TEXT, THRESHOLD_LONGTEXT, VLC_TRUE );
add_string( "joystick-device", DEFAULT_DEVICE , NULL,
DEVICE_TEXT, DEVICE_LONGTEXT, VLC_TRUE );
WAIT_TEXT, WAIT_LONGTEXT, VLC_TRUE );
add_integer ("joystick-max-seek",DEFAULT_MAX_SEEK,NULL,
SEEK_TEXT, SEEK_LONGTEXT, VLC_TRUE );
+ add_string("joystick-mapping",DEFAULT_MAPPING,NULL,
+ MAP_TEXT,MAP_LONGTEXT, VLC_TRUE );
set_description( _("joystick control interface") );
set_capability( "interface", 0 );
set_callbacks( Open, Close );
vlc_module_end();
/*****************************************************************************
- * OpenIntf: initialize interface
+ * Open: initialize interface
*****************************************************************************/
-int Open ( vlc_object_t *p_this )
+static int Open ( vlc_object_t *p_this )
{
intf_thread_t *p_intf = (intf_thread_t *)p_this;
}
/*****************************************************************************
- * CloseIntf: destroy the interface
+ * Close: destroy the interface
*****************************************************************************/
-void Close ( vlc_object_t *p_this )
+static void Close ( vlc_object_t *p_this )
{
intf_thread_t *p_intf = (intf_thread_t *)p_this;
static int Init( intf_thread_t * p_intf )
{
char *psz_device;
+ char *psz_parse;
+ char *psz_eof; /* end of field */
if( !p_intf->b_die )
{
return -1;
}
- p_intf->p_sys->i_repeat =
+ p_intf->p_sys->i_repeat = 1000*
config_GetInt( p_intf, "joystick-repeat");
- p_intf->p_sys->i_wait =
+ p_intf->p_sys->i_wait = 1000*
config_GetInt( p_intf, "joystick-wait");
p_intf->p_sys->i_threshold =
p_intf->p_sys->i_maxseek =
config_GetInt( p_intf, "joystick-max-seek" );
- p_intf->p_sys->axes[0].pf_actup = AXE_0_UP_ACTION;
- p_intf->p_sys->axes[0].pf_actdown = AXE_0_DOWN_ACTION;
- p_intf->p_sys->axes[0].b_trigered = VLC_FALSE;
- p_intf->p_sys->axes[0].l_time = 0;
-
- p_intf->p_sys->axes[1].pf_actup = AXE_1_UP_ACTION;
- p_intf->p_sys->axes[1].pf_actdown = AXE_1_DOWN_ACTION;
- p_intf->p_sys->axes[1].b_trigered = VLC_FALSE;
- p_intf->p_sys->axes[1].l_time = 0;
+
+ psz_parse = config_GetPsz( p_intf, "joystick-mapping" ) ;
+
+ if ( ! psz_parse)
+ {
+ msg_Warn (p_intf,"Invalid mapping. Aborting" );
+ return -1;
+ }
+ if( !strlen( psz_parse ) )
+ {
+ msg_Warn( p_intf, "Invalid mapping. Aborting" );
+ return -1;
+ }
+ p_intf->p_sys->axes[0].pf_actup = AXE_0_UP_ACTION;
+ p_intf->p_sys->axes[0].pf_actdown = AXE_0_DOWN_ACTION;
+ p_intf->p_sys->axes[1].pf_actup = AXE_1_UP_ACTION;
+ p_intf->p_sys->axes[1].pf_actdown = AXE_1_DOWN_ACTION;
+
p_intf->p_sys->buttons[0].pf_actdown = BUTTON_1_PRESS_ACTION;
p_intf->p_sys->buttons[0].pf_actup = BUTTON_1_RELEASE_ACTION;
p_intf->p_sys->buttons[1].pf_actdown = BUTTON_2_PRESS_ACTION;
p_intf->p_sys->buttons[1].pf_actup = BUTTON_2_RELEASE_ACTION;
+/* Macro to parse the command line */
+#define PARSE(name,function) \
+ if(!strncmp( psz_parse , name , strlen( name ) ) ) \
+ { \
+ psz_parse += strlen( name ); \
+ psz_eof = strchr( psz_parse , ',' ); \
+ if( !psz_eof) \
+ psz_eof = strchr( psz_parse, '}' ); \
+ if( !psz_eof) \
+ psz_eof = psz_parse + strlen(psz_parse); \
+ if( psz_eof ) \
+ { \
+ *psz_eof = '\0' ; \
+ } \
+ msg_Dbg(p_intf,"%s -> %s", name,psz_parse) ; \
+ if(!strcasecmp( psz_parse , "play" ) ) function = Play; \
+ if(!strcasecmp( psz_parse , "next" ) ) function = Next; \
+ if(!strcasecmp( psz_parse , "prev" ) ) function = Prev; \
+ if(!strcasecmp( psz_parse , "fullscreen" ) ) function = Fullscreen; \
+ if(!strcasecmp( psz_parse , "forward" ) ) function = Forward; \
+ if(!strcasecmp( psz_parse , "back" ) ) function = Back; \
+ psz_parse = psz_eof; \
+ psz_parse ++; \
+ continue; \
+ } \
+
+ while(1)
+ {
+ PARSE("axis-0-up=" ,p_intf->p_sys->axes[0].pf_actup );
+ PARSE("axis-0-down=" ,p_intf->p_sys->axes[0].pf_actdown );
+ PARSE("axis-1-up=" ,p_intf->p_sys->axes[1].pf_actup );
+ PARSE("axis-1-down=" ,p_intf->p_sys->axes[1].pf_actdown );
+
+ PARSE("butt-1-up=" ,p_intf->p_sys->buttons[0].pf_actup );
+ PARSE("butt-1-down=" ,p_intf->p_sys->buttons[0].pf_actdown );
+ PARSE("butt-2-up=" ,p_intf->p_sys->buttons[1].pf_actup );
+ PARSE("butt-2-down=" ,p_intf->p_sys->buttons[1].pf_actdown );
+
+ if( *psz_parse )
+ psz_parse++;
+ else
+ break;
+ }
+
+ p_intf->p_sys->axes[0].b_trigered = VLC_FALSE;
+ p_intf->p_sys->axes[0].l_time = 0;
+
+ p_intf->p_sys->axes[1].b_trigered = VLC_FALSE;
+ p_intf->p_sys->axes[1].l_time = 0;
+
vlc_mutex_unlock( &p_intf->change_lock );
return 0;
/*****************************************************************************
* handle_event : parse a joystick event and takes the appropriate action *
*****************************************************************************/
-int handle_event ( intf_thread_t *p_intf, struct js_event event)
+static int handle_event ( intf_thread_t *p_intf, struct js_event event)
{
unsigned int i_axe;
* triggering something */
if( event.number == 2 &&
/* Try to avoid Parkinson joysticks */
- abs(event.value - p_intf->p_sys->axes[2].i_value) > 10 )
+ abs(event.value - p_intf->p_sys->axes[2].i_value) > 200 )
{
p_intf->p_sys->axes[2].i_value = event.value;
msg_Dbg( p_intf , "Updating volume" );
}
/* Special for seeking */
- p_intf->p_sys->f_seconds =
+ p_intf->p_sys->f_seconds = 1+
(abs(event.value)-p_intf->p_sys->i_threshold)*
- p_intf->p_sys->i_maxseek/
+ (p_intf->p_sys->i_maxseek - 1 )/
(32767-p_intf->p_sys->i_threshold);
}
/****************************************************************************
- * The possible actions
+ * The actions
****************************************************************************/
-int Next( intf_thread_t *p_intf)
+/* Go to next item in the playlist */
+static int Next( intf_thread_t *p_intf)
{
playlist_t *p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
FIND_ANYWHERE );
return 0;
}
-int Prev( intf_thread_t *p_intf)
+/* Go to previous item in the playlist */
+static int Prev( intf_thread_t *p_intf)
{
playlist_t *p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
FIND_ANYWHERE );
return 0;
}
-int Forward(intf_thread_t *p_intf)
+/* Seek forward */
+static int Forward(intf_thread_t *p_intf)
{
- msg_Dbg(p_intf,"Seeking %f seconds",p_intf->p_sys->f_seconds);
- input_Seek( p_intf->p_sys->p_input, p_intf->p_sys->f_seconds,
+ if(p_intf->p_sys->p_input)
+ {
+ msg_Dbg(p_intf,"Seeking %f seconds",p_intf->p_sys->f_seconds);
+ input_Seek( p_intf->p_sys->p_input, p_intf->p_sys->f_seconds,
INPUT_SEEK_SECONDS | INPUT_SEEK_CUR);
return 0;
+ }
+ return -1;
}
-int Back(intf_thread_t *p_intf)
+/* Seek backwards */
+static int Back(intf_thread_t *p_intf)
{
- msg_Dbg(p_intf,"Seeking %f seconds",p_intf->p_sys->f_seconds);
- input_Seek( p_intf->p_sys->p_input, -(p_intf->p_sys->f_seconds),
+ if(p_intf->p_sys->p_input)
+ {
+ msg_Dbg(p_intf,"Seeking -%f seconds",p_intf->p_sys->f_seconds);
+ input_Seek( p_intf->p_sys->p_input, -(p_intf->p_sys->f_seconds),
INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
- return 0;
+ return 0;
+ }
+ return -1;
}
-int Play(intf_thread_t *p_intf)
+/* Toggle Play/Pause */
+static int Play(intf_thread_t *p_intf)
{
- input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
- return 0;
+ if(p_intf->p_sys->p_input)
+ {
+ input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
+ return 0;
+ }
+ return -1;
}
-int Fullscreen(intf_thread_t *p_intf)
+/* Toggle fullscreen mode */
+static int Fullscreen(intf_thread_t *p_intf)
{
vout_thread_t * p_vout=vlc_object_find(p_intf,
VLC_OBJECT_VOUT, FIND_ANYWHERE );
}
/* dummy event. Use it if you don't wan't anything to happen */
-int dummy(intf_thread_t *p_intf)
+static int dummy(intf_thread_t *p_intf)
{
return 0;
}
-<html>
-<head>
+<?xml version="1.0" encoding="iso-8859-1" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml10/DTD/xhtml10transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
<title>VLC Media Player</title>
+ <style type="css">
+ body {font-family:Verdana, Arial, Sans Serif; }
+ h2 { text-align:center; }
+ table {width:100%;}
+ table.add {width:70%;}
+ div.section {background-color:#FFFFCC;
+ border:1pt black solid;
+ margin-bottom:2em;
+ padding:0.5em;}
+ div.sectitle { background-color:#FFFF99;
+ color:#019;
+ border:1pt black solid;
+ width:20%;
+ font-weight:bold;}
+ tr.ligne1 { background-color:#FFFFEE; }
+ tr.ligne2 { background-color:#FFFFAA; }
+ </style>
<vlc id="if" param1="url_param"/>
<meta http-equiv="refresh" content="0;URL=/" />
<vlc id="end" />
<vlc id="control" param1="stop,pause,previous,next,add,sout,play" />
<vlc id="set" param1="sout" param2="string" />
-</head>
-<body>
- <h2><center><a href="http://www.videolan.org">VLC Media Player <vlc id="value" param1="version" /></a> (http interface)</center></h2>
- <hr/>
- <td>
- <form method="get" action="">
- <input type="submit" name="control" value="stop" />
- <input type="submit" name="control" value="pause" />
- <input type="submit" name="control" value="previous" />
- <input type="submit" name="control" value="next" />
- <a href="info.html">infos</a>
- </form>
- </td>
- <br />
- <td>
- <form method="get" action="" enctype="text/plain" >
- <input type="text" name="mrl" size="40" />
- <input type="submit" name="control" value="add" />
- </form>
- </td>
- <td>
- <form method="get" action="" enctype="text/plain" >
- <input type="text" name="sout" size="30" value="<vlc id="get" param1="sout" param2="string" />" />
- <input type="submit" name="control" value="sout" />
- </form>
- </td>
- <hr/>
- <p>
+ </head>
+ <body>
+ <h2>
+ <a href="http://www.videolan.org">VLC Media Player <vlc id="value" param1="version" /></a> (http interface)</h2>
+ <div class="sectitle">Control VLC</div>
+ <div class="section">
+ <form method="get" action="">
+ <table class="add">
+ <tr>
+ <td><input type="submit" name="control" value="stop" /></td>
+ <td><input type="submit" name="control" value="pause" /></td>
+ <td><input type="submit" name="control" value="previous" /></td>
+ <td><input type="submit" name="control" value="next" /></td>
+ <td><a href="admin/">Administration</a></td>
+ </tr>
+ </table>
+ </form>
+ </div>
+ <div class="sectitle">Add</div>
+ <div class="section">
+ <form method="get" action="" enctype="text/plain" >
+ <table class="add">
+ <tr>
+ <td>Add a MRL (Media Resource Locator) to the playlist</td>
+ <td><input type="text" name="mrl" size="40" /></td>
+ <td><input type="submit" name="control" value="add" /></td>
+ </tr>
+ <tr>
+ <td>Stream Output:</td>
+ <td><input type="text" name="sout" size="40" value="<vlc id="get" param1="sout" param2="string" />" /></td>
+ <td><input type="submit" name="control" value="sout" /></td>
+ </tr>
+ </table>
+ </form>
+ </div>
+
+ <div class="sectitle">VLC Playlist</div>
+ <div class="section">
+ <table>
<vlc id="foreach" param1="pl" param2="playlist" />
- <vlc id="if" param1="pl.current" />
+ <tr class="<vlc id="if" param1="2 pl.index % 0 =" />ligne1<vlc id="else" />ligne2<vlc id="end" />">
+ <td>
+ <vlc id="if" param1="pl.current" />
<b>
<vlc id="end" />
- <a href=?control=play&item=<vlc id="value" param1="pl.index" />><vlc id="value" param1="pl.index" /> - <vlc id="value" param1="pl.name" /></a> <br />
- <vlc id="if" param1="pl.current" />
+ <a href="?control=play&item=<vlc id="value" param1="pl.index" />"><vlc id="value" param1="pl.index" /> - <vlc id="value" param1="pl.name" /></a> <vlc id="if" param1="pl.current" />
</b>
<vlc id="end" />
-
+ </td></tr>
<vlc id="end" />
- </p>
+ </table>
+ </div>
<hr/>
<p> <vlc id="value" param1="copyright" /> </p>
</body>