1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 1999-2004 VideoLAN
5 * $Id: stream.c,v 1.15 2004/02/02 13:00:53 fenrir Exp $
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 *****************************************************************************/
26 #include <vlc/input.h>
30 /****************************************************************************
32 ****************************************************************************/
34 * Read from the stream untill first newline.
35 * \param s Stream handle to read from
36 * \return A null-terminated string. This must be freed,
38 /* FIXME don't use stupid MAX_LINE -> do the same than net_ReadLine */
40 char *stream_ReadLine( stream_t *s )
46 i_data = stream_Peek( s, &p_data, MAX_LINE );
47 msg_Dbg( s, "i_data %d", i_data );
48 while( i < i_data && p_data[i] != '\n' )
58 p_line = malloc( i + 1 );
61 msg_Err( s, "out of memory" );
64 i = stream_Read( s, p_line, i + 1 );
65 p_line[ i - 1 ] = '\0';
66 msg_Dbg( s, "found %d chars long line", i );
73 /* TODO: one day we should create a special module stream
74 * when we would have a access wrapper, and stream filter
75 * (like caching, progessive, gunzip, ... )
78 /* private stream_sys_t for input_Stream* */
81 input_thread_t *p_input;
84 /* private pf_* functions declarations */
85 static int IStreamRead ( stream_t *, void *p_read, int i_read );
86 static int IStreamPeek ( stream_t *, uint8_t **pp_peek, int i_peek );
87 static int IStreamControl( stream_t *, int i_query, va_list );
89 /****************************************************************************
90 * input_StreamNew: create a wrapper for p_input access
91 ****************************************************************************/
92 stream_t *input_StreamNew( input_thread_t *p_input )
94 stream_t *s = vlc_object_create( p_input, sizeof( stream_t ) );
98 s->pf_read = IStreamRead;
99 s->pf_peek = IStreamPeek;
100 s->pf_control= IStreamControl;
102 s->p_sys = malloc( sizeof( stream_sys_t ) );
103 s->p_sys->p_input = p_input;
108 /****************************************************************************
109 * input_StreamDelete:
110 ****************************************************************************/
111 void input_StreamDelete( stream_t *s )
114 vlc_object_destroy( s );
118 /****************************************************************************
120 ****************************************************************************/
121 static int IStreamControl( stream_t *s, int i_query, va_list args )
123 input_thread_t *p_input = s->p_sys->p_input;
131 case STREAM_GET_SIZE:
132 p_i64 = (int64_t*) va_arg( args, int64_t * );
134 vlc_mutex_lock( &p_input->stream.stream_lock );
135 *p_i64 = p_input->stream.p_selected_area->i_size;
136 vlc_mutex_unlock( &p_input->stream.stream_lock );
139 case STREAM_CAN_SEEK:
140 p_b = (vlc_bool_t*) va_arg( args, vlc_bool_t * );
142 vlc_mutex_lock( &p_input->stream.stream_lock );
143 *p_b = p_input->stream.b_seekable;
144 vlc_mutex_unlock( &p_input->stream.stream_lock );
147 case STREAM_CAN_FASTSEEK:
148 p_b = (vlc_bool_t*) va_arg( args, vlc_bool_t * );
150 vlc_mutex_lock( &p_input->stream.stream_lock );
151 *p_b = p_input->stream.b_seekable &&
152 p_input->stream.i_method == INPUT_METHOD_FILE;
153 vlc_mutex_unlock( &p_input->stream.stream_lock );
156 case STREAM_GET_POSITION:
157 p_i64 = (int64_t*) va_arg( args, int64_t * );
159 vlc_mutex_lock( &p_input->stream.stream_lock );
160 *p_i64 = p_input->stream.p_selected_area->i_tell;
161 vlc_mutex_unlock( &p_input->stream.stream_lock );
164 case STREAM_SET_POSITION:
167 i64 = (int64_t) va_arg( args, int64_t );
169 vlc_mutex_lock( &p_input->stream.stream_lock );
171 ( p_input->stream.p_selected_area->i_size > 0 &&
172 p_input->stream.p_selected_area->i_size < i64 ) )
174 vlc_mutex_unlock( &p_input->stream.stream_lock );
175 msg_Warn( s, "seek out of bound" );
179 i_skip = i64 - p_input->stream.p_selected_area->i_tell;
183 vlc_mutex_unlock( &p_input->stream.stream_lock );
187 if( i_skip > 0 && i_skip < p_input->p_last_data -
188 p_input->p_current_data - 1 )
190 /* We can skip without reading/seeking */
191 p_input->p_current_data += i_skip;
192 p_input->stream.p_selected_area->i_tell = i64;
193 vlc_mutex_unlock( &p_input->stream.stream_lock );
196 vlc_mutex_unlock( &p_input->stream.stream_lock );
198 if( p_input->stream.b_seekable &&
199 ( p_input->stream.i_method == INPUT_METHOD_FILE ||
200 i_skip < 0 || i_skip >= ( p_input->i_mtu > 0 ?
201 p_input->i_mtu : 4096 ) ) )
203 input_AccessReinit( p_input );
204 p_input->pf_seek( p_input, i64 );
210 data_packet_t *p_data;
214 msg_Warn( s, "will skip "I64Fd" bytes, slow", i_skip );
221 i_read = input_SplitBuffer( p_input, &p_data,
222 __MIN( (int)p_input->i_bufsize, i_skip ) );
229 input_DeletePacket( p_input->p_method_data, p_data );
230 if( i_read == 0 && i_skip > 0 )
240 p_int = (int*) va_arg( args, int * );
241 *p_int = p_input->i_mtu;
245 msg_Err( s, "invalid stream_vaControl query=0x%x", i_query );
250 /****************************************************************************
252 ****************************************************************************/
253 static int IStreamRead( stream_t *s, void *p_data, int i_data )
255 input_thread_t *p_input = s->p_sys->p_input;
256 uint8_t *p = (uint8_t*)p_data;
257 data_packet_t *p_packet;
261 if( p_data == NULL && i_data > 0 )
265 stream_Control( s, STREAM_GET_POSITION, &i_pos );
268 if( stream_Control( s, STREAM_SET_POSITION, i_pos ) )
275 while( i_data > 0 && !p_input->b_die )
279 i_count = input_SplitBuffer( p_input, &p_packet,
280 __MIN( i_data, (int)p_input->i_bufsize ) );
285 input_DeletePacket( p_input->p_method_data, p_packet );
292 memcpy( p, p_packet->p_payload_start, i_count );
296 input_DeletePacket( p_input->p_method_data, p_packet );
304 /****************************************************************************
306 ****************************************************************************/
307 static int IStreamPeek( stream_t *s, uint8_t **pp_peek, int i_peek )
309 return input_Peek( s->p_sys->p_input, pp_peek, i_peek );