1 /*****************************************************************************
2 * access2 adaptation layer.
3 *****************************************************************************
4 * Copyright (C) 2004 VideoLAN
5 * $Id: demux2.c 7783 2004-05-27 00:02:43Z hartman $
7 * Authors: Laurent Aimar <fenrir@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 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
30 #include <vlc/input.h>
32 /*****************************************************************************
34 *****************************************************************************/
35 static int Access2Open ( vlc_object_t * );
36 static void Access2Close( vlc_object_t * );
39 set_description( _("Access2 adaptation layer" ) );
40 set_capability( "access", 50 );
41 set_callbacks( Access2Open, Access2Close );
42 add_shortcut( "access2" );
43 add_shortcut( "http" );
44 add_shortcut( "ftp" );
45 add_shortcut( "tcp" );
46 add_shortcut( "pvr" );
48 add_shortcut( "file" );
49 add_shortcut( "stream" );
50 add_shortcut( "kfir" );
52 add_shortcut( "udp" );
53 add_shortcut( "udp4" );
54 add_shortcut( "udp6" );
56 add_shortcut( "rtp" );
57 add_shortcut( "rtp4" );
58 add_shortcut( "rtp6" );
61 /*****************************************************************************
63 *****************************************************************************/
64 static int Access2Read ( input_thread_t *, byte_t *, size_t );
65 static void Access2Seek ( input_thread_t *, off_t );
66 static int Access2SetArea( input_thread_t *, input_area_t * );
67 static int Access2Control( input_thread_t *, int, va_list );
75 input_title_t **title;
77 vlc_bool_t b_first_read;
81 /*****************************************************************************
82 * Access2Open: initializes structures
83 *****************************************************************************/
84 static int Access2Open( vlc_object_t * p_this )
86 input_thread_t *p_input = (input_thread_t *)p_this;
87 access2_sys_t *p_sys = malloc( sizeof( access2_sys_t ) );
95 psz_uri = malloc( strlen( p_input->psz_access ) + strlen( p_input->psz_demux ) + strlen( p_input->psz_name ) + 1 + 3 + 1 );
96 if( p_input->psz_demux && *p_input->psz_demux )
98 sprintf( psz_uri, "%s/%s://%s", p_input->psz_access, p_input->psz_demux, p_input->psz_name );
100 else if( p_input->psz_access && *p_input->psz_access )
102 sprintf( psz_uri, "%s://%s", p_input->psz_access, p_input->psz_name );
106 sprintf( psz_uri, "://%s", p_input->psz_name );
109 p_access = access2_New( p_input, psz_uri );
119 /* Init p_input->* */
120 p_input->pf_read = Access2Read;
121 p_input->pf_seek = Access2Seek;
122 p_input->pf_set_program = input_SetProgram;
123 p_input->pf_set_area = Access2SetArea;
124 p_input->pf_access_control = Access2Control;
125 p_input->p_access_data = (access_sys_t*)p_sys;
127 access2_Control( p_access, ACCESS_GET_MTU, &i_int );
128 p_input->i_mtu = i_int;
130 access2_Control( p_access, ACCESS_GET_PTS_DELAY, &i_64 );
131 p_input->i_pts_delay = i_64;
133 if( p_access->psz_demux && *p_access->psz_demux )
135 if( !p_input->psz_demux || *p_input->psz_demux == '\0' )
136 p_input->psz_demux = strdup( p_access->psz_demux );
139 if( access2_Control( p_access, ACCESS_GET_TITLE_INFO,
140 &p_sys->title, &p_sys->i_title ) )
146 /* Init p_input->stream.* */
147 vlc_mutex_lock( &p_input->stream.stream_lock );
148 if( p_sys->i_title > 0 )
150 /* FIXME handle the area 0 */
154 #define area p_input->stream.pp_areas
155 for( i = 0 ; i <= p_sys->i_title ; i++ )
157 input_title_t *t = p_sys->title[i];
159 input_AddArea( p_input, i+1,
160 t->i_seekpoint > 0 ? t->i_seekpoint : 1 );
162 /* Absolute start offset and size */
163 area[i]->i_start = i_start;
164 area[i]->i_size = t->i_size;
166 i_start += t->i_size;
171 Access2SetArea( p_input, p_input->stream.pp_areas[1] );
175 p_input->stream.p_selected_area->i_size = p_access->info.i_size;
177 access2_Control( p_access, ACCESS_CAN_SEEK, &b_bool );
178 p_input->stream.b_seekable = b_bool;
180 access2_Control( p_access, ACCESS_CAN_CONTROL_PACE, &b_bool );
181 p_input->stream.b_pace_control = b_bool;
183 access2_Control( p_access, ACCESS_CAN_SEEK, &b_bool );
185 p_input->stream.i_method = INPUT_METHOD_FILE; /* FIXME */
187 p_input->stream.i_method = INPUT_METHOD_NETWORK;/* FIXME */
188 p_input->stream.p_selected_area->i_tell = p_access->info.i_pos;
189 vlc_mutex_unlock( &p_input->stream.stream_lock );
192 p_sys->p_access = p_access;
193 p_sys->p_block = NULL;
194 p_sys->b_first_read = VLC_TRUE;
199 /*****************************************************************************
200 * Access2Close: frees unused data
201 *****************************************************************************/
202 static void Access2Close( vlc_object_t * p_this )
204 input_thread_t *p_input = (input_thread_t*)p_this;
205 access2_sys_t *p_sys = (access2_sys_t*)p_input->p_access_data;
208 access2_Delete( p_sys->p_access );
210 for( i = 0; i < p_sys->i_title; i++ )
212 vlc_input_title_Delete( p_sys->title[i] );
214 if( p_sys->title ) free( p_sys->title );
217 block_Release( p_sys->p_block );
222 /*****************************************************************************
223 * Access2Read: Read data
224 *****************************************************************************
225 * Returns -1 in case of error, 0 in case of EOF, size otherwise
226 *****************************************************************************/
227 static int Access2Read( input_thread_t *p_input, byte_t *p_buffer, size_t i_len )
229 access2_sys_t *p_sys = (access2_sys_t*)p_input->p_access_data;
230 access_t *p_access = p_sys->p_access;
233 /* TODO update i_size (ex: when read more than half current size and only every 100 times or ...) */
235 if( p_access->pf_read )
237 i_total = p_access->pf_read( p_access, (uint8_t*)p_buffer, (int)i_len );
241 /* Should never occur */
242 if( p_access->pf_block == NULL )
248 /* Emulate the read */
249 while( i_total < i_len )
252 if( p_sys->p_block == NULL )
254 p_sys->p_block = p_access->pf_block( p_access );
256 if( p_sys->p_block == NULL )
258 if( !p_access->info.b_eof && i_total <= 0 )
263 i_copy = __MIN( i_len - i_total, p_sys->p_block->i_buffer );
266 memcpy( &p_buffer[i_total], p_sys->p_block->p_buffer, i_copy );
268 p_sys->p_block->i_buffer -= i_copy;
269 p_sys->p_block->p_buffer += i_copy;
272 if( p_sys->p_block->i_buffer <= 0 )
274 block_Release( p_sys->p_block );
275 p_sys->p_block = NULL;
281 if( p_sys->b_first_read )
283 /* Some access update it only after first read (like udp) */
284 if( p_access->psz_demux && *p_access->psz_demux )
286 if( !p_input->psz_demux || *p_input->psz_demux == '\0' )
287 p_input->psz_demux = strdup( p_access->psz_demux );
289 p_sys->b_first_read = VLC_FALSE;
291 if( p_access->info.i_update & INPUT_UPDATE_SIZE )
293 vlc_mutex_lock( &p_input->stream.stream_lock );
294 p_input->stream.p_selected_area->i_size = p_access->info.i_size;
295 p_input->stream.b_changed = VLC_TRUE;
296 vlc_mutex_unlock( &p_input->stream.stream_lock );
298 p_access->info.i_update &= ~INPUT_UPDATE_SIZE;
301 if( p_access->info.i_update & INPUT_UPDATE_TITLE )
304 msg_Err( p_input, "INPUT_UPDATE_TITLE to do" );
306 if( p_access->info.i_update & INPUT_UPDATE_SEEKPOINT )
309 msg_Err( p_input, "INPUT_UPDATE_SEEKPOINT to do" );
315 /*****************************************************************************
316 * Access2SetArea: initialize input data for title x.
317 * It should be called for each user navigation request.
318 ****************************************************************************/
319 static int Access2SetArea( input_thread_t * p_input, input_area_t * p_area )
322 access_sys_t *p_sys = p_input->p_access_data;
324 /* we can't use the interface slider until initilization is complete */
325 p_input->stream.b_seekable = 0;
327 if( p_area != p_input->stream.p_selected_area )
329 /* Change the default area */
330 p_input->stream.p_selected_area = p_area;
332 /* Change the current track */
333 p_sys->i_track = p_area->i_id - 1;
334 p_sys->i_sector = p_sys->p_sectors[p_sys->i_track];
336 /* Update the navigation variables without triggering a callback */
337 val.i_int = p_area->i_id;
338 var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
341 p_sys->i_sector = p_sys->p_sectors[p_sys->i_track];
343 p_input->stream.p_selected_area->i_tell =
344 (off_t)p_sys->i_sector * (off_t)CDDA_DATA_SIZE
345 - p_input->stream.p_selected_area->i_start;
347 /* warn interface that something has changed */
348 p_input->stream.b_seekable = 1;
349 p_input->stream.b_changed = 1;
355 /*****************************************************************************
357 *****************************************************************************
358 * Returns VLC_EGENERIC/VLC_SUCCESS
359 *****************************************************************************/
360 static void Access2Seek( input_thread_t *p_input, off_t i_pos )
362 access2_sys_t *p_sys = (access2_sys_t*)p_input->p_access_data;
363 access_t *p_access = p_sys->p_access;
365 if( p_access->pf_seek != NULL && p_input->stream.b_seekable )
367 if( !p_access->pf_seek( p_access, i_pos ) )
371 block_Release( p_sys->p_block );
372 p_sys->p_block = NULL;
375 vlc_mutex_lock( &p_input->stream.stream_lock );
376 p_input->stream.p_selected_area->i_tell = p_access->info.i_pos;
377 vlc_mutex_unlock( &p_input->stream.stream_lock );
382 /*****************************************************************************
384 *****************************************************************************
385 * Returns VLC_EGENERIC/VLC_SUCCESS
386 *****************************************************************************/
387 static int Access2Control( input_thread_t *p_input, int i_query, va_list args )
389 access2_sys_t *p_sys = (access2_sys_t*)p_input->p_access_data;
390 access_t *p_access = p_sys->p_access;
392 return access2_vaControl( p_access, i_query, args );