From d69ab00d9d696ff207feb13db0819264eead11f0 Mon Sep 17 00:00:00 2001 From: Henri Fallon Date: Wed, 11 Apr 2001 02:01:24 +0000 Subject: [PATCH] - Ported the 0.2.0's channel changing functions - Cosmetic changes : the word 'vlan' is disappearing - network_ChannelJoin is still commented out as it's not in sync anymore with our channel server. Nitrox should fix this within a week. - X and Xv output : added autohide cursor as in SDL - X and Sv : keys 1 to 0 change channel - SDL : keys F1 to F10 change channel as I was not able to make 1..0 work --- include/common.h | 6 +- include/config.h.in | 18 +-- include/main.h | 6 +- include/netutils.h | 8 +- plugins/sdl/vout_sdl.c | 52 +++++++- plugins/x11/vout_x11.c | 118 +++++++++++++++--- plugins/x11/vout_xvideo.c | 115 ++++++++++++++--- src/interface/interface.c | 11 +- src/interface/intf_ctrl.c | 42 ++++--- src/interface/main.c | 46 ++++--- src/misc/netutils.c | 251 +++++++++++++++++++++++++++++++++++++- 11 files changed, 561 insertions(+), 112 deletions(-) diff --git a/include/common.h b/include/common.h index 7f90479644..04b8c86de7 100644 --- a/include/common.h +++ b/include/common.h @@ -3,7 +3,7 @@ * Collection of useful common types and macros definitions ***************************************************************************** * Copyright (C) 1998, 1999, 2000 VideoLAN - * $Id: common.h,v 1.29 2001/03/16 22:37:06 massiot Exp $ + * $Id: common.h,v 1.30 2001/04/11 02:01:24 henri Exp $ * * Authors: Samuel Hocevar * Vincent Seguin @@ -103,11 +103,11 @@ typedef struct intf_channel_s * p_intf_channel_t; /* Input */ struct input_thread_s; -struct input_vlan_s; +struct input_channel_s; struct input_cfg_s; typedef struct input_thread_s * p_input_thread_t; -typedef struct input_vlan_s * p_input_vlan_t; +typedef struct input_channel_s * p_input_channel_t; typedef struct input_cfg_s * p_input_cfg_t; /* Audio */ diff --git a/include/config.h.in b/include/config.h.in index 817bb3aca2..6f6177a35e 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -190,7 +190,7 @@ #define INPUT_BROADCAST_DEFAULT 0 /* - * Vlan method + * Channel method */ /* Default network interface and environment variable */ @@ -198,14 +198,14 @@ #define INPUT_IFACE_DEFAULT "eth0" /* Default server and port */ -#define INPUT_VLAN_SERVER_VAR "vlc_vlan_server" -#define INPUT_VLAN_SERVER_DEFAULT "138.195.139.95" -#define INPUT_VLAN_PORT_VAR "vlc_vlan_port" -#define INPUT_VLAN_PORT_DEFAULT 6010 - -/* Delay between vlan changes - this is required to avoid flooding the VLAN - * server */ -#define INPUT_VLAN_CHANGE_DELAY (mtime_t)(5*CLOCK_FREQ) +#define INPUT_CHANNEL_SERVER_VAR "vlc_channel_server" +#define INPUT_CHANNEL_SERVER_DEFAULT "138.195.139.95" +#define INPUT_CHANNEL_PORT_VAR "vlc_channel_port" +#define INPUT_CHANNEL_PORT_DEFAULT 6010 + +/* Delay between channel changes - this is required to avoid flooding the + * channel server */ +#define INPUT_CHANNEL_CHANGE_DELAY (mtime_t)(5*CLOCK_FREQ) /* Duration between the time we receive the data packet, and the time we will * mark it to be presented */ diff --git a/include/main.h b/include/main.h index d01d6e0086..c1806a3620 100644 --- a/include/main.h +++ b/include/main.h @@ -3,7 +3,7 @@ * Declaration and extern access to global program object. ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN - * $Id: main.h,v 1.14 2001/03/21 13:42:33 sam Exp $ + * $Id: main.h,v 1.15 2001/04/11 02:01:24 henri Exp $ * * Authors: Vincent Seguin * @@ -47,7 +47,7 @@ typedef struct /* Generic settings */ boolean_t b_audio; /* is audio output allowed ? */ boolean_t b_video; /* is video output allowed ? */ - boolean_t b_vlans; /* are vlans supported ? */ + boolean_t b_channels; /* is channel changing supported ? */ boolean_t b_dvd; /* DVD mode ? */ /* Unique threads */ @@ -60,7 +60,7 @@ typedef struct struct module_bank_s * p_bank; /* module bank */ p_playlist_t p_playlist; /* playlist */ p_intf_msg_t p_msg; /* messages interface data */ - p_input_vlan_t p_vlan; /* vlan library data */ + p_input_channel_t p_channel; /* channel library data */ } main_t; extern main_t *p_main; diff --git a/include/netutils.h b/include/netutils.h index 123134d8ec..fe5cfc6d8e 100644 --- a/include/netutils.h +++ b/include/netutils.h @@ -4,7 +4,7 @@ * modules. ***************************************************************************** * Copyright (C) 1999, 2000, 2001 VideoLAN - * $Id: netutils.h,v 1.9 2001/03/21 13:42:33 sam Exp $ + * $Id: netutils.h,v 1.10 2001/04/11 02:01:24 henri Exp $ * * Authors: Vincent Seguin * Henri Fallon @@ -24,9 +24,13 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/ +/* The channel without stream is 0 */ +#define COMMON_CHANNEL 0 + /***************************************************************************** * Prototypes *****************************************************************************/ int network_BuildLocalAddr ( struct sockaddr_in *, int, boolean_t ); int network_BuildRemoteAddr( struct sockaddr_in *, char * ); - +int network_ChannelJoin( int i_channel_id ); +int network_ChannelCreate( void ); diff --git a/plugins/sdl/vout_sdl.c b/plugins/sdl/vout_sdl.c index 74e55846cb..b0bf0f7514 100644 --- a/plugins/sdl/vout_sdl.c +++ b/plugins/sdl/vout_sdl.c @@ -2,7 +2,7 @@ * vout_sdl.c: SDL video output display method ***************************************************************************** * Copyright (C) 1998, 1999, 2000 VideoLAN - * $Id: vout_sdl.c,v 1.46 2001/04/06 09:15:47 sam Exp $ + * $Id: vout_sdl.c,v 1.47 2001/04/11 02:01:24 henri Exp $ * * Authors: Samuel Hocevar * Pierre Baillet @@ -52,6 +52,7 @@ /* FIXME: get rid of this */ #include "keystrokes.h" #include "main.h" +#include "netutils.h" /***************************************************************************** * FIXME: this file is ... * @@ -274,7 +275,7 @@ static void vout_Destroy( vout_thread_t *p_vout ) static int vout_Manage( vout_thread_t *p_vout ) { SDL_Event event; /* SDL event */ - Uint8 i_key; + char * p_key; /* Process events */ while( SDL_PollEvent(&event) ) @@ -326,9 +327,8 @@ static int vout_Manage( vout_thread_t *p_vout ) break; case SDL_KEYDOWN: /* if a key is pressed */ - i_key = event.key.keysym.sym; - switch( i_key ) + switch( event.key.keysym.sym ) { case SDLK_f: /* switch to fullscreen */ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE; @@ -357,11 +357,51 @@ static int vout_Manage( vout_thread_t *p_vout ) p_vout->b_interface = ! p_vout->b_interface; p_vout->i_changes |= VOUT_INTF_CHANGE; break; + + case SDLK_F10: + network_ChannelJoin( 0 ); + break; + case SDLK_F1: + network_ChannelJoin( 1 ); + break; + case SDLK_F2: + network_ChannelJoin( 2 ); + break; + case SDLK_F3: + network_ChannelJoin( 3 ); + break; + case SDLK_F4: + network_ChannelJoin( 4 ); + break; + case SDLK_F5: + network_ChannelJoin( 5 ); + break; + case SDLK_F6: + network_ChannelJoin( 6 ); + break; + case SDLK_F7: + network_ChannelJoin( 7 ); + break; + case SDLK_F8: + network_ChannelJoin( 8 ); + break; + case SDLK_F9: + network_ChannelJoin( 9 ); + break; + case SDLK_MENU: + p_main->p_intf->b_menu_change = 1; + break; + default: - if( intf_ProcessKey( p_main->p_intf, (char )i_key ) ) + p_key = SDL_GetKeyName( event.key.keysym.sym ) ; + if( intf_ProcessKey( p_main->p_intf, + (char )event.key.keysym.sym ) ) { - intf_DbgMsg( "unhandled key '%c' (%i)", (char)i_key, i_key ); } + intf_DbgMsg( "unhandled key '%c' (%i)", + (char)event.key.keysym.sym, + event.key.keysym.sym ); + } break; } break; diff --git a/plugins/x11/vout_x11.c b/plugins/x11/vout_x11.c index c8230ebafd..2fb70f5648 100644 --- a/plugins/x11/vout_x11.c +++ b/plugins/x11/vout_x11.c @@ -2,7 +2,7 @@ * vout_x11.c: X11 video output display method ***************************************************************************** * Copyright (C) 1998, 1999, 2000 VideoLAN - * $Id: vout_x11.c,v 1.17 2001/04/01 06:21:44 sam Exp $ + * $Id: vout_x11.c,v 1.18 2001/04/11 02:01:24 henri Exp $ * * Authors: Vincent Seguin * Samuel Hocevar @@ -60,6 +60,8 @@ #include "interface.h" #include "intf_msg.h" +#include "netutils.h" /* network_ChannelJoin */ + #include "main.h" /***************************************************************************** @@ -100,6 +102,9 @@ typedef struct vout_sys_s int i_ss_blanking; /* blanking mode */ int i_ss_exposure; /* exposure mode */ + /* Auto-hide cursor */ + mtime_t i_lastmoved; + /* Mouse pointer properties */ boolean_t b_mouse; /* is the mouse pointer displayed ? */ @@ -288,6 +293,10 @@ static int vout_Init( vout_thread_t *p_vout ) p_vout->i_bytes_per_line = p_vout->p_sys->p_ximage[0]->bytes_per_line; vout_SetBuffers( p_vout, p_vout->p_sys->p_ximage[ 0 ]->data, p_vout->p_sys->p_ximage[ 1 ]->data ); + + /* Set date for autohiding cursor */ + p_vout->p_sys->i_lastmoved = mdate(); + return( 0 ); } @@ -352,6 +361,8 @@ static int vout_Manage( vout_thread_t *p_vout ) XEvent xevent; /* X11 event */ boolean_t b_resized; /* window has been resized */ char i_key; /* ISO Latin-1 key */ + KeySym x_key_symbol; + /* Handle X11 events: ConfigureNotify events are parsed to know if the * output window's size changed, MapNotify and UnmapNotify to know if the @@ -360,7 +371,8 @@ static int vout_Manage( vout_thread_t *p_vout ) b_resized = 0; while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window, StructureNotifyMask | KeyPressMask | - ButtonPressMask | ButtonReleaseMask, &xevent ) + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask | Button1MotionMask , &xevent ) == True ) { /* ConfigureNotify event: prepare */ @@ -394,16 +406,73 @@ static int vout_Manage( vout_thread_t *p_vout ) /* Keyboard event */ else if( xevent.type == KeyPress ) { - if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) ) + /* We may have keys like F1 trough F12, ESC ... */ + x_key_symbol = XKeycodeToKeysym( p_vout->p_sys->p_display, + xevent.xkey.keycode, 0 ); + switch( x_key_symbol ) { - /* FIXME: handle stuff here */ - switch( i_key ) - { - case 'q': - /* FIXME: need locking ! */ - p_main->p_intf->b_die = 1; - break; - } + case XK_Escape: + p_main->p_intf->b_die = 1; + break; + case XK_Menu: + p_main->p_intf->b_menu_change = 1; + break; + default: + /* "Normal Keys" + * The reason why I use this instead of XK_0 is that + * with XLookupString, we don't have to care about + * keymaps. */ + + if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) ) + { + /* FIXME: handle stuff here */ + switch( i_key ) + { + case 'q': + case 'Q': + p_main->p_intf->b_die = 1; + break; + case '0': + network_ChannelJoin( 0 ); + break; + case '1': + network_ChannelJoin( 1 ); + break; + case '2': + network_ChannelJoin( 2 ); + break; + case '3': + network_ChannelJoin( 3 ); + break; + case '4': + network_ChannelJoin( 4 ); + break; + case '5': + network_ChannelJoin( 5 ); + break; + case '6': + network_ChannelJoin( 6 ); + break; + case '7': + network_ChannelJoin( 7 ); + break; + case '8': + network_ChannelJoin( 8 ); + break; + case '9': + network_ChannelJoin( 9 ); + break; + default: + if( intf_ProcessKey( p_main->p_intf, + (char )i_key ) ) + { + intf_DbgMsg( "unhandled key '%c' (%i)", + (char)i_key, i_key ); + } + break; + } + } + break; } } /* Mouse click */ @@ -415,10 +484,6 @@ static int vout_Manage( vout_thread_t *p_vout ) /* in this part we will eventually manage * clicks for DVD navigation for instance */ break; - - case Button2: - X11TogglePointer( p_vout ); - break; } } /* Mouse release */ @@ -432,6 +497,15 @@ static int vout_Manage( vout_thread_t *p_vout ) break; } } + /* Mouse move */ + else if( xevent.type == MotionNotify ) + { + p_vout->p_sys->i_lastmoved = mdate(); + if( ! p_vout->p_sys->b_mouse ) + { + X11TogglePointer( p_vout ); + } + } #ifdef DEBUG /* Other event */ else @@ -519,6 +593,17 @@ static int vout_Manage( vout_thread_t *p_vout ) p_vout->i_width, p_vout->i_height); } + /* Autohide Cursour */ + if( mdate() - p_vout->p_sys->i_lastmoved > 2000000 ) + { + /* Hide the mouse automatically */ + if( p_vout->p_sys->b_mouse ) + { + X11TogglePointer( p_vout ); + } + } + + return 0; } @@ -693,7 +778,8 @@ static int X11CreateWindow( vout_thread_t *p_vout ) XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window, StructureNotifyMask | KeyPressMask | - ButtonPressMask | ButtonReleaseMask ); + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask ); if( XDefaultDepth(p_vout->p_sys->p_display, p_vout->p_sys->i_screen) == 8 ) { diff --git a/plugins/x11/vout_xvideo.c b/plugins/x11/vout_xvideo.c index 197a9216ce..86d2a0755a 100644 --- a/plugins/x11/vout_xvideo.c +++ b/plugins/x11/vout_xvideo.c @@ -2,7 +2,7 @@ * vout_xvideo.c: Xvideo video output display method ***************************************************************************** * Copyright (C) 1998, 1999, 2000, 2001 VideoLAN - * $Id: vout_xvideo.c,v 1.4 2001/04/08 16:57:47 sam Exp $ + * $Id: vout_xvideo.c,v 1.5 2001/04/11 02:01:24 henri Exp $ * * Authors: Shane Harper * Vincent Seguin @@ -63,6 +63,8 @@ #include "interface.h" #include "intf_msg.h" +#include "netutils.h" /* network_ChannelJoin */ + #include "main.h" /***************************************************************************** @@ -105,7 +107,10 @@ typedef struct vout_sys_s int i_ss_interval; /* interval between changes */ int i_ss_blanking; /* blanking mode */ int i_ss_exposure; /* exposure mode */ - + + /* Auto-hide cursor */ + mtime_t i_lastmoved; + /* Mouse pointer properties */ boolean_t b_mouse; /* is the mouse pointer displayed ? */ @@ -331,6 +336,7 @@ static int vout_Manage( vout_thread_t *p_vout ) XEvent xevent; /* X11 event */ boolean_t b_resized; /* window has been resized */ char i_key; /* ISO Latin-1 key */ + KeySym x_key_symbol; /* Handle X11 events: ConfigureNotify events are parsed to know if the * output window's size changed, MapNotify and UnmapNotify to know if the @@ -339,7 +345,8 @@ static int vout_Manage( vout_thread_t *p_vout ) b_resized = 0; while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window, StructureNotifyMask | KeyPressMask | - ButtonPressMask | ButtonReleaseMask, &xevent ) + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask, &xevent ) == True ) { /* ConfigureNotify event: prepare */ @@ -375,16 +382,73 @@ static int vout_Manage( vout_thread_t *p_vout ) /* Keyboard event */ else if( xevent.type == KeyPress ) { - if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) ) + /* We may have keys like F1 trough F12, ESC ... */ + x_key_symbol = XKeycodeToKeysym( p_vout->p_sys->p_display, + xevent.xkey.keycode, 0 ); + switch( x_key_symbol ) { - /* FIXME: handle stuff here */ - switch( i_key ) - { - case 'q': - /* FIXME: need locking ! */ - p_main->p_intf->b_die = 1; - break; - } + case XK_Escape: + p_main->p_intf->b_die = 1; + break; + case XK_Menu: + p_main->p_intf->b_menu_change = 1; + break; + default: + /* "Normal Keys" + * The reason why I use this instead of XK_0 is that + * with XLookupString, we don't have to care about + * keymaps. */ + + if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) ) + { + /* FIXME: handle stuff here */ + switch( i_key ) + { + case 'q': + case 'Q': + p_main->p_intf->b_die = 1; + break; + case '0': + network_ChannelJoin( 0 ); + break; + case '1': + network_ChannelJoin( 1 ); + break; + case '2': + network_ChannelJoin( 2 ); + break; + case '3': + network_ChannelJoin( 3 ); + break; + case '4': + network_ChannelJoin( 4 ); + break; + case '5': + network_ChannelJoin( 5 ); + break; + case '6': + network_ChannelJoin( 6 ); + break; + case '7': + network_ChannelJoin( 7 ); + break; + case '8': + network_ChannelJoin( 8 ); + break; + case '9': + network_ChannelJoin( 9 ); + break; + default: + if( intf_ProcessKey( p_main->p_intf, + (char )i_key ) ) + { + intf_DbgMsg( "unhandled key '%c' (%i)", + (char)i_key, i_key ); + } + break; + } + } + break; } } /* Mouse click */ @@ -396,10 +460,6 @@ static int vout_Manage( vout_thread_t *p_vout ) /* in this part we will eventually manage * clicks for DVD navigation for instance */ break; - - case Button2: - XVideoTogglePointer( p_vout ); - break; } } /* Mouse release */ @@ -413,6 +473,16 @@ static int vout_Manage( vout_thread_t *p_vout ) break; } } + /* Mouse move */ + else if( xevent.type == MotionNotify ) + { + p_vout->p_sys->i_lastmoved = mdate(); + if( ! p_vout->p_sys->b_mouse ) + { + XVideoTogglePointer( p_vout ); + } + } + #ifdef DEBUG /* Other event */ else @@ -482,6 +552,16 @@ static int vout_Manage( vout_thread_t *p_vout ) p_vout->i_width, p_vout->i_height ); } + /* Autohide Cursour */ + if( mdate() - p_vout->p_sys->i_lastmoved > 2000000 ) + { + /* Hide the mouse automatically */ + if( p_vout->p_sys->b_mouse ) + { + XVideoTogglePointer( p_vout ); + } + } + return 0; } @@ -684,7 +764,8 @@ static int XVideoCreateWindow( vout_thread_t *p_vout ) XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window, StructureNotifyMask | KeyPressMask | - ButtonPressMask | ButtonReleaseMask ); + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask ); /* At this stage, the window is open, displayed, and ready to * receive data */ diff --git a/src/interface/interface.c b/src/interface/interface.c index 709f7253bb..c23091cef9 100644 --- a/src/interface/interface.c +++ b/src/interface/interface.c @@ -4,7 +4,7 @@ * interface, such as command line. ***************************************************************************** * Copyright (C) 1998, 1999, 2000 VideoLAN - * $Id: interface.c,v 1.71 2001/03/21 13:42:34 sam Exp $ + * $Id: interface.c,v 1.72 2001/04/11 02:01:24 henri Exp $ * * Authors: Vincent Seguin * @@ -322,16 +322,18 @@ int intf_ProcessKey( intf_thread_t *p_intf, int g_key ) keyparm k_reply; k_reply = intf_GetKey( p_intf, g_key); - switch( k_reply.key ) { - case INTF_KEY_QUIT: /* quit order */ + case INTF_KEY_QUIT: /* quit order */ p_intf->b_die = 1; break; case INTF_KEY_SET_CHANNEL: /* Change channel - return code is ignored since SelectChannel displays * its own error messages */ - intf_SelectChannel( p_intf, k_reply.param ); +/* intf_SelectChannel( p_intf, k_reply.param ); */ +/* network_ChannelJoin() */ +/* FIXME : keyboard event is for the time being half handled by the interface + * half handled directly by the plugins. We should decide what to do. */ break; case INTF_KEY_INC_VOLUME: /* volume + */ if( (p_main->p_aout != NULL) && (p_main->p_aout->vol < VOLUME_MAX) ) @@ -380,4 +382,3 @@ int intf_ProcessKey( intf_thread_t *p_intf, int g_key ) return( 0 ); } - diff --git a/src/interface/intf_ctrl.c b/src/interface/intf_ctrl.c index 45f59a3e04..fc1a85682e 100644 --- a/src/interface/intf_ctrl.c +++ b/src/interface/intf_ctrl.c @@ -19,7 +19,7 @@ * More informations about parameters stand in `list of commands' section. ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN - * $Id: intf_ctrl.c,v 1.35 2001/04/06 09:15:47 sam Exp $ + * $Id: intf_ctrl.c,v 1.36 2001/04/11 02:01:24 henri Exp $ * * Authors: Vincent Seguin * @@ -80,7 +80,7 @@ static int SpawnInput ( int i_argc, intf_arg_t *p_argv ); #ifdef DEBUG static int Test ( int i_argc, intf_arg_t *p_argv ); #endif -static int Vlan ( int i_argc, intf_arg_t *p_argv ); +static int Channel ( int i_argc, intf_arg_t *p_argv ); static int Psi ( int i_argc, intf_arg_t *p_argv ); /* @@ -170,11 +170,12 @@ const intf_command_t control_command[] = /* help: */ "Spawn a decoder thread for . The stream will be" \ " received by ." }, { "spawn-input", SpawnInput, /* spawn-input */ - /* format: */ "method=i? filename=s? hostname=s? ip=s? port=i? vlan=i?", + /* format: */ "method=i? filename=s? hostname=s? ip=s? port=i?"\ + " channel=i?", /* summary: */ "spawn an input thread", /* summary: */ "spawn-input [method=]\n" \ "[filename=|hostname=|ip=]\n" \ - "[port=] [vlan=]", + "[port=] [channel=]", /* help: */ "Spawn an input thread. Method is 10, 20, 21, 22, 32, "\ "hostname is the fully-qualified domain name, ip is a dotted-decimal address." }, #ifdef DEBUG @@ -186,16 +187,17 @@ const intf_command_t control_command[] = "developpers as an easy way to test part of their code. If you don't know "\ "what it should do, just try !" }, #endif - { "vlan", Vlan, + { "channel", Channel, /* format: */ "intf=s? s i? ", - /* summary: */ "vlan operations", - /* usage: */ "vlan synchro\n" \ - "vlan [intf=] request\n" \ - "vlan [intf=] join \n" \ - "vlan [intf=] leave", - /* help: */ "Perform various operations on vlans. 'synchro' resynchronize " \ - "with the server. 'request' ask which is the current vlan (for the default "\ - "interface or for a given one). 'join' and 'leave' try to change vlan." }, + /* summary: */ "channel changing operations", + /* usage: */ "channel synchro\n" \ + "channel [intf=] request\n" \ + "channel [intf=] join \n" \ + "channel [intf=] leave", + /* help: */ "Perform various operations on channels. 'synchro'"\ + "resynchronize with the server. 'request' ask which is the current"\ + "channel (for the default interface or for a given one)."\ + "'join' and 'leave' try to change channel." }, { "psi", Psi, /* format: */ "i ", /* summary: */ "Dump PSI tables", @@ -529,18 +531,18 @@ static int Test( int i_argc, intf_arg_t *p_argv ) #endif /***************************************************************************** - * Vlan: vlan operations + * Channels: channel operations ***************************************************************************** - * This function performs various vlan operations. + * This function performs various channel operations. *****************************************************************************/ -static int Vlan( int i_argc, intf_arg_t *p_argv ) +static int Channel( int i_argc, intf_arg_t *p_argv ) { int i_command; /* command argument number */ - /* Do not try anything if vlans are deactivated */ - if( !p_main->b_vlans ) + /* Do not try anything if channel changing is desactivated */ + if( !p_main->b_channels ) { - intf_IntfMsg("vlans are deactivated"); + intf_IntfMsg("channel changing is desactivated"); return( INTF_OTHER_ERROR ); } @@ -564,7 +566,7 @@ static int Vlan( int i_argc, intf_arg_t *p_argv ) /* Command is unknown */ else { - intf_IntfMsg("vlan error: unknown command %s", p_argv[i_command].psz_str ); + intf_IntfMsg("channel error: unknown command %s", p_argv[i_command].psz_str ); return( INTF_USAGE_ERROR ); } diff --git a/src/interface/main.c b/src/interface/main.c index 4e940e61b0..10ddde6cdf 100644 --- a/src/interface/main.c +++ b/src/interface/main.c @@ -4,7 +4,7 @@ * and spawn threads. ***************************************************************************** * Copyright (C) 1998, 1999, 2000 VideoLAN - * $Id: main.c,v 1.82 2001/04/06 09:15:47 sam Exp $ + * $Id: main.c,v 1.83 2001/04/11 02:01:24 henri Exp $ * * Authors: Vincent Seguin * Samuel Hocevar @@ -76,6 +76,8 @@ #include "beos_specific.h" #endif +#include "netutils.h" /* network_ChannelJoin */ + #include "main.h" /***************************************************************************** @@ -97,7 +99,7 @@ #define OPT_FULLSCREEN 165 #define OPT_OVERLAY 166 -#define OPT_VLANS 170 +#define OPT_CHANNELS 170 #define OPT_SERVER 171 #define OPT_PORT 172 #define OPT_BROADCAST 173 @@ -159,7 +161,7 @@ static const struct option longopts[] = /* Input options */ { "input", 1, 0, OPT_INPUT }, - { "vlans", 0, 0, OPT_VLANS }, + { "channels", 0, 0, OPT_CHANNELS }, { "server", 1, 0, OPT_SERVER }, { "port", 1, 0, OPT_PORT }, { "broadcast", 0, 0, OPT_BROADCAST }, @@ -293,16 +295,13 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] ) /* * Initialize shared resources and libraries */ - /* FIXME: no VLANs */ -#if 0 - if( p_main->b_vlans && input_VlanCreate() ) + if( p_main->b_channels && network_ChannelCreate() ) { - /* On error during vlans initialization, switch off vlans */ - intf_Msg( "Virtual LANs initialization failed : " - "vlans management is deactivated" ); - p_main->b_vlans = 0; + /* On error during Channels initialization, switch off channels */ + intf_Msg( "Channels initialization failed : " + "Channel management is deactivated" ); + p_main->b_channels = 0; } -#endif /* * Run interface @@ -379,15 +378,12 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] ) } /* - * Free shared resources and libraries + * Go back into channel 0 which is the network */ - /* FIXME */ -#if 0 - if( p_main->b_vlans ) + if( p_main->b_channels ) { - input_VlanDestroy(); + network_ChannelJoin( COMMON_CHANNEL ); } -#endif /* * Free module bank @@ -518,9 +514,9 @@ static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] ) p_main->ppsz_argv = ppsz_argv; p_main->ppsz_env = ppsz_env; - p_main->b_audio = 1; - p_main->b_video = 1; - p_main->b_vlans = 0; + p_main->b_audio = 1; + p_main->b_video = 1; + p_main->b_channels = 0; p_main->i_warning_level = 4; @@ -651,8 +647,8 @@ static int GetConfiguration( int i_argc, char *ppsz_argv[], char *ppsz_env[] ) case OPT_INPUT: /* --input */ main_PutPszVariable( INPUT_METHOD_VAR, optarg ); break; - case OPT_VLANS: /* --vlans */ - p_main->b_vlans = 1; + case OPT_CHANNELS: /* --channels */ + p_main->b_channels = 1; break; case OPT_SERVER: /* --server */ main_PutPszVariable( INPUT_SERVER_VAR, optarg ); @@ -754,7 +750,7 @@ static void Usage( int i_fashion ) "\n -s, --dvdsubtitle \tchoose DVD subtitle channel" "\n" "\n --input \tinput method" - "\n --vlans \tenable vlans" + "\n --channels \tenable channels" "\n --server \tvideo server address" "\n --port \tvideo server port" "\n --broadcast \tlisten to a broadcast" @@ -809,8 +805,8 @@ static void Usage( int i_fashion ) "\n " INPUT_PORT_VAR "= \tvideo server port" "\n " INPUT_IFACE_VAR "= \tnetwork interface" "\n " INPUT_BROADCAST_VAR "={1|0} \tbroadcast mode" - "\n " INPUT_VLAN_SERVER_VAR "= \tvlan server" - "\n " INPUT_VLAN_PORT_VAR "= \tvlan server port" ); + "\n " INPUT_CHANNEL_SERVER_VAR "= \tchannel server" + "\n " INPUT_CHANNEL_PORT_VAR "= \tchannel server port" ); } diff --git a/src/misc/netutils.c b/src/misc/netutils.c index 7f1cd8e154..350d5ba7ba 100644 --- a/src/misc/netutils.c +++ b/src/misc/netutils.c @@ -2,7 +2,7 @@ * netutils.c: various network functions ***************************************************************************** * Copyright (C) 1999, 2000, 2001 VideoLAN - * $Id: netutils.c,v 1.22 2001/03/21 13:42:34 sam Exp $ + * $Id: netutils.c,v 1.23 2001/04/11 02:01:24 henri Exp $ * * Authors: Vincent Seguin * Benoit Steiner @@ -33,6 +33,7 @@ #include /* errno() */ #include /* bzero(), bcopy() */ #include /* gethostname() */ +#include /* gettimeofday */ #include /* BSD: struct in_addr */ #include /* BSD: struct sockaddr */ @@ -40,6 +41,10 @@ #include /* inet_ntoa(), inet_aton() */ #endif +#ifdef SYS_LINUX +#include /* ioctl() */ +#endif + #if defined (HAVE_NET_IF_H) #include /* interface (arch-dependent) */ #endif @@ -52,15 +57,31 @@ #include "common.h" #include "mtime.h" #include "threads.h" +#include "main.h" #include "intf_msg.h" -#if !defined( SYS_BEOS ) && !defined( SYS_NTO ) - #include "netutils.h" + + /***************************************************************************** - * input_BuildLocalAddr : fill a sockaddr_in structure for local binding + * input_channel_t: channel library data + ***************************************************************************** + * Store global channel library data. + * The part of the code concerning the channel changing process is unstable + * as it depends on the VideoLAN channel server, which isn't frozen for + * the time being. + *****************************************************************************/ +typedef struct input_channel_s +{ + int i_channel_id; /* current channel number */ + mtime_t last_change; /* last change date */ +} input_channel_t; + + +/***************************************************************************** + * network_BuildLocalAddr : fill a sockaddr_in structure for local binding *****************************************************************************/ int network_BuildLocalAddr( struct sockaddr_in * p_socket, int i_port, boolean_t b_broadcast ) @@ -113,7 +134,7 @@ int network_BuildLocalAddr( struct sockaddr_in * p_socket, int i_port, } /***************************************************************************** - * input_BuildRemoteAddr : fill a sockaddr_in structure for remote host + * network_BuildRemoteAddr : fill a sockaddr_in structure for remote host *****************************************************************************/ int network_BuildRemoteAddr( struct sockaddr_in * p_socket, char * psz_server ) { @@ -147,5 +168,223 @@ int network_BuildRemoteAddr( struct sockaddr_in * p_socket, char * psz_server ) } return( 0 ); } -#endif +/***************************************************************************** + * network_ChannelCreate: initialize global channel method data + ***************************************************************************** + * Initialize channel input method global data. This function should be called + * once before any input thread is created or any call to other + * input_Channel*() function is attempted. + *****************************************************************************/ +int network_ChannelCreate( void ) +{ +/* Even when BSD are supported, BeOS is not likely to be supported, so + * I prefer to put it apart */ +#ifdef SYS_BEOS + intf_ErrMsg( "error: channel changing is not yet supported under BeOS" ); + return( 1 ); +#else +/* FIXME : channels handling only work for linux */ +#ifdef SYS_LINUX + /* Allocate structure */ + p_main->p_channel = malloc( sizeof( input_channel_t ) ); + if( p_main->p_channel == NULL ) + { + intf_ErrMsg("error: %s\n", strerror(ENOMEM)); + return( -1 ); + } + + /* Initialize structure */ + p_main->p_channel->i_channel_id = 0; + p_main->p_channel->last_change = 0; + + intf_Msg("Channels initialized\n"); + return( 0 ); +#else + intf_ErrMsg( "error : channel changing only works with linux yest" ); +#endif /* SYS_LINUX */ +#endif /* SYS_BEOS */ +} + +/***************************************************************************** + * network_ChannelJoin: join a channel + ***************************************************************************** + * This function will try to join a channel. If the relevant interface is + * already on the good channel, nothing will be done. Else, and if possible + * (if the interface is not locked), the channel server will be contacted + * and a change will be requested. The function will block until the change + * is effective. Note that once a channel is no more used, it's interface + * should be unlocked using input_ChannelLeave(). + * Non 0 will be returned in case of error. + *****************************************************************************/ +int network_ChannelJoin( int i_channel_id ) +{ + intf_ErrMsg("Changing to channel %d",i_channel_id); + return(0); +/* Courtesy of Nitrox. He'll update it soon */ +#if 0 +/* I still prefer to put BeOS a bit apart */ +#ifdef SYS_BEOS + intf_ErrMsg( "Channels are not yet supported uunder BeOS" ); + return( -1 ); +#else +#ifdef SYS_LINUX + int socket_cl; + int fromlen; + struct ifreq interface; + struct sockaddr_in sa_server; + struct sockaddr_in sa_client; + unsigned int version = 12; + char mess[80]; + char mess_length = 80; + struct timeval *date_cl; + struct timeval time; + long unsigned int date; + int nbanswer; + char answer; + fd_set rfds; + unsigned int rc; +/* debug */ intf_ErrMsg("ChannelJoin : %d",i_channel_id); + /* If last change is too recent, wait a while */ + if( mdate() - p_main->p_channel->last_change < INPUT_CHANNEL_CHANGE_DELAY ) + { + intf_Msg("Waiting before changing channel...\n"); + mwait( p_main->p_channel->last_change + INPUT_CHANNEL_CHANGE_DELAY ); + } + p_main->p_channel->last_change = mdate(); + p_main->p_channel->i_channel_id = i_channel_id; + + intf_Msg("Joining channel %d\n", i_channel_id ); + + /* + * Looking for information about the eth0 interface + */ + interface.ifr_addr.sa_family=AF_INET; + strcpy(interface.ifr_name,INPUT_IFACE_DEFAULT); + + + /* + * Initialysing the socket + */ + socket_cl=socket(AF_INET,SOCK_DGRAM,0); + + + /* + * Getting the server's information + */ + bzero(&sa_server,sizeof(struct sockaddr_in)); + sa_server.sin_family=AF_INET; + sa_server.sin_port=htons(INPUT_CHANNEL_PORT_DEFAULT); + inet_aton(INPUT_CHANNEL_SERVER_DEFAULT,&(sa_server.sin_addr)); + + /* + * Looking for the interface MAC address + */ + ioctl(socket_cl,SIOCGIFHWADDR,&interface); + intf_DbgMsg( + "CHANNELSERVER: macaddr == %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", + interface.ifr_hwaddr.sa_data[0] & 0xff, + interface.ifr_hwaddr.sa_data[1] & 0xff, + interface.ifr_hwaddr.sa_data[2] & 0xff, + interface.ifr_hwaddr.sa_data[3] & 0xff, + interface.ifr_hwaddr.sa_data[4] & 0xff, + interface.ifr_hwaddr.sa_data[5] & 0xff); + + /* + * Getting date of the client + */ + date_cl=malloc(sizeof(struct timeval)); + if(date_cl==NULL) + { + intf_ErrMsg("CHANNELSERVER: unable to allocate memory\n"); + /* return VS_R_MEMORY;*/ + return -1; + } + + if (gettimeofday(date_cl,0)==-1) + return -1; + date=date_cl->tv_sec; + free(date_cl); + intf_DbgMsg("CHANNELSERVER: date %lu\n",date); + + + /* + * Build of the message + */ + sprintf(mess,"%d %u %lu %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x \n", + i_channel_id, version, date, + interface.ifr_hwaddr.sa_data[0] & 0xff, + interface.ifr_hwaddr.sa_data[1] & 0xff, + interface.ifr_hwaddr.sa_data[2] & 0xff, + interface.ifr_hwaddr.sa_data[3] & 0xff, + interface.ifr_hwaddr.sa_data[4] & 0xff, + interface.ifr_hwaddr.sa_data[5] & 0xff); + + intf_DbgMsg("CHANNELSERVER: The message is %s\n",mess); + + + /* + * Open the socket 2 + */ + bzero(&sa_client,sizeof(struct sockaddr_in)); + sa_client.sin_family=AF_INET; + sa_client.sin_port=htons(4312); + sa_client.sin_addr.s_addr=INADDR_ANY; + fromlen=sizeof(struct sockaddr); + rc=bind(socket_cl,(struct sockaddr *)(&sa_client),sizeof(struct sockaddr)); + if (rc) + { + intf_ErrMsg("CHANNELSERVER: Unable to bind socket:%u\n",rc); + /* TODO put CS_R_BIND in types.h*/ + /* return CS_R_SOCKET;*/ + return -1; + } + + + /* + * Send the message + */ + sendto(socket_cl,mess,mess_length,0,(struct sockaddr *)(&sa_server),\ + sizeof(struct sockaddr)); + + /* + * Waiting 5 sec for one answer from the server + */ + time.tv_sec=5; + time.tv_usec=0; + FD_ZERO(&rfds); + FD_SET(socket_cl,&rfds); + nbanswer=select(socket_cl+1,&rfds,NULL,NULL,&time); + if(nbanswer==0) + intf_DbgMsg("CHANNELSERVER: no answer\n"); + else if(nbanswer==-1) + intf_DbgMsg("CHANNELSERVER: Unable to receive the answer\n"); + else + { + recvfrom(socket_cl,&answer,sizeof(char),0,\ + (struct sockaddr *)(&sa_client),&fromlen); + intf_DbgMsg("CHANNELSERVER: the answer : %hhd\n",answer); + if(answer==-1) + intf_DbgMsg( + "CHANNELSERVER: The server failed to create the thread\n"); + else if(answer==0) + intf_DbgMsg( + "CHANNELSERVER: The server tries to change the channel\n"); + else + intf_DbgMsg("CHANNELSERVER: Unknown answer !\n"); + } + + /* + * Close the socket + */ + close(socket_cl); + + return 0; +#else /* SYS_LINUX */ + intf_ErrMsg( "Channel only work under linux yet" ); +#endif /* SYS_LINUX */ + +} +#endif /* SYS_BEOS */ +#endif /* if 0 */ +} -- 2.39.2