1 /*****************************************************************************
2 * intf_channels.c: channel handling functions
3 *****************************************************************************
4 * Copyright (C) 1998, 1999, 2000 VideoLAN
5 * $Id: intf_channels.c,v 1.3 2001/04/28 03:36:25 sam Exp $
7 * Authors: Vincent Seguin <seguin@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
29 #include <errno.h> /* ENOMEM */
30 #include <stdlib.h> /* free(), strtol() */
31 #include <stdio.h> /* FILE */
32 #include <string.h> /* strerror() */
40 #include "intf_channels.h"
41 #include "interface.h"
45 /*****************************************************************************
47 *****************************************************************************/
48 static int ParseChannel( intf_channel_t *p_channel, char *psz_str );
50 /*****************************************************************************
51 * intf_LoadChannels: load channels description from a file
52 *****************************************************************************
53 * This structe describes all interface-specific data of the main (interface)
55 * Each line of the file is a semicolon separated list of the following
57 * integer channel number
58 * string channel description
59 * integer input method (see input.h)
62 * integer input vlan id
63 * The last field must end with a semicolon.
64 * Comments and empty lines are not explicitely allowed, but lines with parsing
65 * errors are ignored without warning.
66 *****************************************************************************/
67 int intf_LoadChannels( intf_thread_t *p_intf, char *psz_filename )
69 FILE * p_file; /* file */
70 intf_channel_t * p_channel; /* current channel */
71 char psz_line[INTF_MAX_CMD_SIZE]; /* line buffer */
72 int i_index; /* channel or field index */
74 /* Set default value */
75 p_intf->p_channel = NULL;
78 p_file = fopen( psz_filename, "r" );
81 intf_DbgMsg( "intf warning: cannot open %s (%s)",
82 psz_filename, strerror(errno) );
86 /* First pass: count number of lines */
87 for( i_index = 0; fgets( psz_line, INTF_MAX_CMD_SIZE, p_file ) != NULL;
95 /* Allocate array and rewind - some of the lines may be invalid,
96 * and the array will probably be larger than the actual number of
97 * channels, but it has no consequences. */
98 p_intf->p_channel = malloc( sizeof( intf_channel_t ) * i_index );
99 if( p_intf->p_channel == NULL )
101 intf_ErrMsg( "intf error: cannot create intf_channel_t (%s)",
106 p_channel = p_intf->p_channel;
109 /* Second pass: read channels descriptions */
110 while( fgets( psz_line, INTF_MAX_CMD_SIZE, p_file ) != NULL )
112 if( !ParseChannel( p_channel, psz_line ) )
114 intf_DbgMsg( "channel [%d] %s : method %d (%s:%d vlan id %d)",
115 p_channel->i_channel, p_channel->psz_description,
116 p_channel->i_input_method,
117 p_channel->psz_input_source,
118 p_channel->i_input_port, p_channel->i_input_vlan_id );
123 /* Add marker at the end of the array */
124 p_channel->i_channel = -1;
132 /*****************************************************************************
133 * intf_UnloadChannels: unload channels description
134 *****************************************************************************
135 * This function free all resources allocated by LoadChannels, if any.
136 *****************************************************************************/
137 void intf_UnloadChannels( intf_thread_t *p_intf )
139 int i_channel; /* channel index */
141 if( p_intf->p_channel != NULL )
143 /* Free allocated strings */
145 p_intf->p_channel[ i_channel ].i_channel != -1;
148 if( p_intf->p_channel[ i_channel ].psz_description != NULL )
150 free( p_intf->p_channel[ i_channel ].psz_description );
152 if( p_intf->p_channel[ i_channel ].psz_input_source != NULL )
154 free( p_intf->p_channel[ i_channel ].psz_input_source );
159 free( p_intf->p_channel );
160 p_intf->p_channel = NULL;
164 /*****************************************************************************
165 * intf_SelectChannel: change channel
166 *****************************************************************************
167 * Kill existing input, if any, and try to open a new one, using an input
168 * configuration table.
169 *****************************************************************************/
170 int intf_SelectChannel( intf_thread_t * p_intf, int i_channel )
174 intf_channel_t * p_channel; /* channel */
176 /* Look for channel in array */
177 if( p_intf->p_channel != NULL )
179 for( p_channel = p_intf->p_channel; p_channel->i_channel != -1; p_channel++ )
181 if( p_channel->i_channel == i_channel )
187 /* Kill existing input, if any */
188 if( p_intf->p_input != NULL )
190 input_DestroyThread( p_intf->p_input, NULL );
193 intf_Msg("Channel %d: %s", i_channel, p_channel->psz_description );
195 /* Open a new input */
196 p_intf->p_input = input_CreateThread( p_channel->i_input_method, p_channel->psz_input_source,
197 p_channel->i_input_port, p_channel->i_input_vlan_id,
198 p_intf->p_vout, p_main->p_aout, NULL );
199 return( p_intf->p_input == NULL );
204 /* Channel does not exist */
205 intf_Msg("Channel %d does not exist", i_channel );
210 /* Following functions are local */
212 /*****************************************************************************
213 * ParseChannel: parse a channel description line
214 *****************************************************************************
215 * See intf_LoadChannels. This function return non 0 on parsing error.
216 *****************************************************************************/
217 static int ParseChannel( intf_channel_t *p_channel, char *psz_str )
219 char * psz_index; /* current character */
220 char * psz_end; /* end pointer for strtol */
221 int i_field; /* field number, -1 on error */
222 int i_field_length; /* field length, for text fields */
224 /* Set some default fields */
225 p_channel->i_channel = 0;
226 p_channel->psz_description = NULL;
227 p_channel->i_input_method = 0;
228 p_channel->psz_input_source = NULL;
229 p_channel->i_input_port = 0;
230 p_channel->i_input_vlan_id = 0;
234 for( psz_index = psz_str; (i_field != -1) && (*psz_index != '\0'); psz_index++ )
236 if( *psz_index == ';' )
238 /* Mark end of field */
244 case 0: /* channel number */
245 p_channel->i_channel = strtol( psz_str, &psz_end, 0);
246 if( (*psz_str == '\0') || (*psz_end != '\0') )
251 case 1: /* channel description */
252 i_field_length = strlen( psz_str );
253 if( i_field_length != 0 )
255 p_channel->psz_description = malloc( i_field_length + 1 );
256 if( p_channel->psz_description == NULL )
258 intf_ErrMsg( "intf error: cannot create channel "
259 "description (%s)", strerror( ENOMEM ) );
264 strcpy( p_channel->psz_description, psz_str );
268 case 2: /* input method */
269 p_channel->i_input_method = strtol( psz_str, &psz_end, 0);
270 if( (*psz_str == '\0') || (*psz_end != '\0') )
275 case 3: /* input source */
276 i_field_length = strlen( psz_str );
277 if( i_field_length != 0 )
279 p_channel->psz_input_source = malloc( i_field_length + 1 );
280 if( p_channel->psz_input_source == NULL )
282 intf_ErrMsg( "intf error: cannot create input "
283 "source (%s)", strerror( ENOMEM ) );
288 strcpy( p_channel->psz_input_source, psz_str );
292 case 4: /* input port */
293 p_channel->i_input_port = strtol( psz_str, &psz_end, 0);
294 if( (*psz_str == '\0') || (*psz_end != '\0') )
299 case 5: /* input vlan id */
300 p_channel->i_input_vlan_id = strtol( psz_str, &psz_end, 0);
301 if( (*psz_str == '\0') || (*psz_end != '\0') )
306 /* ... following fields are ignored */
309 /* Set new beginning of field */
310 psz_str = psz_index + 1;
314 /* At least the first three fields must be parsed sucessfully for function
315 * success. Other parsing errors are returned using i_field = -1. */
318 /* Function fails. Free allocated strings */
319 if( p_channel->psz_description != NULL )
321 free( p_channel->psz_description );
323 if( p_channel->psz_input_source != NULL )
325 free( p_channel->psz_input_source );