1 /*****************************************************************************
2 * input_ext-intf.c: services to the interface
3 *****************************************************************************
4 * Copyright (C) 1998-2001 VideoLAN
5 * $Id: input_ext-intf.c,v 1.49 2003/05/04 22:42:17 gbazin Exp $
7 * Authors: Christophe Massiot <massiot@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 <string.h> /* memcpy(), memset() */
31 #include "stream_control.h"
32 #include "input_ext-dec.h"
33 #include "input_ext-intf.h"
34 #include "input_ext-plugins.h"
36 /*****************************************************************************
37 * input_SetStatus: change the reading status
38 *****************************************************************************/
39 void __input_SetStatus( vlc_object_t * p_this, int i_mode )
41 input_thread_t *p_input;
43 p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT );
47 msg_Err( p_this, "no input found" );
51 vlc_mutex_lock( &p_input->stream.stream_lock );
55 case INPUT_STATUS_END:
56 p_input->stream.i_new_status = PLAYING_S;
58 msg_Dbg( p_input, "end of stream" );
61 case INPUT_STATUS_PLAY:
62 p_input->stream.i_new_status = PLAYING_S;
63 msg_Dbg( p_input, "playing at normal rate" );
66 case INPUT_STATUS_PAUSE:
67 /* XXX: we don't need to check i_status, because input_clock.c
69 p_input->stream.i_new_status = PAUSE_S;
70 msg_Dbg( p_input, "toggling pause" );
73 case INPUT_STATUS_FASTER:
74 /* If we are already going too fast, go back to default rate */
75 if( p_input->stream.control.i_rate * 8 <= DEFAULT_RATE )
77 msg_Dbg( p_input, "can not play any faster" );
81 p_input->stream.i_new_status = FORWARD_S;
82 p_input->stream.i_new_rate =
83 p_input->stream.control.i_rate / 2;
85 if ( p_input->stream.i_new_rate < DEFAULT_RATE )
87 msg_Dbg( p_input, "playing at %i:1 fast forward",
88 DEFAULT_RATE / p_input->stream.i_new_rate );
90 else if ( p_input->stream.i_new_rate > DEFAULT_RATE )
92 msg_Dbg( p_input, "playing at 1:%i slow motion",
93 p_input->stream.i_new_rate / DEFAULT_RATE );
95 else if ( p_input->stream.i_new_rate == DEFAULT_RATE )
97 p_input->stream.i_new_status = PLAYING_S;
98 msg_Dbg( p_input, "playing at normal rate" );
103 case INPUT_STATUS_SLOWER:
104 /* If we are already going too slow, go back to default rate */
105 if( p_input->stream.control.i_rate >= 8 * DEFAULT_RATE )
107 msg_Dbg( p_input, "can not play any slower" );
111 p_input->stream.i_new_status = FORWARD_S;
112 p_input->stream.i_new_rate =
113 p_input->stream.control.i_rate * 2;
115 if ( p_input->stream.i_new_rate < DEFAULT_RATE )
117 msg_Dbg( p_input, "playing at %i:1 fast forward",
118 DEFAULT_RATE / p_input->stream.i_new_rate );
120 else if ( p_input->stream.i_new_rate > DEFAULT_RATE )
122 msg_Dbg( p_input, "playing at 1:%i slow motion",
123 p_input->stream.i_new_rate / DEFAULT_RATE );
125 else if ( p_input->stream.i_new_rate == DEFAULT_RATE )
127 p_input->stream.i_new_status = PLAYING_S;
128 msg_Dbg( p_input, "playing at normal rate" );
137 vlc_cond_signal( &p_input->stream.stream_wait );
138 vlc_mutex_unlock( &p_input->stream.stream_lock );
140 vlc_object_release( p_input );
143 /*****************************************************************************
144 * input_Seek: changes the stream postion
145 *****************************************************************************/
146 void __input_Seek( vlc_object_t * p_this, off_t i_position, int i_whence )
148 input_thread_t *p_input;
150 char psz_time1[OFFSETTOTIME_MAX_SIZE];
151 char psz_time2[OFFSETTOTIME_MAX_SIZE];
153 p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT );
155 if( p_input == NULL )
157 msg_Err( p_this, "no input found" );
161 vlc_mutex_lock( &p_input->stream.stream_lock );
163 #define A p_input->stream.p_selected_area
164 switch( i_whence & 0x30 )
166 case INPUT_SEEK_SECONDS:
167 i_position *= (off_t)50 * p_input->stream.i_mux_rate;
170 case INPUT_SEEK_PERCENT:
171 i_position = A->i_size * i_position / (off_t)100;
174 case INPUT_SEEK_BYTES:
179 switch( i_whence & 0x03 )
182 A->i_seek = A->i_tell + i_position;
186 A->i_seek = A->i_size + i_position;
191 A->i_seek = i_position;
199 else if( A->i_seek > A->i_size )
201 A->i_seek = A->i_size;
204 msg_Dbg( p_input, "seeking position "I64Fd"/"I64Fd" (%s/%s)",
205 A->i_seek, A->i_size,
206 input_OffsetToTime( p_input, psz_time1, i_position ),
207 input_OffsetToTime( p_input, psz_time2, A->i_size ) );
210 vlc_cond_signal( &p_input->stream.stream_wait );
211 vlc_mutex_unlock( &p_input->stream.stream_lock );
213 vlc_object_release( p_input );
216 /*****************************************************************************
217 * input_Tell: requests the stream postion
218 *****************************************************************************/
219 void __input_Tell( vlc_object_t * p_this, stream_position_t * p_position )
221 input_thread_t *p_input;
223 p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT );
225 if( p_input == NULL )
227 p_position->i_tell = 0;
228 p_position->i_size = 0;
229 p_position->i_mux_rate = 0;
230 msg_Err( p_this, "no input found" );
234 vlc_mutex_lock( &p_input->stream.stream_lock );
236 #define A p_input->stream.p_selected_area
237 p_position->i_tell = A->i_tell;
238 p_position->i_size = A->i_size;
239 p_position->i_mux_rate = p_input->stream.i_mux_rate;
242 vlc_mutex_unlock( &p_input->stream.stream_lock );
243 vlc_object_release( p_input );
246 /*****************************************************************************
247 * input_OffsetToTime : converts an off_t value to a time indicator, using
249 *****************************************************************************
250 * BEWARE : this function assumes that you already own the lock on
251 * p_input->stream.stream_lock
252 *****************************************************************************/
253 char * input_OffsetToTime( input_thread_t * p_input, char * psz_buffer,
258 if( p_input->stream.i_mux_rate )
260 i_seconds = i_offset / 50 / p_input->stream.i_mux_rate;
261 snprintf( psz_buffer, OFFSETTOTIME_MAX_SIZE, "%d:%02d:%02d",
262 (int) (i_seconds / (60 * 60)),
263 (int) (i_seconds / 60 % 60),
264 (int) (i_seconds % 60) );
265 return( psz_buffer );
269 /* Divide by zero is not my friend. */
270 sprintf( psz_buffer, "-:--:--" );
271 return( psz_buffer );
275 /*****************************************************************************
276 * input_DumpStream: dumps the contents of a stream descriptor
277 *****************************************************************************
278 * BEWARE : this function assumes that you already own the lock on
279 * p_input->stream.stream_lock
280 *****************************************************************************/
281 void input_DumpStream( input_thread_t * p_input )
283 char psz_time1[OFFSETTOTIME_MAX_SIZE];
284 char psz_time2[OFFSETTOTIME_MAX_SIZE];
287 #define S p_input->stream
288 msg_Dbg( p_input, "dumping stream ID 0x%x [OK:%ld/D:%ld]", S.i_stream_id,
289 S.c_packets_read, S.c_packets_trashed );
291 msg_Dbg( p_input, "seekable stream, position: "I64Fd"/"I64Fd" (%s/%s)",
292 S.p_selected_area->i_tell, S.p_selected_area->i_size,
293 input_OffsetToTime( p_input, psz_time1,
294 S.p_selected_area->i_tell ),
295 input_OffsetToTime( p_input, psz_time2,
296 S.p_selected_area->i_size ) );
298 msg_Dbg( p_input, "pace %scontrolled", S.b_pace_control ? "" : "un-" );
300 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
302 #define P p_input->stream.pp_programs[i]
303 msg_Dbg( p_input, "dumping program 0x%x, version %d (%s)",
304 P->i_number, P->i_version,
305 P->b_is_ok ? "complete" : "partial" );
307 for( j = 0; j < p_input->stream.pp_programs[i]->i_es_number; j++ )
309 #define ES p_input->stream.pp_programs[i]->pp_es[j]
310 msg_Dbg( p_input, "ES 0x%x, "
311 "stream 0x%x, fourcc `%4.4s', %s [OK:%ld/ERR:%ld]",
312 ES->i_id, ES->i_stream_id, (char*)&ES->i_fourcc,
313 ES->p_decoder_fifo != NULL ? "selected" : "not selected",
314 ES->c_packets, ES->c_invalid_packets );
320 /*****************************************************************************
321 * input_ToggleES: answers to a user request with calls to (Un)SelectES
322 *****************************************************************************
323 * Useful since the interface plugins know p_es.
324 * It only works for audio & spu ( to be sure nothing nasty is being done ).
325 * b_select is a boolean to know if we have to select or unselect ES
326 *****************************************************************************/
327 int input_ToggleES( input_thread_t * p_input, es_descriptor_t * p_es,
328 vlc_bool_t b_select )
330 vlc_mutex_lock( &p_input->stream.stream_lock );
336 p_input->stream.p_newly_selected_es = p_es;
340 p_input->stream.p_removed_es = p_es;
344 vlc_mutex_unlock( &p_input->stream.stream_lock );
349 /****************************************************************************
350 * input_ChangeArea: interface request an area change
351 ****************************************************************************/
352 int input_ChangeArea( input_thread_t * p_input, input_area_t * p_area )
354 vlc_mutex_lock( &p_input->stream.stream_lock );
356 p_input->stream.p_new_area = p_area;
358 vlc_mutex_unlock( &p_input->stream.stream_lock );
363 /****************************************************************************
364 * input_ChangeProgram: interface request a program change
365 ****************************************************************************/
366 int input_ChangeProgram( input_thread_t * p_input, uint16_t i_program_number )
368 pgrm_descriptor_t * p_program;
371 vlc_mutex_lock( &p_input->stream.stream_lock );
373 p_program = input_FindProgram( p_input, i_program_number );
375 if ( p_program == NULL )
377 msg_Err( p_input, "could not find selected program" );
381 p_input->stream.p_new_program = p_program;
383 vlc_mutex_unlock( &p_input->stream.stream_lock );
385 /* Update the navigation variables without triggering a callback */
386 val.i_int = i_program_number;
387 var_Change( p_input, "program", VLC_VAR_SETVALUE, &val, NULL );
392 /****************************************************************************
393 * input_ToggleGrayscale: change to grayscale or color output
394 ****************************************************************************/
395 int input_ToggleGrayscale( input_thread_t * p_input )
397 /* No need to warn the input thread since only the decoders and outputs
399 vlc_mutex_lock( &p_input->stream.control.control_lock );
400 p_input->stream.control.b_grayscale =
401 !p_input->stream.control.b_grayscale;
403 msg_Dbg( p_input, "changing to %s output",
404 p_input->stream.control.b_grayscale ? "grayscale" : "color" );
406 vlc_mutex_unlock( &p_input->stream.control.control_lock );
411 /****************************************************************************
412 * input_ToggleMute: activate/deactivate mute mode
413 ****************************************************************************/
414 int input_ToggleMute( input_thread_t * p_input )
416 /* We need to feed the decoders with 0, and only input can do that, so
417 * pass the message to the input thread. */
418 vlc_mutex_lock( &p_input->stream.stream_lock );
419 p_input->stream.b_new_mute = !p_input->stream.control.b_mute;
421 msg_Dbg( p_input, "%s mute mode",
422 p_input->stream.control.b_mute ? "activating" : "deactivating" );
424 vlc_mutex_unlock( &p_input->stream.stream_lock );