1 /*****************************************************************************
2 * intf_channels.c: channel handling functions
3 *****************************************************************************
4 * Copyright (C) 1998, 1999, 2000 VideoLAN
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
28 #include <errno.h> /* ENOMEM */
29 #include <stdlib.h> /* free(), strtol() */
30 #include <stdio.h> /* FILE */
31 #include <string.h> /* strerror() */
39 #include "intf_channels.h"
40 #include "interface.h"
44 /*****************************************************************************
46 *****************************************************************************/
47 static int ParseChannel( intf_channel_t *p_channel, char *psz_str );
49 /*****************************************************************************
50 * intf_LoadChannels: load channels description from a file
51 *****************************************************************************
52 * This structe describes all interface-specific data of the main (interface)
54 * Each line of the file is a semicolon separated list of the following
56 * integer channel number
57 * string channel description
58 * integer input method (see input.h)
61 * integer input vlan id
62 * The last field must end with a semicolon.
63 * Comments and empty lines are not explicitely allowed, but lines with parsing
64 * errors are ignored without warning.
65 *****************************************************************************/
66 int intf_LoadChannels( intf_thread_t *p_intf, char *psz_filename )
68 FILE * p_file; /* file */
69 intf_channel_t * p_channel; /* current channel */
70 char psz_line[INTF_MAX_CMD_SIZE]; /* line buffer */
71 int i_index; /* channel or field index */
73 /* Set default value */
74 p_intf->p_channel = NULL;
77 p_file = fopen( psz_filename, "r" );
80 intf_DbgMsg( "intf warning: cannot open %s (%s)",
81 psz_filename, strerror(errno) );
85 /* First pass: count number of lines */
86 for( i_index = 0; fgets( psz_line, INTF_MAX_CMD_SIZE, p_file ) != NULL;
94 /* Allocate array and rewind - some of the lines may be invalid, and the
95 * array will probably be larger than the actual number of channels, but
96 * it has no consequence. */
97 p_intf->p_channel = malloc( sizeof( intf_channel_t ) * i_index );
98 if( p_intf->p_channel == NULL )
100 intf_ErrMsg( "intf error: cannot create intf_channel_t (%s)",
105 p_channel = p_intf->p_channel;
108 /* Second pass: read channels descriptions */
109 while( fgets( psz_line, INTF_MAX_CMD_SIZE, p_file ) != NULL )
111 if( !ParseChannel( p_channel, psz_line ) )
113 intf_DbgMsg( "channel [%d] %s : method %d (%s:%d vlan id %d)",
114 p_channel->i_channel, p_channel->psz_description,
115 p_channel->i_input_method,
116 p_channel->psz_input_source,
117 p_channel->i_input_port, p_channel->i_input_vlan_id );
122 /* Add marker at the end of the array */
123 p_channel->i_channel = -1;
131 /*****************************************************************************
132 * intf_UnloadChannels: unload channels description
133 *****************************************************************************
134 * This function free all resources allocated by LoadChannels, if any.
135 *****************************************************************************/
136 void intf_UnloadChannels( intf_thread_t *p_intf )
138 int i_channel; /* channel index */
140 if( p_intf->p_channel != NULL )
142 /* Free allocated strings */
144 p_intf->p_channel[ i_channel ].i_channel != -1;
147 if( p_intf->p_channel[ i_channel ].psz_description != NULL )
149 free( p_intf->p_channel[ i_channel ].psz_description );
151 if( p_intf->p_channel[ i_channel ].psz_input_source != NULL )
153 free( p_intf->p_channel[ i_channel ].psz_input_source );
158 free( p_intf->p_channel );
159 p_intf->p_channel = NULL;
163 /*****************************************************************************
164 * intf_SelectChannel: change channel
165 *****************************************************************************
166 * Kill existing input, if any, and try to open a new one, using an input
167 * configuration table.
168 *****************************************************************************/
169 int intf_SelectChannel( intf_thread_t * p_intf, int i_channel )
173 intf_channel_t * p_channel; /* channel */
175 /* Look for channel in array */
176 if( p_intf->p_channel != NULL )
178 for( p_channel = p_intf->p_channel; p_channel->i_channel != -1; p_channel++ )
180 if( p_channel->i_channel == i_channel )
186 /* Kill existing input, if any */
187 if( p_intf->p_input != NULL )
189 input_DestroyThread( p_intf->p_input, NULL );
192 intf_Msg("Channel %d: %s", i_channel, p_channel->psz_description );
194 /* Open a new input */
195 p_intf->p_input = input_CreateThread( p_channel->i_input_method, p_channel->psz_input_source,
196 p_channel->i_input_port, p_channel->i_input_vlan_id,
197 p_intf->p_vout, p_main->p_aout, NULL );
198 return( p_intf->p_input == NULL );
203 /* Channel does not exist */
204 intf_Msg("Channel %d does not exist", i_channel );
209 /* Following functions are local */
211 /*****************************************************************************
212 * ParseChannel: parse a channel description line
213 *****************************************************************************
214 * See intf_LoadChannels. This function return non 0 on parsing error.
215 *****************************************************************************/
216 static int ParseChannel( intf_channel_t *p_channel, char *psz_str )
218 char * psz_index; /* current character */
219 char * psz_end; /* end pointer for strtol */
220 int i_field; /* field number, -1 on error */
221 int i_field_length; /* field length, for text fields */
223 /* Set some default fields */
224 p_channel->i_channel = 0;
225 p_channel->psz_description = NULL;
226 p_channel->i_input_method = 0;
227 p_channel->psz_input_source = NULL;
228 p_channel->i_input_port = 0;
229 p_channel->i_input_vlan_id = 0;
233 for( psz_index = psz_str; (i_field != -1) && (*psz_index != '\0'); psz_index++ )
235 if( *psz_index == ';' )
237 /* Mark end of field */
243 case 0: /* channel number */
244 p_channel->i_channel = strtol( psz_str, &psz_end, 0);
245 if( (*psz_str == '\0') || (*psz_end != '\0') )
250 case 1: /* channel description */
251 i_field_length = strlen( psz_str );
252 if( i_field_length != 0 )
254 p_channel->psz_description = malloc( i_field_length + 1 );
255 if( p_channel->psz_description == NULL )
257 intf_ErrMsg( "intf error: cannot create channel "
258 "description (%s)", strerror( ENOMEM ) );
263 strcpy( p_channel->psz_description, psz_str );
267 case 2: /* input method */
268 p_channel->i_input_method = strtol( psz_str, &psz_end, 0);
269 if( (*psz_str == '\0') || (*psz_end != '\0') )
274 case 3: /* input source */
275 i_field_length = strlen( psz_str );
276 if( i_field_length != 0 )
278 p_channel->psz_input_source = malloc( i_field_length + 1 );
279 if( p_channel->psz_input_source == NULL )
281 intf_ErrMsg( "intf error: cannot create input "
282 "source (%s)", strerror( ENOMEM ) );
287 strcpy( p_channel->psz_input_source, psz_str );
291 case 4: /* input port */
292 p_channel->i_input_port = strtol( psz_str, &psz_end, 0);
293 if( (*psz_str == '\0') || (*psz_end != '\0') )
298 case 5: /* input vlan id */
299 p_channel->i_input_vlan_id = strtol( psz_str, &psz_end, 0);
300 if( (*psz_str == '\0') || (*psz_end != '\0') )
305 /* ... following fields are ignored */
308 /* Set new beginning of field */
309 psz_str = psz_index + 1;
313 /* At least the first three fields must be parsed sucessfully for function
314 * success. Other parsing errors are returned using i_field = -1. */
317 /* Function fails. Free allocated strings */
318 if( p_channel->psz_description != NULL )
320 free( p_channel->psz_description );
322 if( p_channel->psz_input_source != NULL )
324 free( p_channel->psz_input_source );