/* Input */
struct input_thread_s;
-struct input_vlan_method_s;
+struct input_vlan_s;
struct input_cfg_s;
typedef struct input_thread_s * p_input_thread_t;
-typedef struct input_vlan_method_s * p_input_vlan_method_t;
+typedef struct input_vlan_s * p_input_vlan_t;
typedef struct input_cfg_s * p_input_cfg_t;
/* Audio */
/* Use a LIFO or FIFO for PES netlist ? */
#undef INPUT_LIFO_PES_NETLIST
-/* Maximum length of a hostname */
-#define INPUT_MAX_HOSTNAME_LENGTH 100
+/* Maximum length of a hostname or source name */
+#define INPUT_MAX_SOURCE_LENGTH 100
/* Default input method */
#define INPUT_DEFAULT_METHOD INPUT_METHOD_TS_UCAST
/* Default remote server */
-#define VIDEOLAN_DEFAULT_SERVER "vod.via.ecp.fr"
+#define INPUT_DEFAULT_SERVER "138.195.143.220"
-/* Default videolan port */
-#define VIDEOLAN_DEFAULT_PORT 1234
+/* Default input port */
+#define INPUT_DEFAULT_PORT 1234
/* Default videolan VLAN */
#define VIDEOLAN_DEFAULT_VLAN 3
* Vlan method
*/
-/* Default VLAN server */
-#define VLAN_DEFAULT_SERVER "vlanserver.via.ecp.fr"
-#define VLAN_DEFAULT_SERVER_PORT 6010
+/* Default network interface and environment variable */
+#define INPUT_IFACE_VAR "vlc_iface"
+#define INPUT_IFACE_DEFAULT "eth0"
+
+/* Default server and port */
+#define INPUT_VLAN_SERVER_VAR "vlc_vlan_server"
+#define INPUT_VLAN_SERVER_DEFAULT "138.195.140.31"
+#define INPUT_VLAN_PORT_VAR "vlc_vlan_port"
+#define INPUT_VLAN_PORT_DEFAULT 6010
/*******************************************************************************
* Audio configuration
* (c)1999 VideoLAN
******************************************************************************/
-/* needs : "netlist.h", "config.h", "mtime.h" */
-
-/* ?? missing:
- * tables version control */
-
-/******************************************************************************
- * External structures
- ******************************************************************************
- * These structures, required here only as pointers destinations, are declared
- * in other headers.
- ******************************************************************************/
-struct video_cfg_s; /* video configuration descriptor */
-struct vout_thread_s; /* video output thread */
-struct stream_descriptor_s; /* PSI tables */
-
/******************************************************************************
* Constants related to input
******************************************************************************/
******************************************************************************
* Describe a TS packet.
******************************************************************************/
-typedef struct ts_packet_struct
+typedef struct ts_packet_s
{
/* Nothing before this line, the code relies on that */
byte_t buffer[TS_PACKET_SIZE]; /* raw TS data packet */
unsigned int i_payload_end; /* guess ? :-) */
/* Used to chain the TS packets that carry data for a same PES or PSI */
- struct ts_packet_struct * p_prev_ts;
- struct ts_packet_struct * p_next_ts;
+ struct ts_packet_s * p_prev_ts;
+ struct ts_packet_s * p_next_ts;
} ts_packet_t;
-
/******************************************************************************
* pes_packet_t
******************************************************************************
* Describes an PES packet, with its properties, and pointers to the TS packets
* containing it.
******************************************************************************/
-typedef struct
+typedef struct pes_packet_s
{
/* PES properties */
boolean_t b_data_loss; /* The previous (at least) PES packet
* (used by the demultiplexer). */
} pes_packet_t;
-
/******************************************************************************
* psi_section_t
******************************************************************************
* Describes a PSI section. Beware, it doesn't contain pointers to the TS
* packets that contain it as for a PES, but the data themselves
******************************************************************************/
-typedef struct
+typedef struct psi_section_s
{
byte_t buffer[PSI_SECTION_SIZE];
* Describes an elementary stream, and includes fields required to handle and
* demultiplex this elementary stream.
******************************************************************************/
-typedef struct
+typedef struct es_descriptor_t
{
u16 i_id; /* stream ID, PID for TS streams */
u8 i_type; /* stream type */
#endif
} input_netlist_t;
+
+
/******************************************************************************
* input_thread_t
******************************************************************************
* update all reference to it each time the table would be reallocated
******************************************************************************/
-/* function pointers */
-struct input_thread_s;
-struct input_cfg_s;
-typedef int (*f_open_t)( struct input_thread_s *, struct input_cfg_s *);
-typedef int (*f_read_t)( struct input_thread_s *, const struct iovec *,
- size_t );
-typedef void (*f_clean_t)( struct input_thread_s * );
+/* Function pointers used in structure */
+typedef int (input_open_t) ( p_input_thread_t p_input );
+typedef int (input_read_t) ( p_input_thread_t p_input, const struct iovec *p_vector,
+ size_t i_count );
+typedef void (input_close_t) ( p_input_thread_t p_input );
+/* Structure */
typedef struct input_thread_s
{
/* Thread properties and locks */
- boolean_t b_die; /* 'die' flag */
- boolean_t b_error; /* deadlock */
- vlc_thread_t thread_id; /* id for thread functions */
- vlc_mutex_t programs_lock; /* programs modification lock */
- vlc_mutex_t es_lock; /* es modification lock */
+ boolean_t b_die; /* 'die' flag */
+ boolean_t b_error; /* deadlock */
+ vlc_thread_t thread_id; /* id for thread functions */
+ vlc_mutex_t programs_lock; /* programs modification lock */
+ vlc_mutex_t es_lock; /* es modification lock */
+ int * pi_status; /* temporary status flag */
/* Input method description */
- int i_method; /* input method */
- int i_handle; /* file/socket descriptor */
- int i_vlan_id; /* id for vlan method */
- f_open_t p_open; /* pointer to the opener of the method */
- f_read_t p_read; /* pointer to the reading function */
- f_clean_t p_clean; /* pointer to the destroying function */
+ int i_method; /* input method */
+ int i_handle; /* file/socket descriptor */
+ char * psz_source; /* source */
+ int i_port; /* port number */
+ int i_vlan; /* id for vlan method */
+ input_open_t * p_Open; /* opener of the method */
+ input_read_t * p_Read; /* reading function */
+ input_close_t * p_Close; /* destroying function */
/* General stream description */
stream_descriptor_t * p_stream; /* PAT tables */
/* Netlists */
input_netlist_t netlist; /* see above */
- /* ?? default settings for new decoders */
- struct aout_thread_s * p_aout; /* audio output thread structure */
+ /* Default settings for spawned decoders */
+ p_aout_thread_t p_aout; /* audio output thread structure */
+ p_vout_thread_t p_vout; /* video output thread */
#ifdef STATS
- /* Stats */
- count_t c_loops; /* number of loops */
- count_t c_bytes; /* total of bytes read */
- count_t c_payload_bytes; /* total of payload useful bytes */
- count_t c_ts_packets_read; /* total of packets read */
- count_t c_ts_packets_trashed; /* total of trashed packets */
- /* ?? ... other stats */
+ /* Statistics */
+ count_t c_loops; /* number of loops */
+ count_t c_bytes; /* bytes read */
+ count_t c_payload_bytes; /* payload useful bytes */
+ count_t c_packets_read; /* packets read */
+ count_t c_packets_trashed; /* trashed packets */
#endif
} input_thread_t;
#define INPUT_METHOD_TS_BCAST 22 /* TS UDP broadcast */
#define INPUT_METHOD_TS_VLAN_BCAST 32 /* TS UDP broadcast with VLANs */
-/******************************************************************************
- * input_cfg_t: input thread configuration structure
- ******************************************************************************
- * This structure is passed as a parameter to input_CreateTtread(). It includes
- * several fields describing potential properties of a new object.
- * The 'i_properties' field allow to set only a subset of the required
- * properties, asking the called function to use default settings for
- * the other ones.
- ******************************************************************************/
-typedef struct input_cfg_s
-{
- u64 i_properties;
-
- /* Input method properties */
- int i_method; /* input method */
- char * psz_filename; /* filename */
- char * psz_hostname; /* server hostname */
- char * psz_ip; /* server IP */
- int i_port; /* port */
- int i_vlan; /* vlan number */
-
- /* ??... default settings for new decoders */
- struct aout_thread_s * p_aout; /* audio output thread structure */
-
-} input_cfg_t;
-
-/* Properties flags */
-#define INPUT_CFG_METHOD (1 << 0)
-#define INPUT_CFG_FILENAME (1 << 4)
-#define INPUT_CFG_HOSTNAME (1 << 8)
-#define INPUT_CFG_IP (1 << 9)
-#define INPUT_CFG_PORT (1 << 10)
-#define INPUT_CFG_VLAN (1 << 11)
-
/*****************************************************************************
* Prototypes
*****************************************************************************/
-input_thread_t *input_CreateThread ( input_cfg_t *p_cfg );
-void input_DestroyThread ( input_thread_t *p_input );
+input_thread_t *input_CreateThread ( int i_method, char *psz_source, int i_port,
+ int i_vlan, p_vout_thread_t p_vout,
+ p_aout_thread_t p_aout, int *pi_status );
+void input_DestroyThread ( input_thread_t *p_input, int *pi_status );
+
-int input_OpenAudioStream ( input_thread_t *p_input, int i_pid
- /* ?? , struct audio_cfg_s * p_cfg */ );
+int input_OpenAudioStream ( input_thread_t *p_input, int i_pid );
void input_CloseAudioStream ( input_thread_t *p_input, int i_pid );
-int input_OpenVideoStream ( input_thread_t *p_input,
- struct vout_thread_s *p_vout, struct video_cfg_s * p_cfg );
+int input_OpenVideoStream ( input_thread_t *p_input, int i_pid );
void input_CloseVideoStream ( input_thread_t *p_input, int i_pid );
-
-/* ?? settings functions */
-/* ?? info functions */
/*******************************************************************************
- * file.h: file streams functions interface
+ * input_file.h: file streams functions interface
* (c)1999 VideoLAN
*******************************************************************************/
/******************************************************************************
* Prototypes
******************************************************************************/
-int input_FileCreateMethod( input_thread_t *p_input ,
- input_cfg_t *p_cfg );
-int input_FileRead( input_thread_t *p_input, const struct iovec *p_vector,
- size_t i_count );
-void input_FileDestroyMethod( input_thread_t *p_input );
+int input_FileOpen ( input_thread_t *p_input );
+int input_FileRead ( input_thread_t *p_input, const struct iovec *p_vector,
+ size_t i_count );
+void input_FileClose ( input_thread_t *p_input );
/******************************************************************************
* Prototypes
******************************************************************************/
-int input_NetlistOpen( input_thread_t *p_input );
-void input_NetlistClean( input_thread_t *p_input );
-/* ?? implement also a "normal" (non inline, non static) function in input_netlist.c,
- which will be used when inline is disabled */
-/* ?? test */ static __inline__ void input_NetlistFreePES( input_thread_t *p_input,
- pes_packet_t *p_pes_packet );
-static __inline__ void input_NetlistFreeTS( input_thread_t *p_input,
- ts_packet_t *p_ts_packet );
+int input_NetlistInit ( input_thread_t *p_input );
+void input_NetlistEnd ( input_thread_t *p_input );
+
+static __inline__ void input_NetlistFreePES( input_thread_t *p_input, pes_packet_t *p_pes_packet );
+static __inline__ void input_NetlistFreeTS( input_thread_t *p_input, ts_packet_t *p_ts_packet );
static __inline__ pes_packet_t* input_NetlistGetPES( input_thread_t *p_input );
-/*******************************************************************************
+/******************************************************************************
* input_NetlistFreePES: add a PES packet to the netlist
*******************************************************************************
* Add a PES packet to the PES netlist, so that the packet can immediately be
/*******************************************************************************
- * network.h: network functions interface
+ * input_network.h: network functions interface
* (c)1999 VideoLAN
*******************************************************************************/
-/*
- needs :
- - <sys/uio.h>
- - <sys/socket.h>
- - <unistd.h>
- - <netinet/in.h>
- - <netdb.h>
- - <arpa/inet.h>
- - <stdio.h>
- - <sys/ioctl.h>
- - <net/if.h>
-*/
-
/******************************************************************************
* Prototypes
******************************************************************************/
-int input_NetworkCreateMethod( input_thread_t *p_input,
- input_cfg_t *p_cfg );
-int input_NetworkRead( input_thread_t *p_input, const struct iovec *p_vector,
- size_t i_count );
-void input_NetworkDestroyMethod( input_thread_t *p_input );
+int input_NetworkOpen ( input_thread_t *p_input );
+int input_NetworkRead ( input_thread_t *p_input, const struct iovec *p_vector,
+ size_t i_count );
+void input_NetworkClose ( input_thread_t *p_input );
int input_PcrInit ( input_thread_t *p_input );
void input_PcrDecode ( input_thread_t *p_input, es_descriptor_t* p_es,
u8* p_pcr_data );
-void input_PcrClean ( input_thread_t *p_input );
+void input_PcrEnd ( input_thread_t *p_input );
/*******************************************************************************
* psi.h: PSI management interface
* (c)1999 VideoLAN
- *******************************************************************************
- * Requires:
- * "config.h"
- * "common.h"
- * "mtime.h"
******************************************************************************/
-
-
-
-
-
-
/******************************************************************************
* Prototypes
******************************************************************************/
-int input_PsiInit( input_thread_t *p_input );
-void input_PsiDecode( input_thread_t *p_input, psi_section_t* p_psi_section );
-void input_PsiRead( input_thread_t *p_input /* ??? */ );
-int input_PsiClean( input_thread_t *p_input );
+int input_PsiInit ( input_thread_t *p_input );
+void input_PsiDecode ( input_thread_t *p_input, psi_section_t* p_psi_section );
+void input_PsiRead ( input_thread_t *p_input );
+int input_PsiEnd ( input_thread_t *p_input );
* "vlc_thread.h"
*******************************************************************************/
-/*******************************************************************************
- * Vlan server related constants
- *******************************************************************************/
-
-#define VLAN_SERVER_MSG_LENGTH 256 /* maximum length of a message */
-#define VLAN_CLIENT_VERSION "1.3.0" /* vlan client version */
-
-/* Messages codes */
-#define VLAN_LOGIN_REQUEST 98 /* login: <version> <login> <passwd> */
-#define VLAN_LOGIN_ANSWER 97 /* login accepted: [msg] */
-#define VLAN_LOGIN_REJECTED 96 /* login rejected: [msg] */
-
-#define VLAN_LOGOUT 99 /* logout */
-
-#define VLAN_INFO_REQUEST 31 /* info: no argument */
-#define VLAN_INFO_ANSWER 32/* info ok: <switch> <port> <vlan> <sharers> */
-#define VLAN_INFO_REJECTED 33 /* info rejected: [msg] */
-
-#define VLAN_CHANGE_REQUEST 21/* change: <mac> [ip] <vlan dest> [vlan src] */
-#define VLAN_CHANGE_ANSWER 22 /* change ok: [msg] */
-#define VLAN_CHANGE_REJECTED 23 /* change failed: [msg] */
-
-/*******************************************************************************
- * Macros to build/extract vlan_ids
- *******************************************************************************/
-#define VLAN_ID_IFACE( vlan_id ) ( ((vlan_id) >> 8) & 0xff )
-#define VLAN_ID_VLAN( vlan_id ) ( (vlan_id) & 0xff )
-#define VLAN_ID( iface, vlan ) ( ((iface) << 8) | (vlan) )
-
/*******************************************************************************
* Prototypes
*******************************************************************************/
-int input_VlanCreate ( void );
-void input_VlanDestroy ( void );
-
-int input_VlanId ( char *psz_iface, int i_vlan );
+int input_VlanCreate ( void );
+void input_VlanDestroy ( void );
int input_VlanJoin ( int i_vlan_id );
void input_VlanLeave ( int i_vlan_id );
-int input_VlanRequest ( char *psz_iface );
-int input_VlanSynchronize ( void );
/* Shared data - these structures are accessed directly from p_main by
* several modules */
p_intf_msg_t p_msg; /* messages interface data */
- p_input_vlan_method_t p_input_vlan; /* vlan input method */
+ p_input_vlan_t p_vlan; /* vlan library data */
} main_t;
extern main_t *p_main;
#include <string.h>
#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
+#include <netinet/in.h>
+
#include <sys/ioctl.h>
#include <sys/shm.h>
#include <sys/soundcard.h>
/* Video */
#include "video.h"
#include "video_output.h"
+#include "vdec_idct.h"
#ifdef OLD_DECODER
#include "video_decoder.h"
/* Interface */
#include "intf_cmd.h"
#include "intf_ctrl.h"
+
#ifndef OLD_DECODER
#include "intf_sys.h"
#include "intf_console.h"
#endif
+
#include "interface.h"
#include "main.h"
+
+
/******************************************************************************
* Local prototypes
******************************************************************************/
-static void input_Thread( input_thread_t *p_input );
-static void ErrorThread( input_thread_t *p_input );
-static void EndThread( input_thread_t *p_input );
-static __inline__ int input_ReadPacket( input_thread_t *p_input );
-static __inline__ void input_SortPacket( input_thread_t *p_input,
- ts_packet_t *ts_packet );
-static __inline__ void input_DemuxTS( input_thread_t *p_input,
- ts_packet_t *ts_packet,
- es_descriptor_t *es_descriptor );
-static __inline__ void input_DemuxPES( input_thread_t *p_input,
- ts_packet_t *ts_packet,
- es_descriptor_t *p_es_descriptor,
- boolean_t b_unit_start, boolean_t b_packet_lost );
-static __inline__ void input_DemuxPSI( input_thread_t *p_input,
+static void RunThread ( input_thread_t *p_input );
+static void ErrorThread ( input_thread_t *p_input );
+static void EndThread ( input_thread_t *p_input );
+
+static __inline__ int input_ReadPacket( input_thread_t *p_input );
+static __inline__ void input_SortPacket( input_thread_t *p_input,
+ ts_packet_t *ts_packet );
+static __inline__ void input_DemuxTS( input_thread_t *p_input,
ts_packet_t *ts_packet,
- es_descriptor_t *p_es_descriptor,
- boolean_t b_unit_start, boolean_t b_packet_lost );
+ es_descriptor_t *es_descriptor );
+static __inline__ void input_DemuxPES( input_thread_t *p_input,
+ ts_packet_t *ts_packet,
+ es_descriptor_t *p_es_descriptor,
+ boolean_t b_unit_start, boolean_t b_packet_lost );
+static __inline__ void input_DemuxPSI( input_thread_t *p_input,
+ ts_packet_t *ts_packet,
+ es_descriptor_t *p_es_descriptor,
+ boolean_t b_unit_start, boolean_t b_packet_lost );
/*******************************************************************************
- * input_CreateThread: initialize and spawn an input thread
+ * input_CreateThread: creates a new input thread
*******************************************************************************
- * This function initializes and spawns an input thread. It returns NULL on
- * failure. If you want a better understanding of the input thread, don't start
- * by reading this function :-).
+ * This function creates a new input, and returns a pointer
+ * to its description. On error, it returns NULL.
+ * If pi_status is NULL, then the function will block until the thread is ready.
+ * If not, it will be updated using one of the THREAD_* constants.
*******************************************************************************/
-input_thread_t *input_CreateThread( input_cfg_t *p_cfg )
+input_thread_t *input_CreateThread ( int i_method, char *psz_source, int i_port, int i_vlan,
+ p_vout_thread_t p_vout, p_aout_thread_t p_aout, int *pi_status )
{
- input_thread_t * p_input;
- int i_index;
+ input_thread_t * p_input; /* thread descriptor */
+ int i_status; /* thread status */
+ int i_index; /* index for tables initialization */
- intf_DbgMsg("input debug 1-1: creating thread (cfg : %p)\n", p_cfg );
-
- /* Allocate input_thread_t structure. */
- if( !( p_input = (input_thread_t *)malloc(sizeof(input_thread_t)) ) )
+ /* Allocate descriptor */
+ intf_DbgMsg("\n");
+ p_input = (input_thread_t *)malloc( sizeof(input_thread_t) );
+ if( p_input == NULL )
{
- intf_ErrMsg("input error: can't allocate input thread structure (%s)\n",
- strerror(errno));
+ intf_ErrMsg("error: %s\n", strerror(ENOMEM));
return( NULL );
}
- /* Init it */
- bzero( p_input, sizeof(input_thread_t));
- for( i_index = 0; i_index < INPUT_MAX_ES; i_index++ )
+
+ /* Initialize thread properties */
+ p_input->b_die = 0;
+ p_input->b_error = 0;
+ p_input->pi_status = (pi_status != NULL) ? pi_status : &i_status;
+ *p_input->pi_status = THREAD_CREATE;
+
+ /* Initialize input method description */
+ p_input->i_method = i_method;
+ p_input->psz_source = psz_source;
+ p_input->i_port = i_port;
+ p_input->i_vlan = i_vlan;
+ switch( i_method )
{
- p_input->p_es[i_index].i_id = EMPTY_PID;
+ case INPUT_METHOD_TS_FILE: /* file methods */
+ p_input->p_Open = input_FileOpen;
+ p_input->p_Read = input_FileRead;
+ p_input->p_Close = input_FileClose;
+ break;
+ case INPUT_METHOD_TS_VLAN_BCAST: /* vlan network method */
+ if( !p_main->b_vlans )
+ {
+ intf_ErrMsg("error: vlans are not activated\n");
+ free( p_input );
+ return( NULL );
+ }
+ /* ... pass through */
+ case INPUT_METHOD_TS_UCAST: /* network methods */
+ case INPUT_METHOD_TS_MCAST:
+ case INPUT_METHOD_TS_BCAST:
+ p_input->p_Open = input_NetworkOpen;
+ p_input->p_Read = input_NetworkRead;
+ p_input->p_Close = input_NetworkClose;
+ break;
+ default:
+ intf_ErrMsg("error: unknow input method\n");
+ free( p_input );
+ return( NULL );
+ break;
}
- /* Find out which method we are gonna use and retrieve pointers. */
- if( !((p_cfg->i_properties) & INPUT_CFG_METHOD) )
+ /* Initialize stream description */
+ for( i_index = 0; i_index < INPUT_MAX_ES; i_index++ )
{
- /* i_method is not set. */
- intf_DbgMsg("input debug: using default method (%d)\n",
- INPUT_DEFAULT_METHOD);
- p_cfg->i_method = INPUT_DEFAULT_METHOD;
- p_cfg->i_properties |= INPUT_CFG_METHOD;
+ p_input->p_es[i_index].i_id = EMPTY_PID;
}
- p_input->i_method = p_cfg->i_method;
- switch( p_cfg->i_method )
- {
- /* File methods */
- case INPUT_METHOD_TS_FILE:
-#ifdef OLD_DECODER
- p_input->p_open = &input_FileCreateMethod;
- p_input->p_read = &input_FileRead;
- p_input->p_clean = &input_FileDestroyMethod;
-#else
- p_input->p_open = input_FileCreateMethod;
- p_input->p_read = input_FileRead;
- p_input->p_clean = input_FileDestroyMethod;
-#endif
- break;
-
- /* Network methods */
- case INPUT_METHOD_TS_UCAST:
- case INPUT_METHOD_TS_MCAST:
- case INPUT_METHOD_TS_BCAST:
- case INPUT_METHOD_TS_VLAN_BCAST:
-#ifdef OLD_DECODER
- p_input->p_open = &input_NetworkCreateMethod;
- p_input->p_read = &input_NetworkRead;
- p_input->p_clean = &input_NetworkDestroyMethod;
-#else
- p_input->p_open = input_NetworkCreateMethod;
- p_input->p_read = input_NetworkRead;
- p_input->p_clean = input_NetworkDestroyMethod;
-#endif
- break;
+
+ /* Initialize default settings for spawned decoders */
+ p_input->p_aout = p_aout;
+ p_input->p_vout = p_vout;
- case INPUT_METHOD_NONE:
- default:
-#ifdef DEBUG
- /* Internal error, which should never happen */
- intf_DbgMsg("input debug: unknow method type %d\n",
- p_cfg->i_method);
- return( NULL );
+#ifdef STATS
+ /* Initialize statistics */
+ p_input->c_loops = 0;
+ p_input->c_bytes = 0;
+ p_input->c_payload_bytes = 0;
+ p_input->c_packets_read = 0;
+ p_input->c_packets_trashed = 0;
#endif
- break;
- }
- /* Initialize PSI decoder. */
- intf_DbgMsg("Initializing PSI decoder\n");
- if( input_PsiInit( p_input ) == -1 )
+ /* Initialize PSI and PCR decoders */
+ if( input_PsiInit( p_input ) )
{
free( p_input );
return( NULL );
}
- /* Initialize PCR decoder. */
- intf_DbgMsg("Initializing PCR decoder\n");
- if( input_PcrInit( p_input ) == -1 )
+ if( input_PcrInit( p_input ) )
{
- input_PsiClean( p_input );
+ input_PsiEnd( p_input );
free( p_input );
return( NULL );
}
- /* Initialize netlists. */
- if( input_NetlistOpen( p_input ) )
+ /* Initialize netlists */
+ if( input_NetlistInit( p_input ) )
{
- input_PsiClean( p_input );
- input_PcrClean( p_input );
+ input_PsiEnd( p_input );
+ input_PcrEnd( p_input );
free( p_input );
return( NULL );
}
-#ifdef STATS
- /* Initialize counters. */
- p_input->c_bytes = 0;
- p_input->c_payload_bytes = 0;
- p_input->c_ts_packets_read = 0;
- p_input->c_ts_packets_trashed = 0;
-#ifdef DEBUG
- p_input->c_loops = 0;
-#endif
-#endif
+ intf_DbgMsg("configuration: method=%d, source=%s, port=%d, vlan=%d\n",
+ i_method, psz_source, i_port, i_vlan );
/* Let the appropriate method open the socket. */
- if( (*(p_input->p_open))( p_input, p_cfg ) == -1 )
+ if( p_input->p_Open( p_input ) )
{
- input_NetlistClean( p_input );
- input_PsiClean( p_input );
- input_PcrClean( p_input );
+ input_NetlistEnd( p_input );
+ input_PsiEnd( p_input );
+ input_PcrEnd( p_input );
free( p_input );
return( NULL );
}
- intf_DbgMsg("input debug: method %d properly initialized the socket\n",
- p_input->i_method);
-
/* Create thread and set locks. */
- p_input->b_die = 0;
vlc_mutex_init( &p_input->netlist.lock );
vlc_mutex_init( &p_input->programs_lock );
vlc_mutex_init( &p_input->es_lock );
-#ifdef NO_THREAD
- input_Thread( p_input );
-#else
- if( vlc_thread_create(&p_input->thread_id, "input", (vlc_thread_func_t)input_Thread,
- (void *) p_input) )
+ if( vlc_thread_create(&p_input->thread_id, "input", (void *) RunThread, (void *) p_input) )
{
- intf_ErrMsg("input error: can't spawn input thread (%s)\n",
- strerror(errno) );
- (*p_input->p_clean)( p_input );
- input_NetlistClean( p_input );;
- input_PsiClean( p_input );
- input_PcrClean( p_input );
+ intf_ErrMsg("error: %s\n", strerror(errno) );
+ p_input->p_Close( p_input );
+ input_NetlistEnd( p_input );;
+ input_PsiEnd( p_input );
+ input_PcrEnd( p_input );
free( p_input );
return( NULL );
}
-#endif
-
- /* Default setting for new decoders */
- p_input->p_aout = p_cfg->p_aout;
-
+
+ intf_Msg("Input initialized\n");
+
+ /* If status is NULL, wait until the thread is created */
+ if( pi_status == NULL )
+ {
+ do
+ {
+ msleep( THREAD_SLEEP );
+ }while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
+ && (i_status != THREAD_FATAL) );
+ if( i_status != THREAD_READY )
+ {
+ return( NULL );
+ }
+ }
return( p_input );
}
******************************************************************************
* This function should not return until the thread is effectively cancelled.
******************************************************************************/
-void input_DestroyThread( input_thread_t *p_input )
+void input_DestroyThread( input_thread_t *p_input, int *pi_status )
{
- intf_DbgMsg("input debug: requesting termination of input thread\n");
- p_input->b_die = 1; /* ask thread to kill itself */
+ int i_status; /* thread status */
+
+ /* Set status */
+ p_input->pi_status = (pi_status != NULL) ? pi_status : &i_status;
+ *p_input->pi_status = THREAD_DESTROY;
+
+ /* Request thread destruction */
+ p_input->b_die = 1;
- /* Remove this as soon as the "status" flag is implemented */
- vlc_thread_join( p_input->thread_id ); /* wait until it's done */
+ /* If status is NULL, wait until thread has been destroyed */
+ if( pi_status == NULL )
+ {
+ do
+ {
+ msleep( THREAD_SLEEP );
+ }while( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
+ && (i_status != THREAD_FATAL) );
+ }
}
#if 0
/* following functions are local */
/*******************************************************************************
- * input_Thread: input thread
+ * InitThread: initialize input thread
+ *******************************************************************************
+ * This function is called from RunThread and performs the second step of the
+ * initialization. It returns 0 on success. Note that the thread's flag are not
+ * modified inside this function.
+ *******************************************************************************/
+static int InitThread( input_thread_t *p_input )
+{
+ /* Mark thread as running and return */
+ intf_DbgMsg("\n");
+ *p_input->pi_status = THREAD_READY;
+ intf_DbgMsg("thread ready\n");
+ return( 0 );
+}
+
+/*******************************************************************************
+ * RunThread: main thread loop
*******************************************************************************
* Thread in charge of processing the network packets and demultiplexing.
*******************************************************************************/
-static void input_Thread( input_thread_t *p_input )
+static void RunThread( input_thread_t *p_input )
{
- intf_DbgMsg("input debug 11-1: thread %p is active\n", p_input);
+ /*
+ * Initialize thread and free configuration
+ */
+ p_input->b_error = InitThread( p_input );
+ if( p_input->b_error )
+ {
+ free( p_input ); /* destroy descriptor */
+ return;
+ }
+
+ /*
+ * Main loop
+ */
+ intf_DbgMsg("\n");
while( !p_input->b_die && !p_input->b_error )
{
/* Scatter read the UDP packet from the network or the file. */
#endif
}
+ /*
+ * Error loop
+ */
if( p_input->b_error )
{
ErrorThread( p_input );
}
- /* Ohoh, we have to die as soon as possible. */
+ /* End of thread */
EndThread( p_input );
-
- intf_DbgMsg("input debug: thread %p destroyed\n", p_input);
- vlc_thread_exit();
+ intf_DbgMsg("thread end\n");
}
/******************************************************************************
* ErrorThread: RunThread() error loop
+ *******************************************************************************
+ * This function is called when an error occured during thread main's loop.
******************************************************************************/
static void ErrorThread( input_thread_t *p_input )
{
+ /* Wait until a `die' order */
+ intf_DbgMsg("\n");
while( !p_input->b_die )
{
- msleep( INPUT_IDLE_SLEEP );
+ /* Sleep a while */
+ msleep( VOUT_IDLE_SLEEP );
}
}
*******************************************************************************/
static void EndThread( input_thread_t * p_input )
{
- int i_es_loop;
+ int * pi_status; /* threas status */
+ int i_es_loop; /* es index */
+
+ /* Store status */
+ intf_DbgMsg("\n");
+ pi_status = p_input->pi_status;
+ *pi_status = THREAD_END;
- (*p_input->p_clean)( p_input ); /* close input method */
+ /* Close input method */
+ p_input->p_Close( p_input );
- /* Destroy all decoder threads. */
- for( i_es_loop = 0; i_es_loop < INPUT_MAX_ES; i_es_loop++ )
+ /* Destroy all decoder threads */
+ for( i_es_loop = 0;
+ (i_es_loop < INPUT_MAX_ES) && (p_input->pp_selected_es[i_es_loop] != NULL) ;
+ i_es_loop++ )
{
- if( p_input->pp_selected_es[i_es_loop] )
+ switch( p_input->pp_selected_es[i_es_loop]->i_type )
{
- switch( p_input->pp_selected_es[i_es_loop]->i_type )
- {
- case MPEG1_VIDEO_ES:
- case MPEG2_VIDEO_ES:
+ case MPEG1_VIDEO_ES:
+ case MPEG2_VIDEO_ES:
#ifdef OLD_DECODER
- vdec_DestroyThread( (vdec_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) /*, NULL */ );
+ vdec_DestroyThread( (vdec_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) /*, NULL */ );
#else
- vpar_DestroyThread( (vpar_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) /*, NULL */ );
+ vpar_DestroyThread( (vpar_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) /*, NULL */ );
#endif
- break;
-
- case MPEG1_AUDIO_ES:
- case MPEG2_AUDIO_ES:
- adec_DestroyThread( (adec_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) );
- break;
-
- case AC3_AUDIO_ES:
- ac3dec_DestroyThread( (ac3dec_thread_t *)(p_input->pp_selected_es[i_es_loop]->p_dec) );
- break;
-
- default:
- break;
- }
- }
- else
- {
- /* pp_selected_es should not contain any hole. */
+ break;
+ case MPEG1_AUDIO_ES:
+ case MPEG2_AUDIO_ES:
+ adec_DestroyThread( (adec_thread_t*)(p_input->pp_selected_es[i_es_loop]->p_dec) );
+ break;
+ case AC3_AUDIO_ES:
+ ac3dec_DestroyThread( (ac3dec_thread_t *)(p_input->pp_selected_es[i_es_loop]->p_dec) );
break;
+#ifdef DEBUG
+ default:
+ intf_DbgMsg("error: unknown decoder type %d\n", p_input->pp_selected_es[i_es_loop]->i_type );
+ break;
+#endif
}
}
- input_NetlistClean( p_input ); /* clean netlist */
- input_PsiClean( p_input ); /* clean PSI information */
- input_PcrClean( p_input ); /* clean PCR information */
- free( p_input ); /* free input_thread structure */
+ input_NetlistEnd( p_input ); /* clean netlist */
+ input_PsiEnd( p_input ); /* clean PSI information */
+ input_PcrEnd( p_input ); /* clean PCR information */
+ free( p_input ); /* free input_thread structure */
- intf_DbgMsg("input debug: EndThread(%p)\n", p_input);
+ /* Update status */
+ *pi_status = THREAD_OVER;
}
/*******************************************************************************
#endif /* FIFO netlist */
/* Scatter read the buffer. */
- i_packet_size = (*p_input->p_read)( p_input,
+ i_packet_size = (*p_input->p_Read)( p_input,
&p_input->netlist.p_ts_free[i_base_index],
INPUT_TS_READ_ONCE );
if( i_packet_size == (-1) )
#endif
#ifdef STATS
- p_input->c_ts_packets_read += i_current_index - i_base_index;
+ p_input->c_packets_read += i_current_index - i_base_index;
p_input->c_bytes += (i_current_index - i_base_index) * TS_PACKET_SIZE;
#endif
- return( 0 );
+ return( 0 );
}
/*******************************************************************************
// U16_AT(&p_ts_packet->buffer[1]) & 0x1fff);
input_NetlistFreeTS( p_input, p_ts_packet );
#ifdef STATS
- p_input->c_ts_packets_trashed++;
+ p_input->c_packets_trashed++;
#endif
}
{
input_NetlistFreeTS( p_input, p_ts_packet );
#ifdef STATS
- p_input->c_ts_packets_trashed++;
+ p_input->c_packets_trashed++;
#endif
}
else
{
/* The FIFO is full !!! This should not happen. */
#ifdef STATS
- p_input->c_ts_packets_trashed += p_pes->i_ts_packets;
+ p_input->c_packets_trashed += p_pes->i_ts_packets;
p_es_descriptor->c_invalid_packets += p_pes->i_ts_packets;
#endif
input_NetlistFreePES( p_input, p_pes );
{
intf_DbgMsg("No fifo to receive PES %p: trash\n", p_pes);
#ifdef STATS
- p_input->c_ts_packets_trashed += p_pes->i_ts_packets;
+ p_input->c_packets_trashed += p_pes->i_ts_packets;
p_es_descriptor->c_invalid_packets += p_pes->i_ts_packets;
#endif
input_NetlistFreePES( p_input, p_pes );
/*******************************************************************************
- * file.c: functions to read from a file
+ * input_file.c: functions to read from a file
* (c)1999 VideoLAN
*******************************************************************************/
#include "input_file.h"
/******************************************************************************
- * input_FileCreateMethod : open a file descriptor
+ * input_FileOpen : open a file descriptor
******************************************************************************/
-int input_FileCreateMethod( input_thread_t *p_input ,
- input_cfg_t *p_cfg )
+int input_FileOpen( input_thread_t *p_input )
{
- return( -1 );
+ //??
+ return( 1 );
}
/******************************************************************************
int input_FileRead( input_thread_t *p_input, const struct iovec *p_vector,
size_t i_count )
{
- return( -1 );
+ //??
+ return( -1 );
}
/******************************************************************************
- * input_FileDestroyMethod : close a file descriptor
+ * input_FileClose : close a file descriptor
******************************************************************************/
-void input_FileDestroyMethod( input_thread_t *p_input )
+void input_FileClose( input_thread_t *p_input )
{
+ //??
}
/******************************************************************************
* input_NetlistOpen: initialize the netlists buffers
******************************************************************************/
-int input_NetlistOpen( input_thread_t *p_input )
+int input_NetlistInit( input_thread_t *p_input )
{
int i_base, i_packets, i_iovec;
/******************************************************************************
* input_NetlistClean: clean the netlists buffers
******************************************************************************/
-void input_NetlistClean( input_thread_t *p_input )
+void input_NetlistEnd( input_thread_t *p_input )
{
int i;
#include "intf_msg.h"
/******************************************************************************
- * Local prototypes
+ * input_NetworkOpen: initialize a network stream
******************************************************************************/
-
-
-/******************************************************************************
- * input_NetworkCreateMethod: initialize a network stream
- ******************************************************************************/
-int input_NetworkCreateMethod( input_thread_t *p_input,
- input_cfg_t *p_cfg )
+int input_NetworkOpen( input_thread_t *p_input )
{
- int i_socket_option, i_port, i_dummy;
+ int i_socket_option;
struct sockaddr_in sa_in;
- char psz_hostname[INPUT_MAX_HOSTNAME_LENGTH];
+ char psz_hostname[INPUT_MAX_SOURCE_LENGTH];
- /* First and foremost, in the VLAN method, we join the desired VLAN. */
+ /* First and foremost, in the VLAN method, join the desired VLAN. */
if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
{
- /* Get a VLAN ID (VlanLib). */
- if( ( p_input->i_vlan_id = input_VlanId( NULL, p_cfg->i_vlan ) )
- == (-1) )
+ if( input_VlanJoin( p_input->i_vlan ) )
{
- intf_ErrMsg("input error: VlanId() failed (%d)\n",
- p_input->i_vlan_id);
- return( -1 );
- }
- /* Join the VLAN. */
- if( ( i_dummy = input_VlanJoin( p_input->i_vlan_id ) ) != 0 )
- {
- intf_ErrMsg("input error: VlanJoin() failed (%d)\n",
- i_dummy);
- return( -1 );
- }
+ intf_ErrMsg("error: can't join vlan %d\n", p_input->i_vlan);
+ return( 1 );
+ }
}
- /* We open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
+ /* Open a SOCK_DGRAM (UDP) socket, in the AF_INET domain, automatic (0)
* protocol */
if( (p_input->i_handle = socket( AF_INET, SOCK_DGRAM, 0 )) == (-1) )
{
- intf_ErrMsg("input error: socket() error (%s)\n",
- strerror(errno));
- return( -1 );
+ intf_ErrMsg("error: can't create socket (%s)\n", strerror(errno));
+ return( 1 );
}
- intf_DbgMsg("input debug: socket %d opened (cfg: %p)\n", p_input->i_handle,
- p_cfg);
-
- /* we set up the options of our socket. It doesn't need to be non-blocking,
- * on the contrary (when this thread is waiting for data, it doesn't have
- * the lock, so decoders can work. */
+ /*
+ * Set up the options of the socket
+ */
- /* set SO_REUSEADDR option which allows to re-bind() a busy port */
+ /* Set SO_REUSEADDR option which allows to re-bind() a busy port */
i_socket_option = 1;
if( setsockopt( p_input->i_handle,
SOL_SOCKET,
&i_socket_option,
sizeof( i_socket_option ) ) == (-1) )
{
- intf_ErrMsg("input error: setsockopt(SO_REUSEADDR) error (%s)\n",
- strerror(errno));
+ intf_ErrMsg("error: can't configure socket (%s)\n", strerror(errno));
close( p_input->i_handle );
- return( -1 );
+ return( 1 );
}
/* Increase the receive buffer size to 1/2MB (8Mb/s during 1/2s) to avoid
&i_socket_option,
sizeof( i_socket_option ) ) == (-1) )
{
- intf_ErrMsg("input error: setsockopt(SO_RCVBUF) error (%s)\n",
- strerror(errno));
+ intf_ErrMsg("error: can't configure socket (%s)\n", strerror(errno));
close( p_input->i_handle );
- return( -1 );
+ return( 1 );
}
- /* Now, we bind the socket. */
+ /*
+ * Bind the socket
+ */
- /* Find the port. */
- if( p_cfg->i_properties & INPUT_CFG_PORT )
+ /* Use default port if not specified */
+ if( p_input->i_port == 0 )
{
- i_port = p_cfg->i_port;
- intf_DbgMsg("input debug: using port %d\n", i_port);
- }
- else
- {
-#ifdef VIDEOLAN_DEFAULT_PORT
- /* default port */
- i_port = VIDEOLAN_DEFAULT_PORT;
- intf_DbgMsg("input debug: using default port (%d)\n", i_port);
-#else
- intf_ErrMsg("input error: no default port\n");
- return( -1 );
-#endif
+ p_input->i_port = INPUT_DEFAULT_PORT;
}
/* Find the address. */
switch( p_input->i_method )
{
- case INPUT_METHOD_TS_BCAST:
- case INPUT_METHOD_TS_VLAN_BCAST:
- /* In that case, we have to bind with the broadcast address.
- * broadcast addresses are very hard to find and depends on
- * implementation, so we thought using a #define would be much
- * simpler. */
+ case INPUT_METHOD_TS_BCAST:
+ case INPUT_METHOD_TS_VLAN_BCAST:
+ /* In that case, we have to bind with the broadcast address.
+ * broadcast addresses are very hard to find and depends on
+ * implementation, so we thought using a #define would be much
+ * simpler. */
#ifdef INPUT_BCAST_ADDR
- if( BuildInetAddr( &sa_in, INPUT_BCAST_ADDR, i_port ) == (-1) )
- { /* see netutils.c */
- close( p_input->i_handle );
- return( -1 );
- }
+ if( BuildInetAddr( &sa_in, INPUT_BCAST_ADDR, p_input->i_port ) == (-1) )
+ {
+ close( p_input->i_handle );
+ return( 1 );
+ }
#else
- /* We bind with any address. Security problem ! */
- if( BuildInetAddr( &sa_in, NULL, i_port ) == (-1) )
- {
- close( p_input->i_handle );
- return( -1 ),
- }
+ /* We bind with any address. Security problem ! */
+ if( BuildInetAddr( &sa_in, NULL, p_input->i_port ) == (-1) )
+ {
+ close( p_input->i_handle );
+ return( -1 );
+ }
#endif
- break;
+ break;
- case INPUT_METHOD_TS_UCAST:
- /* We bind with the local address. */
- if( gethostname( psz_hostname, sizeof( psz_hostname ) ) == (-1) )
- {
- intf_ErrMsg("input error: gethostname failed (%s)\n",
- strerror(errno));
- close( p_input->i_handle );
- return( -1 );
- }
- if( BuildInetAddr( &sa_in, psz_hostname, i_port ) == (-1) )
- {
- close( p_input->i_handle );
- return( -1 );
- }
- break;
- case INPUT_METHOD_TS_MCAST:
- /* We bind with 239.0.0.1. */
- if( BuildInetAddr( &sa_in, "239.0.0.1", i_port ) == (-1) )
- {
- close( p_input->i_handle );
- return( -1 );
- }
- break;
+ case INPUT_METHOD_TS_UCAST:
+ /* Unicast: bind with the local address. */
+ if( gethostname( psz_hostname, sizeof( psz_hostname ) ) == (-1) )
+ {
+ intf_ErrMsg("error: can't get hostname (%s)\n", strerror(errno));
+ close( p_input->i_handle );
+ return( 1 );
+ }
+ if( BuildInetAddr( &sa_in, psz_hostname, p_input->i_port ) == (-1) )
+ {
+ close( p_input->i_handle );
+ return( 1 );
+ }
+ break;
+
+ case INPUT_METHOD_TS_MCAST:
+ /* Multicast: bind with 239.0.0.1. */
+ if( BuildInetAddr( &sa_in, "239.0.0.1", p_input->i_port ) == (-1) )
+ {
+ close( p_input->i_handle );
+ return( 1 );
+ }
+ break;
}
/* Effectively bind the socket. */
- if( bind( p_input->i_handle,
- (struct sockaddr *) &sa_in,
- sizeof( sa_in ) ) < 0 )
+ if( bind( p_input->i_handle, (struct sockaddr *) &sa_in, sizeof( sa_in ) ) < 0 )
{
- intf_ErrMsg("input error: bind() failed (%s)\n",
- strerror(errno));
+ intf_ErrMsg("error: can't bind socket (%s)\n", strerror(errno));
close( p_input->i_handle );
- return( -1 );
+ return( 1 );
}
- /* Connect the socket to the remote server. */
+ /*
+ * Connect the socket to the remote server
+ */
- /* Find which server we have to use. */
- if( p_cfg->i_properties & INPUT_CFG_HOSTNAME )
- {
- if( BuildInetAddr( &sa_in, p_cfg->psz_hostname, htons(0) ) == (-1) )
- {
- close( p_input->i_handle );
- return( -1 );
- }
- }
- else if( p_cfg->i_properties & INPUT_CFG_IP )
+ /* Use default host if not specified */
+ if( p_input->psz_source == NULL )
{
- if( BuildInetAddr( &sa_in, p_cfg->psz_ip, htons(0) ) == (-1) )
- {
- close( p_input->i_handle );
- return( -1 );
- }
+ p_input->psz_source = INPUT_DEFAULT_SERVER;
}
- else
+
+ if( BuildInetAddr( &sa_in, p_input->psz_source, htons(0) ) == (-1) )
{
-#ifdef VIDEOLAN_DEFAULT_SERVER
- /* default server */
- if( BuildInetAddr( &sa_in, VIDEOLAN_DEFAULT_SERVER, htons(0) ) == (-1) )
- {
- close( p_input->i_handle );
- return( -1 );
- }
-#else
- intf_ErrMsg("input error: no default videolan server\n");
+ close( p_input->i_handle );
return( -1 );
-#endif
}
- /* Effectively connect the socket. */
- if( connect( p_input->i_handle,
- (struct sockaddr *) &sa_in,
+ /* Connect the socket. */
+ if( connect( p_input->i_handle, (struct sockaddr *) &sa_in,
sizeof( sa_in ) ) == (-1) )
{
- intf_ErrMsg("input error: connect() failed\n");
+ intf_ErrMsg("error: can't connect socket\n" );
close( p_input->i_handle );
- return( -1 );
+ return( 1 );
}
return( 0 );
}
}
/******************************************************************************
- * input_NetworkDestroyMethod: close a network stream
+ * input_NetworkClose: close a network stream
******************************************************************************/
-void input_NetworkDestroyMethod( input_thread_t *p_input )
+void input_NetworkClose( input_thread_t *p_input )
{
/* Close local socket. */
if( p_input->i_handle )
{
- if( close( p_input->i_handle) == (-1) )
- {
- intf_ErrMsg("input error: can't close network socket (%s)\n",
- strerror(errno) );
- }
+ close( p_input->i_handle );
}
- /* In case of VLAN method, leave the current VLAN. */
+ /* Leave vlan if required */
if( p_input->i_method == INPUT_METHOD_TS_VLAN_BCAST )
- {
- input_VlanLeave( p_input->i_vlan_id );
- }
+ {
+ input_VlanLeave( p_input->i_vlan );
+ }
}
+
}
/******************************************************************************
- * input_PcrClean : Clean PCR structures before dying
+ * input_PcrEnd : Clean PCR structures before dying
******************************************************************************/
-void input_PcrClean( input_thread_t *p_input )
+void input_PcrEnd( input_thread_t *p_input )
{
ASSERT( p_input );
/******************************************************************************
* input_PsiClean: Clean PSI structures before dying
******************************************************************************/
-int input_PsiClean( input_thread_t *p_input )
+int input_PsiEnd( input_thread_t *p_input )
{
ASSERT(p_input);
/*******************************************************************************
- * input_vlan.c: vlan input method
+ * input_vlan.c: vlan management library
* (c)1999 VideoLAN
- *******************************************************************************
- * ??
*******************************************************************************/
-/* ???????????????????????????????????????????????????????????????????????????
- * This works (well, it should :), but should have a good place in horror museum:
- * - the vlan-capable interfaces are retrieved from a names list, instead
- * of being read from the system
- * - the vlan server sucks, and therefore the vlan clients sucks:
- * - it is unable to process several operations between a login and a logout
- * A lot of requests could be grouped if it could.
- * - it is incoherent concerning it's messages (and what it needs to perform
- * an operation
- * - it is totally unable to handle several mac adresses on a single switch
- * port (and therefore bridged/hubbed machines)
- * - however, the API is ok, should be able to handle all futures evolutions,
- * including vlan-conscient cards.
- *
- * So there is a lot to do in this file, but not before having reprogrammed the
- * vlan server !
- * What would be a good interface to the vlan server ? Here are some ideas:
- * ( later ! )
- * ??????????????????????????????????????????????????????????????????????????? */
-
/*******************************************************************************
* Preamble
*******************************************************************************/
-#include "vlc.h"
-
-/*#include <errno.h>
-#include <pthread.h>
#include <errno.h>
-#include <unistd.h>
#include <stdio.h>
-#include <stdlib.h>
+#include <unistd.h>
#include <string.h>
+#include <stdlib.h>
+
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
-#include <sys/soundcard.h>
-#include <sys/uio.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/XShm.h>
+#include <sys/socket.h>
#include "config.h"
#include "common.h"
#include "mtime.h"
#include "vlc_thread.h"
#include "netutils.h"
-
-#include "input.h"
#include "input_vlan.h"
-
-#include "audio_output.h"
-
-#include "video.h"
-#include "video_output.h"
-
-#include "xconsole.h"
-#include "interface.h"
#include "intf_msg.h"
-
-#include "pgm_data.h"*/
-
-/*******************************************************************************
- * input_vlan_iface_t: vlan-capable network interface
- *******************************************************************************
- * This structure describes the abilities of a network interface capable of
- * vlan management. Note that an interface could have several IP adresses, but
- * since only the MAC address is used to change vlan, only one needs to be
- * retrieved.
- * ?? it could be interesting to send a port id on vlan request, to know if two
- * interfaces are dependant regarding vlan changes.
- *******************************************************************************/
-typedef struct
-{
- char * psz_name; /* interface name */
- struct sockaddr_in sa_in; /* interface IP */
- char psz_mac[20]; /* interface MAC */
-
- /* Hardware properties */
- int i_master; /* master interface index */
- int i_switch; /* switch number */
- int i_port; /* port number */
- int i_sharers; /* number of MACs on this port */
-
- /* Vlan properties - these are only used if i_master is negative */
- int i_refcount; /* locks counter */
- int i_vlan; /* current vlan */
- int i_default_vlan; /* default vlan */
-} input_vlan_iface_t;
-
-/*******************************************************************************
- * input_vlan_server_t: vlan server
- *******************************************************************************
- * This structure describes a vlan server.
- *******************************************************************************/
-typedef struct
-{
- struct sockaddr_in sa_in; /* server address */
- int i_socket; /* socket descriptor */
-
- /* Login informations */
- char * psz_login; /* server login */
- char * psz_passwd; /* server password */
-} input_vlan_server_t;
+#include "main.h"
/*******************************************************************************
- * vlan_method_data_t
+ * input_vlan_t: vlan library data
*******************************************************************************
* Store global vlan library data.
*******************************************************************************/
-typedef struct input_vlan_method_s
+typedef struct input_vlan_s
{
- vlc_mutex_t lock; /* library lock */
-
- /* Server */
- input_vlan_server_t server; /* vlan server */
-
- /* Network interfaces */
- int i_ifaces; /* number of vlan-compliant interfaces */
- input_vlan_iface_t * p_iface; /* interfaces */
-} input_vlan_method_t;
-
-/*
- * Constants
- */
+ int i_dummy;
+} input_vlan_t;
-/* List of vlan-capable interfaces names */
-static const char *psz_ifaces_names[] = { "eth0", "eth1", "eth2", "eth3", "eth4", "eth5", NULL };
-
-/*
+/*******************************************************************************
* Local prototypes
- */
-static int IfaceInfo ( input_vlan_iface_t *p_iface );
-static int IfaceDependance ( input_vlan_method_t *p_method, int i_iface );
-static int ServerLogin ( input_vlan_server_t *p_server );
-static void ServerLogout ( input_vlan_server_t *p_server );
-static int ServerRequestChange ( input_vlan_server_t *p_server,
- input_vlan_iface_t *p_iface, int i_vlan );
-static int ServerRequestInfo ( input_vlan_server_t *p_server,
- input_vlan_iface_t *p_iface );
+ *******************************************************************************/
+static int ZeTrucMucheFunction( int Channel );
/*******************************************************************************
* input_VlanCreate: initialize global vlan method data
*******************************************************************************/
int input_VlanCreate( void )
{
- char * psz_server; // ??? get from environment
- int i_port; // ??? get from environment
- int i_index; /* interface/servers index */
- input_vlan_iface_t * p_iface; /* interfaces */
- input_vlan_method_t *p_method = p_main->p_input_vlan; //??
-
- /* Build vlan server descriptor */
- if( BuildInetAddr( &p_method->server.sa_in, psz_server, i_port ) )
- {
- return( -1 );
- }
-
- /* Allocate interfaces array */
- for( i_index = 0; psz_ifaces_names[i_index] != NULL; i_index++ )
- {
- ;
- }
- p_iface = malloc( sizeof(input_vlan_iface_t) * i_index );
- if( p_iface == NULL )
- {
- return( ENOMEM );
- }
-
- /* Initialize interfaces array */
- for( i_index = p_method->i_ifaces = 0; psz_ifaces_names[i_index] != NULL; i_index++ )
- {
- /* Retrieve interface name */
- p_iface[p_method->i_ifaces].psz_name = (char *) psz_ifaces_names[i_index];
-
- /* Test if interface is vlan-capable */
- if( !IfaceInfo( &p_iface[p_method->i_ifaces] ) )
- {
- /* If interface passed first step, login to vlan server */
- if( !ServerLogin( &p_method->server ) )
- {
- /* Request informations from server about the interface - if the interface
- * pass this last test, it is vlan-capable and can be added to the list of
- * interfaces. */
- if( !ServerRequestInfo( &p_method->server, &p_iface[p_method->i_ifaces]) )
- {
- /* Check if interface is dependant */
- if( !IfaceDependance( p_method, p_method->i_ifaces ) )
- {
- /* Interface is master: initialize properties */
- p_iface[p_method->i_ifaces].i_default_vlan = p_iface[p_method->i_ifaces].i_vlan;
- p_iface[p_method->i_ifaces].i_refcount = 0;
- intf_DbgMsg("input debug: added vlan-capable interface %s (%s)\n",
- p_iface[p_method->i_ifaces].psz_name,
- p_iface[p_method->i_ifaces].psz_mac);
- }
-#ifdef DEBUG
- else
- {
- /* Interface is slave */
- intf_DbgMsg("input debug: added vlan-capable interface %s (%s), depends from %s\n",
- p_iface[p_method->i_ifaces].psz_name,
- p_iface[p_method->i_ifaces].psz_mac,
- p_iface[p_iface[p_method->i_ifaces].i_master].psz_name );
- }
-#endif
- /* Increment size counter */
- p_method->i_ifaces++;
- }
- /* Logout from server */
- ServerLogout( &p_method->server );
- }
- }
- }
-
- /* If number of vlan-capable interfaces is null, then desactivate vlans */
- if( p_method->i_ifaces == 0 )
+ /* Allocate structure */
+ p_main->p_vlan = malloc( sizeof( input_vlan_t ) );
+ if( p_main->p_vlan == NULL )
{
- free( p_iface );
- return( -1 );
+ intf_ErrMsg("error: %s\n", strerror(ENOMEM));
+ return( 1 );
}
-
- /* Reallocate interfaces array to save memory */
- p_method->p_iface = realloc( p_iface, sizeof(input_vlan_iface_t) * p_method->i_ifaces );
- if( p_method->p_iface == NULL )
- {
- /* Realloc failed, but the previous pointer is still valid */
- p_method->p_iface = p_iface;
- }
-
- /* Initialize lock */
- vlc_mutex_init( &p_method->lock );
- intf_Msg("input: vlans input method installed\n", p_method->i_ifaces);
+ intf_Msg("VLANs initialized\n");
return( 0 );
}
*******************************************************************************/
void input_VlanDestroy( void )
{
- int i_index; /* server/interface index */
- input_vlan_method_t *p_method = p_main->p_input_vlan; // ??
-
- /* Leave all remaining vlans */
- for( i_index = 0; i_index < p_method->i_ifaces; i_index++ )
- {
-#ifdef DEBUG
- /* Check if interface is still locked */
- if( p_method->p_iface[i_index].i_refcount )
- {
- intf_DbgMsg("input debug: interface %s is still vlan-locked\n",
- p_method->p_iface[i_index].psz_name);
- p_method->p_iface[i_index].i_refcount = 0;
- }
-#endif
- /* Join default (starting) vlan */
- input_VlanJoin( VLAN_ID( i_index, p_method->p_iface[i_index].i_default_vlan ) );
- }
-
- /* Free interfaces array */
- free( p_method->p_iface );
-
- intf_DbgMsg("input debug: vlan method terminated\n");
-}
-
-/*******************************************************************************
- * input_VlanId: get a vlan_id for a given interface
- *******************************************************************************
- * Get a vlan_id given a network interface and a vlan number. If psz_iface is
- * NULL, then the default network interface will be used. A negative value
- * will be returned in case of error.
- *******************************************************************************/
-int input_VlanId( char *psz_iface, int i_vlan )
-{
- input_vlan_method_t * p_method; /* method global data */
- int i_index; /* interface index */
-
- p_method = p_main->p_input_vlan;
-
- /* If psz_iface is NULL, use first (default) interface (if there is one) */
- if( psz_iface == NULL )
- {
- return( p_method->i_ifaces ? VLAN_ID( 0, i_vlan ) : -1 );
- }
-
- /* Browse all interfaces */
- for( i_index = 0; i_index < p_main->p_input_vlan->i_ifaces ; i_index++ )
- {
- /* If interface has been found, return */
- if( !strcmp( p_main->p_input_vlan->p_iface[i_index].psz_name, psz_iface ) )
- {
- return( VLAN_ID( i_index, i_vlan ) );
- }
- }
-
- return( -1 );
+ /* Free structure */
+ free( p_main->p_vlan );
}
/*******************************************************************************
*******************************************************************************/
int input_VlanJoin( int i_vlan_id )
{
- input_vlan_method_t * p_method; /* method global data */
- input_vlan_iface_t * p_iface; /* interface (shortcut) */
- int i_err; /* error indicator */
-
- /* Initialize shortcuts, and use master if interface is dependant */
- i_err = 0;
- p_method = p_main->p_input_vlan;
- p_iface = &p_method->p_iface[ VLAN_ID_IFACE( i_vlan_id ) ];
- if( p_iface->i_master >= 0 )
- {
- p_iface = &p_method->p_iface[ p_iface->i_master ];
- }
-
- /* Get lock */
- vlc_mutex_lock( &p_method->lock );
-
- /* If the interface is in the wished vlan, increase lock counter */
- if( p_iface->i_vlan != VLAN_ID_VLAN( i_vlan_id ) )
- {
- p_iface->i_refcount++;
- }
- /* If not, if it is not locked, the vlan can be changed */
- else if( !p_iface->i_refcount )
- {
- /* Login to server */
- if( (i_err = !ServerLogin( &p_method->server )) )
- {
-
- /* Request vlan change */
- if( (i_err = !ServerRequestChange( &p_method->server,
- p_iface, VLAN_ID_VLAN( i_vlan_id ) ) ) )
- {
- p_iface->i_refcount++;
- }
- /* Logout */
- ServerLogout( &p_method->server );
- }
- }
- /* Else, the vlan is locked and can't be changed */
- else
- {
- i_err = 1;
- }
-
- /* Release lock (if this point is reached, the function succeeded) */
- vlc_mutex_unlock( &p_method->lock );
- return( i_err );
+ intf_Msg("Joining VLAN %d (channel %d)\n", i_vlan_id + 2, i_vlan_id );
+ return( ZeTrucMucheFunction( i_vlan_id ) ); // ?? join vlan
}
/*******************************************************************************
*******************************************************************************/
void input_VlanLeave( int i_vlan_id )
{
- input_vlan_method_t * p_method; /* method global data */
- input_vlan_iface_t * p_iface; /* interface (shortcut) */
- int i_err; /* error indicator */
-
- /* Initialize shortcuts, and use master if interface is dependant */
- i_err = 0;
- p_method = p_main->p_input_vlan;
- p_iface = &p_method->p_iface[ VLAN_ID_IFACE( i_vlan_id ) ];
- if( p_iface->i_master >= 0 )
- {
- p_iface = &p_method->p_iface[ p_iface->i_master ];
- }
-
- /* Get lock */
- vlc_mutex_lock( &p_method->lock );
-
- /* Decrease reference counter */
- p_method->p_iface[ VLAN_ID_IFACE( i_vlan_id ) ].i_refcount--;
-
- /* Release lock */
- vlc_mutex_unlock( &p_method->lock );
-}
-
-/*******************************************************************************
- * input_VlanRequest: request vlan number for a given interface
- *******************************************************************************
- * Request the vlan number (and not id) of a given network interface. A
- * connection to the server can eventually occur, event if it not the case in
- * current implementation. A negative number can be returned on error.
- *******************************************************************************/
-int input_VlanRequest( char *psz_iface )
-{
- input_vlan_method_t * p_method; /* method global data */
- int i_index; /* interface index */
-
- p_method = p_main->p_input_vlan;
-
- /* If psz_iface is NULL, use first (default) interface (if there is one) -
- * note that interface 0 can't be dependant, so dependance does not need
- * to be tested */
- if( psz_iface == NULL )
- {
- return( p_method->i_ifaces ? p_method->p_iface[0].i_vlan : -1 );
- }
-
- /* Browse all interfaces */
- for( i_index = 0; i_index < p_method->i_ifaces ; i_index++ )
- {
- /* If interface has been found, return vlan */
- if( !strcmp( p_method->p_iface[i_index].psz_name, psz_iface ) )
- {
- /* If interface is dependant, use master, else return own vlan */
- return( (p_method->p_iface[i_index].i_master >= 0) ?
- p_method->p_iface[p_method->p_iface[i_index].i_master].i_vlan :
- p_method->p_iface[i_index].i_vlan );
- }
- }
-
- /* If not found, return an error */
- return( -1 );
-}
-
-/*******************************************************************************
- * input_VlanSynchronize: resynchronize with vlan server
- *******************************************************************************
- * Resynchronize with the vlan server. Vlans for all interfaces are requested
- * and changed if required. This call may take a lot of time, and is intended
- * for emergency situations.
- *******************************************************************************/
-int input_VlanSynchronize( void )
-{
- input_vlan_method_t * p_method; /* method global data */
- input_vlan_iface_t * p_iface; /* interface (shortcut) */
- int i_index; /* interface index */
- int i_vlan; /* vlan for current interface */
-
- /* Get lock */
- p_method = p_main->p_input_vlan;
- pthread_mutex_lock( &p_method->lock );
-/* ??
- p_method = &p_program_data->input_vlan_method;
- vlc_mutex_lock( &p_method->lock );
-*/
-
- for( i_index = 0; i_index < p_method->i_ifaces; i_index++ )
- {
- p_iface = &p_method->p_iface[ i_index ];
-
- /* Ignore dependant interfaces and interfaces for wich login failed */
- if( (p_iface->i_master < 0) && !ServerLogin( &p_method->server ) )
- {
- /* Request interface informations */
- i_vlan = p_iface->i_vlan;
- if( !ServerRequestInfo( &p_method->server, p_iface ) )
- {
- /* If synchronization has been lost, then try to resynchronize -
- * this part is ugly because of the vlan server bug requiring a
- * logout between two requests */
- if( p_iface->i_vlan != i_vlan )
- {
- intf_Msg("input: lost vlan synchronization for interface %s\n",
- p_iface->psz_name );
- ServerLogout( &p_method->server );
- if( !ServerLogin( &p_method->server ) )
- {
- if( !ServerRequestChange( &p_method->server, p_iface, i_vlan ) )
- {
- intf_Msg("input: retrieved vlan synchronization for interface %s\n",
- p_iface->psz_name );
- }
- }
- /* Note that when this login fails, then the next logout will
- * also fail... but I don't want to spend time finding a
- * clean way to avoid this if the vlan server bug is fixed */
- }
- }
- /* Logout */
- ServerLogout( &p_method->server );
- }
- }
-
- /* Release lock */
- vlc_mutex_unlock( &p_method->lock );
- return( 0 );
+ intf_Msg("Leaving VLAN %d (channel %d)\n", i_vlan_id + 2, i_vlan_id );
+ ZeTrucMucheFunction( 0 ); // ?? join default vlan
}
/* following functions are local */
-/*******************************************************************************
- * IfaceInfo: read info about an interface
- *******************************************************************************
- * This function reads informations about a network interface. It should return
- * 0 and updated interface informations for vlan capable interfaces, and non 0
- * if interface is not vlan-capable or informations request failed.
- *******************************************************************************/
-static int IfaceInfo( input_vlan_iface_t *p_iface )
+static int ZeTrucMucheFunction( int Channel)
{
- int i_socket;
- struct ifreq device;
-
- /* Copy interface name */
- strcpy(device.ifr_name, p_iface->psz_name);
-
- /* Open a datagram socket */
- i_socket = socket(AF_INET, SOCK_DGRAM, 0);
- if(i_socket < 0)
- {
- intf_ErrMsg("input error: unable to open socket on %s: %s\n",
- p_iface->psz_name, strerror(errno));
- return( -1 );
- }
-
- /* Read IP address */
- if(ioctl(i_socket, SIOCGIFDSTADDR, &device) < 0)
- {
- intf_ErrMsg("input error: can not read IP address for %s: %s\n",
- p_iface->psz_name, strerror(errno));
- return( -1 );
- }
- memcpy( &p_iface->sa_in, &device.ifr_hwaddr, sizeof(struct sockaddr_in));
-
- /* Read MAC address */
- if(ioctl(i_socket, SIOCGIFHWADDR, &device) < 0)
- {
- intf_ErrMsg("input error: can not read MAC address for %s: %s\n",
- p_iface->psz_name, strerror(errno));
- return( -1 );
- }
-
- /* Translate MAC address to ASCII standard */
- sprintf(p_iface->psz_mac, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
- device.ifr_hwaddr.sa_data[0]&0xff,
- device.ifr_hwaddr.sa_data[1]&0xff,
- device.ifr_hwaddr.sa_data[2]&0xff,
- device.ifr_hwaddr.sa_data[3]&0xff,
- device.ifr_hwaddr.sa_data[4]&0xff,
- device.ifr_hwaddr.sa_data[5]&0xff);
-
- return( 0 );
-}
-
-/*******************************************************************************
- * IfaceDependance: check interface dependance
- *******************************************************************************
- * Check if an interface designed by it's index is dependant from another one.
- * All the interfaces from 0 to i_index excluded are tested. If a 'master'
- * interface is found, then the 'i_master' field is set to a positive value.
- * Non 0 is returned if the interface is dependant.
- *******************************************************************************/
-static int IfaceDependance( input_vlan_method_t *p_method, int i_iface )
-{
- int i_index; /* interface index */
-
- for( i_index = 0; i_index < i_iface; i_index++ )
- {
- /* Two interface are dependant if they are on the same switch and
- * port */
- if( ( p_method->p_iface[i_index].i_switch == p_method->p_iface[i_iface].i_switch )
- && ( p_method->p_iface[i_index].i_port == p_method->p_iface[i_iface].i_port ) )
- {
- /* Interface is slave */
- p_method->p_iface[i_iface].i_master = i_index;
- return( 1 );
- }
- }
-
- /* Interface is master */
- p_method->p_iface[i_iface].i_master = -1;
- return( 0 );
-}
-
-/*******************************************************************************
- * ServerLogin: login to a vlan server
- *******************************************************************************
- * Initiate login sequence to a vlan server: open a socket, bind it and send
- * login sequence. If the login fails for any reason, non 0 is returned.
- *******************************************************************************/
-static int ServerLogin( input_vlan_server_t *p_server )
-{
- struct sockaddr_in sa_client; /* client address */
- char psz_msg[VLAN_SERVER_MSG_LENGTH + 1];/* server message */
- int i_bytes; /* number of bytes read */
-
- psz_msg[VLAN_SERVER_MSG_LENGTH] = '\0'; /* make sure the string ends */
-
- /* Initialize local socket */
- BuildInetAddr( &sa_client, NULL, 0 );
- p_server->i_socket = socket(AF_INET, SOCK_STREAM, 0);
- if( p_server->i_socket < 0 )
- {
- /* Error: return an error */
- intf_ErrMsg("input error: can not open socket (%s)\n", strerror(errno));
- return( errno );
- }
-
- /* Bind the server socket to client */
- if( bind( p_server->i_socket, (struct sockaddr *) &sa_client, sizeof(sa_client)) < 0)
- {
- /* Error: close socket and return an error */
- intf_ErrMsg("input error: can not bind socket (%s)\n", strerror(errno));
- close( p_server->i_socket );
- return( errno );
- }
-
- /* Try to connect to the VLANserver */
- if( connect( p_server->i_socket, (struct sockaddr *) &p_server->sa_in,
- sizeof(p_server->sa_in)) < 0)
- {
- /* Error: close socket and return an error */
- intf_ErrMsg("input error: unable to connect to the VLAN server (%s)\n",
- strerror(errno));
- close( p_server->i_socket );
- return( errno );
- }
-
- /* Send login message */
- snprintf(psz_msg, VLAN_SERVER_MSG_LENGTH, "%d %s %s %s\n",
- VLAN_LOGIN_REQUEST, VLAN_CLIENT_VERSION,
- p_server->psz_login, p_server->psz_passwd );
- if( send(p_server->i_socket, psz_msg, sizeof(char) * strlen( psz_msg ), 0) < 0)
- {
- intf_ErrMsg("input error: unable to login to the VLANserver: %s",
- strerror(errno));
- close( p_server->i_socket );
- return( errno );
- }
-
- /* Listen to response */
- i_bytes = recv(p_server->i_socket, psz_msg, VLAN_SERVER_MSG_LENGTH, 0);
- if( i_bytes < 0 )
- {
- intf_ErrMsg("input error: no response from VLANserver: %s\n",
- strerror(errno));
- ServerLogout( p_server );
- return( -1 );
- }
-
- /* Parse answer to login request */
- psz_msg[ i_bytes ] = '\0'; /* terminate string */
- if( atoi(psz_msg) == VLAN_LOGIN_REJECTED )
- {
- intf_ErrMsg("input error: login rejected by VLANserver: %s\n", psz_msg);
- ServerLogout( p_server );
- return( -1 );
- }
- else if( atoi(psz_msg) != VLAN_LOGIN_ANSWER )
- {
- intf_ErrMsg("input error: unexpected answer from VLAN server: %s\n", psz_msg);
- ServerLogout( p_server );
- return( -1 );
- }
-
- intf_DbgMsg("input debug: VLANserver login ok.\n");
- return 0;
+ int i_socket;
+ char * ipaddr;
+ struct ifreq interface;
+ struct sockaddr_in sa_server;
+ struct sockaddr_in sa_client;
+ char mess[80];
+
+
+ /*
+ *Looking for informations about the eth0 interface
+ */
+
+ interface.ifr_addr.sa_family = AF_INET;
+ strcpy( interface.ifr_name, main_GetPszVariable( INPUT_IFACE_VAR, INPUT_IFACE_DEFAULT ) );
+
+ i_socket = socket( AF_INET, SOCK_DGRAM, 0 );
+
+ /* Looking for the interface IP address */
+ ioctl( i_socket, SIOCGIFDSTADDR, &interface );
+ ipaddr = inet_ntoa((*(struct sockaddr_in *)(&(interface.ifr_addr))).sin_addr );
+
+ /* Looking for the interface MAC address */
+ ioctl( i_socket, SIOCGIFHWADDR, &interface );
+ close( i_socket );
+
+ /*
+ * Getting address, port, ... of the server
+ */
+
+ /* Initialize */
+ bzero( &sa_server, sizeof(struct sockaddr_in) );
+ /* sin_family is ALWAYS set to AF_INET (see in man 7 ip)*/
+ sa_server.sin_family = AF_INET;
+ /* Giving port on to connect after having convert it*/
+ sa_server.sin_port = htons ( main_GetIntVariable( INPUT_VLAN_PORT_VAR, INPUT_VLAN_PORT_DEFAULT ));
+ /* Giving address after having convert it into binary data*/
+ inet_aton( main_GetPszVariable( INPUT_VLAN_SERVER_VAR, INPUT_VLAN_SERVER_DEFAULT ), &(sa_server.sin_addr) );
+
+ /*
+ * Getting address, port, ... of the client
+ */
+
+ /* Initialize */
+ bzero( &sa_client, sizeof(struct sockaddr_in) );
+ /* sin_family is ALWAYS set to AF_INET (see in man 7 ip)*/
+ sa_client.sin_family = AF_INET;
+ /* Giving port on to connect after having convert it*/
+ sa_client.sin_port = htons( 0 );
+ /* Giving address after having convert it into binary data*/
+ inet_aton( ipaddr, &(sa_client.sin_addr) );
+
+ /* Initialization of the socket */
+ i_socket = socket(AF_INET, SOCK_DGRAM, 17 ); // ?? UDP
+ /* SOCK_DGRAM because here we use DATAGRAM
+ * Sachant qu'il y a un #define AF_INET = PF_INET dans sys/socket.h et que PF_INET est le IP protocol family ...
+ * Protocol is in #define, should be 17 for udp */
+
+ /* Elaborate the message to send */
+ sprintf( mess , "%d %s %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x \n",
+ Channel, ipaddr,
+ 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,
+ 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
+ );
+
+ /* Send the message */
+ intf_DbgMsg("%s\n", mess);
+ sendto(i_socket,mess,80,0,(struct sockaddr *)&sa_server,sizeof(struct sockaddr));
+
+ /*Close the socket */
+ close( i_socket );
+
+ return 0;
}
-
-/*******************************************************************************
- * ServerLogout: logout from a vlan server
- *******************************************************************************
- * Logout from a vlan server. This function sends the logout message to the
- * server and close the socket.
- *******************************************************************************/
-static void ServerLogout( input_vlan_server_t *p_server )
-{
- char psz_msg[VLAN_SERVER_MSG_LENGTH + 1]; /* server message */
-
- psz_msg[VLAN_SERVER_MSG_LENGTH] = '\0'; /* make sure the string ends */
-
- /* Send logout */
- snprintf(psz_msg, VLAN_SERVER_MSG_LENGTH, "%d\n", VLAN_LOGOUT);
- if( send(p_server->i_socket, psz_msg, sizeof(char) * strlen(psz_msg), 0) < 0)
- {
- intf_ErrMsg("input error: can't send logout message to VLANserver: %s\n",
- strerror(errno));
- }
-
- /* Close socket */
- if( close(p_server->i_socket) < 0)
- {
- intf_ErrMsg("input error: unable to close socket: %s\n", strerror(errno));
- }
-
- intf_DbgMsg("input debug: VLANserver logout ok\n");
-}
-
-/*******************************************************************************
- * ServerRequestChange: request vlan change from a server
- *******************************************************************************
- * Request vlan change from a vlan server. The client must be logged in. If the
- * change succeeded, the interface structure is updated. Note that only masters
- * should be sent to this function.
- *******************************************************************************/
-static int ServerRequestChange( input_vlan_server_t *p_server,
- input_vlan_iface_t *p_iface, int i_vlan )
-{
- char psz_msg[VLAN_SERVER_MSG_LENGTH + 1]; /* server message */
- int i_bytes; /* number of bytes read */
-
- psz_msg[VLAN_SERVER_MSG_LENGTH] = '\0'; /* make sure the string ends */
-
- /* Send request */
- snprintf(psz_msg, VLAN_SERVER_MSG_LENGTH, "%d %s %s %d %d",
- VLAN_CHANGE_REQUEST, p_iface->psz_mac,
- inet_ntoa(p_iface->sa_in.sin_addr), i_vlan, p_iface->i_vlan);
- if( send( p_server->i_socket, psz_msg, sizeof(char) * strlen(psz_msg), 0) < 0)
- {
- intf_ErrMsg("input error: unable to send request to VLANserver: %s\n",
- strerror(errno));
- return( -1 );
- }
-
- /* Listen to response */
- i_bytes = recv(p_server->i_socket, psz_msg, VLAN_SERVER_MSG_LENGTH, 0);
- if( i_bytes < 0 )
- {
- intf_ErrMsg("input error: no response from VLANserver: %s",
- strerror(errno));
- return( -1 );
- }
-
- /* Parse answer to vlan request */
- psz_msg[ i_bytes ] = '\0'; /* terminate string */
- if( atoi( psz_msg ) == VLAN_CHANGE_REJECTED )
- {
- intf_ErrMsg("input error: change request rejected by VLANserver: %s\n", psz_msg );
- return( -1 );
- }
- else if( atoi( psz_msg ) != VLAN_CHANGE_ANSWER )
- {
- intf_ErrMsg("input error: unexpected answer from VLAN server: %s\n", psz_msg);
- return( -1 );
- }
-
- /* ?? send packet for the switch to learn mac again */
-
- /* Update interface and return */
- intf_DbgMsg("input debug: interface %s moved to vlan %d\n",
- p_iface->psz_name, i_vlan );
- p_iface->i_vlan = i_vlan;
- return( 0 );
-}
-
-/*******************************************************************************
- * ServerRequestInfo: ask current vlan to server
- *******************************************************************************
- * Request current vlan from a vlan server. The client must be logged in. This
- * function updates the p_iface structure or returns non 0. Note that only
- * masters should be sent to this function.
- *******************************************************************************/
-static int ServerRequestInfo( input_vlan_server_t *p_server,
- input_vlan_iface_t *p_iface )
-{
- char psz_msg[VLAN_SERVER_MSG_LENGTH + 1]; /* server message */
- int i_bytes; /* number of bytes read */
- int i_switch; /* switch number */
- int i_port; /* port number */
- int i_vlan; /* vlan number */
- int i_sharers; /* number of mac addresses on this port */
-
- psz_msg[VLAN_SERVER_MSG_LENGTH] = '\0'; /* make sure the string ends */
-
- /* Send request */
- snprintf(psz_msg, VLAN_SERVER_MSG_LENGTH, "%d", VLAN_INFO_REQUEST);
- if( send( p_server->i_socket, psz_msg, sizeof(char) * strlen(psz_msg), 0) < 0)
- {
- intf_ErrMsg("input error: unable to send request to VLANserver: %s\n",
- strerror(errno));
- return( -1 );
- }
-
- /* Listen to response */
- i_bytes = recv(p_server->i_socket, psz_msg, VLAN_SERVER_MSG_LENGTH, 0);
- if( i_bytes < 0 )
- {
- intf_ErrMsg("input error: no response from VLANserver: %s",
- strerror(errno));
- return( -1 );
- }
-
- /* Parse answer to vlan request */
- psz_msg[ i_bytes ] = '\0'; /* terminate string */
- if( atoi( psz_msg ) == VLAN_INFO_REJECTED )
- {
- intf_ErrMsg("input error: info request rejected by VLANserver: %s\n", psz_msg );
- return( -1 );
- }
- else if( atoi( psz_msg ) != VLAN_INFO_ANSWER )
- {
- intf_ErrMsg("input error: unexpected answer from VLAN server: %s\n", psz_msg);
- return( -1 );
- }
- else if( sscanf(psz_msg, "%*d %d %d %d %d", &i_switch, &i_port, &i_vlan, &i_sharers) != 4 )
- {
- intf_ErrMsg("input error: invalid answer from VLAN server: %s\n", psz_msg);
- return( -1 );
- }
-
- /* Update interface and return */
- intf_DbgMsg("input debug: interface %s is on switch %d, port %d, vlan %d, %d sharers\n",
- p_iface->psz_name, i_switch, i_port, i_vlan, i_sharers);
- p_iface->i_switch = i_switch;
- p_iface->i_port = i_port;
- p_iface->i_vlan = i_vlan;
- p_iface->i_sharers = i_sharers;
- return( 0 );
-}
-
-
-
-
#include "intf_sys.h"
-/*******************************************************************************
- * Constants
- *******************************************************************************/
-
-/* INTF_INPUT_CFG: pre-configured inputs */
-#define INTF_MAX_INPUT_CFG 10
-static const input_cfg_t INTF_INPUT_CFG[] =
-{
- /* properties method
- * file host ip port vlan */
-
- /* Local input (unicast) */
- { INPUT_CFG_METHOD | INPUT_CFG_IP, INPUT_METHOD_TS_UCAST,
- NULL, NULL, "127.0.0.1", 0, 0 },
-
- /* Broadcasts */
- { INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
- NULL, NULL, NULL, 0, 0 },
- { INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
- NULL, NULL, NULL, 0, 1 },
- { INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
- NULL, NULL, NULL, 0, 2 },
- { INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
- NULL, NULL, NULL, 0, 3 },
- { INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
- NULL, NULL, NULL, 0, 4 },
- { INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
- NULL, NULL, NULL, 0, 5 },
- { INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
- NULL, NULL, NULL, 0, 6 },
- { INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
- NULL, NULL, NULL, 0, 7 },
- { INPUT_CFG_METHOD | INPUT_CFG_VLAN, INPUT_METHOD_TS_VLAN_BCAST,
- NULL, NULL, NULL, 0, 8 }
-};
-
/*******************************************************************************
* intf_Create: prepare interface before main loop
*******************************************************************************
}
if( (p_intf->p_input != NULL) && p_intf->p_input->b_error )
{
- input_DestroyThread( p_intf->p_input /*, NULL */ );
+ input_DestroyThread( p_intf->p_input, NULL );
p_intf->p_input = NULL;
intf_DbgMsg("Input thread destroyed\n");
}
*******************************************************************************/
int intf_SelectInput( intf_thread_t * p_intf, int i_index )
{
- intf_DbgMsg("0x%x\n", p_intf );
+ intf_DbgMsg("\n");
/* Kill existing input, if any */
if( p_intf->p_input != NULL )
{
- input_DestroyThread( p_intf->p_input /*??, NULL*/ );
+ input_DestroyThread( p_intf->p_input, NULL );
}
- /* Check that input index is valid */
- if( (i_index < 0) || (INTF_MAX_INPUT_CFG < i_index) )
- {
- p_intf->p_input = NULL;
- return( 1 );
- }
-
/* Open a new input */
- p_intf->p_input = input_CreateThread( &INTF_INPUT_CFG[ i_index ] /*??, NULL*/ );
+ intf_Msg("Switching to channel %d\n", i_index );
+ p_intf->p_input = input_CreateThread( INPUT_METHOD_TS_VLAN_BCAST, NULL, 0, i_index,
+ p_intf->p_vout, p_main->p_aout, NULL );
return( p_intf->p_input == NULL );
}
{
case 'Q': /* quit order */
case 'q':
- case 27:
+ case 27: /* escape key */
p_intf->b_die = 1;
break;
case '0': /* source change */
/******************************************************************************
* SpawnInput: spawn an input thread (ok ?)
******************************************************************************
- * Spawn an input thread with the correct p_cfg parameters.
+ * Spawn an input thread
******************************************************************************/
static int SpawnInput( int i_argc, intf_arg_t *p_argv )
{
- input_cfg_t cfg;
int i_arg;
-
- /* Erase p_cfg. */
- bzero( &cfg, sizeof( cfg ) );
+ int i_method = 0; /* method parameter */
+ char * psz_source = NULL; /* source parameter */
+ int i_port = 0; /* port parameter */
+ int i_vlan = 0; /* vlan parameter */
/* Parse parameters - see command list above */
for ( i_arg = 1; i_arg < i_argc; i_arg++ )
switch( p_argv[i_arg].i_index )
{
case 0: /* method */
- cfg.i_method = p_argv[i_arg].i_num;
- break;
- case 1: /* filename */
- cfg.psz_filename = p_argv[i_arg].psz_str;
- break;
- case 2: /* hostname */
- cfg.psz_hostname = p_argv[i_arg].psz_str;
+ i_method = p_argv[i_arg].i_num;
break;
- case 3: /* ip */
- cfg.psz_ip = p_argv[i_arg].psz_str;
+ case 1: /* filename, hostname, ip */
+ case 2:
+ case 3:
+ psz_source = p_argv[i_arg].psz_str;
break;
case 4: /* port */
- cfg.i_port = p_argv[i_arg].i_num;
+ i_port = p_argv[i_arg].i_num;
break;
case 5: /* VLAN */
- cfg.i_vlan = p_argv[i_arg].i_num;
+ i_vlan = p_argv[i_arg].i_num;
break;
}
}
- /* Setting i_properties to indicate which parameters are set. */
- if( cfg.i_method )
- {
- cfg.i_properties |= INPUT_CFG_METHOD;
- }
- if( cfg.psz_filename )
- {
- cfg.i_properties |= INPUT_CFG_FILENAME;
- }
- if( cfg.psz_hostname )
- {
- cfg.i_properties |= INPUT_CFG_HOSTNAME;
- }
- if( cfg.psz_ip )
- {
- cfg.i_properties |= INPUT_CFG_IP;
- }
- if( cfg.i_port )
- {
- cfg.i_properties |= INPUT_CFG_PORT;
- }
- if( cfg.i_vlan )
- {
- cfg.i_properties |= INPUT_CFG_VLAN;
- }
-
- /* Default settings for the decoder threads */
- cfg.p_aout = p_main->p_aout;
-
- /* Create the input thread */
+ /* Destroy current input, if any */
if( p_main->p_intf->p_input != NULL )
{
- input_DestroyThread( p_main->p_intf->p_input /*??, NULL*/ );
+ input_DestroyThread( p_main->p_intf->p_input, NULL );
}
- p_main->p_intf->p_input = input_CreateThread( &cfg /*??,NULL*/ );
+ p_main->p_intf->p_input = input_CreateThread( i_method, psz_source, i_port, i_vlan,
+ p_main->p_intf->p_vout, p_main->p_aout,
+ NULL );
return( INTF_NO_ERROR );
}
;
}
- /* Command is 'synchro' */
- if( !strcmp(p_argv[i_command].psz_str, "synchro") )
- {
- input_VlanSynchronize();
- }
- /* Command is 'request' */
- else if( !strcmp(p_argv[i_command].psz_str, "request") )
- {
- /* ?? */
- }
/* Command is 'join' */
- else if( !strcmp(p_argv[i_command].psz_str, "join") )
+ if( !strcmp(p_argv[i_command].psz_str, "join") )
{
/* ?? */
}
/* Vlan parameters */
intf_Msg("VLANs (Virtual Local Aera Networks) parameters:\n" \
- " vlan_server=<host>[:<port>] VLANs server address and port\n" \
+ " " INPUT_IFACE_VAR "=<interface> network interface\n" \
+ " " INPUT_VLAN_SERVER_VAR "=<hostname> vlan server\n" \
+ " " INPUT_VLAN_PORT_VAR "=<port> vlan server port\n" \
);
/* Interfaces keys */
int i_status; /* thread status */
/* Allocate descriptor */
+ intf_DbgMsg("\n");
p_vout = (vout_thread_t *) malloc( sizeof(vout_thread_t) );
if( p_vout == NULL )
{
return( NULL );
}
- intf_Msg("Video: display initialized (%dx%d, %d bpp)\n",
+ intf_Msg("Video display initialized (%dx%d, %d bpp)\n",
p_vout->i_width, p_vout->i_height, p_vout->i_screen_depth );
/* If status is NULL, wait until the thread is created */
int i_status; /* thread status */
/* Set status */
+ intf_DbgMsg("\n");
p_vout->pi_status = (pi_status != NULL) ? pi_status : &i_status;
*p_vout->pi_status = THREAD_DESTROY;
int i_index; /* generic index */
/* Update status */
+ intf_DbgMsg("\n");
*p_vout->pi_status = THREAD_START;
/* Initialize output method - this function issues its own error messages */
free( p_vout ); /* destroy descriptor */
return;
}
+ intf_DbgMsg("\n");
/*
* Main loop - it is not executed if an error occured during
static void ErrorThread( vout_thread_t *p_vout )
{
/* Wait until a `die' order */
+ intf_DbgMsg("\n");
while( !p_vout->b_die )
{
/* Sleep a while */
int i_picture;
/* Store status */
+ intf_DbgMsg("\n");
pi_status = p_vout->pi_status;
*pi_status = THREAD_END;
}
if( i_err ) /* an error occured */
{
- intf_Msg("Video: XShm extension desactivated\n" );
+ intf_Msg("XShm video sextension desactivated\n" );
p_vout->p_sys->b_shm = 0;
}
}
intf_ErrMsg("error: can't resize display\n");
return( 1 );
}
- intf_Msg("Video: display resized to %dx%d\n", p_vout->i_width, p_vout->i_height);
+ intf_Msg("Video display resized to %dx%d\n", p_vout->i_width, p_vout->i_height);
}
return 0;
p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
if( !p_vout->p_sys->b_shm )
{
- intf_Msg("Video: XShm extension is not available\n");
+ intf_Msg("XShm video extension is not available\n");
}
/* Get the screen depth */