]> git.sesse.net Git - vlc/blob - src/input/input_ext-intf.c
* added functions in inputs to change the current program (most of
[vlc] / src / input / input_ext-intf.c
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.30 2001/12/07 16:47:47 jobi Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *
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.
13  * 
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "defs.h"
28
29 #include <string.h>                                    /* memcpy(), memset() */
30 #include <sys/types.h>                                              /* off_t */
31
32 #include "config.h"
33 #include "common.h"
34 #include "intf_msg.h"
35 #include "threads.h"
36 #include "mtime.h"
37
38 #include "stream_control.h"
39 #include "input_ext-dec.h"
40 #include "input_ext-intf.h"
41 #include "input_ext-plugins.h"
42
43 /*****************************************************************************
44  * input_SetStatus: change the reading status
45  *****************************************************************************/
46 void input_SetStatus( input_thread_t * p_input, int i_mode )
47 {
48     vlc_mutex_lock( &p_input->stream.stream_lock );
49
50     switch( i_mode )
51     {
52     case INPUT_STATUS_END:
53         p_input->stream.i_new_status = PLAYING_S;
54         p_input->b_eof = 1;
55         intf_Msg( "input: end of stream" );
56         break;
57
58     case INPUT_STATUS_PLAY:
59         p_input->stream.i_new_status = PLAYING_S;
60         intf_Msg( "input: playing at normal rate" );
61         break;
62
63     case INPUT_STATUS_PAUSE:
64         /* XXX: we don't need to check i_status, because input_clock.c
65          * does it for us */
66         p_input->stream.i_new_status = PAUSE_S;
67         intf_Msg( "input: toggling pause" );
68         break;
69
70     case INPUT_STATUS_FASTER:
71         /* If we are already going too fast, go back to default rate */
72         if( p_input->stream.control.i_rate * 8 <= DEFAULT_RATE )
73         {
74             p_input->stream.i_new_status = PLAYING_S;
75             intf_Msg( "input: playing at normal rate" );
76         }
77         else
78         {
79             p_input->stream.i_new_status = FORWARD_S;
80
81             if( p_input->stream.control.i_rate < DEFAULT_RATE
82                     && p_input->stream.control.i_status == FORWARD_S )
83             {
84                 p_input->stream.i_new_rate =
85                                     p_input->stream.control.i_rate / 2;
86             }
87             else
88             {
89                 p_input->stream.i_new_rate = DEFAULT_RATE / 2;
90             }
91             intf_Msg( "input: playing at %i:1 fast forward",
92                       DEFAULT_RATE / p_input->stream.i_new_rate );
93         }
94         break;
95
96     case INPUT_STATUS_SLOWER:
97         /* If we are already going too slow, go back to default rate */
98         if( p_input->stream.control.i_rate >= 8 * DEFAULT_RATE )
99         {
100             p_input->stream.i_new_status = PLAYING_S;
101             intf_Msg( "input: playing at normal rate" );
102         }
103         else
104         {
105             p_input->stream.i_new_status = FORWARD_S;
106
107             if( p_input->stream.control.i_rate > DEFAULT_RATE
108                     && p_input->stream.control.i_status == FORWARD_S )
109             {
110                 p_input->stream.i_new_rate =
111                                     p_input->stream.control.i_rate * 2;
112             }
113             else
114             {
115                 p_input->stream.i_new_rate = DEFAULT_RATE * 2;
116             }
117             intf_Msg( "input: playing at 1:%i slow motion",
118                       p_input->stream.i_new_rate / DEFAULT_RATE );
119         }
120         break;
121
122     default:
123         break;
124     }
125
126     vlc_cond_signal( &p_input->stream.stream_wait );
127     vlc_mutex_unlock( &p_input->stream.stream_lock );
128 }
129
130 /*****************************************************************************
131  * input_Seek: changes the stream postion
132  *****************************************************************************/
133 void input_Seek( input_thread_t * p_input, off_t i_position )
134 {
135     char        psz_time1[OFFSETTOTIME_MAX_SIZE];
136     char        psz_time2[OFFSETTOTIME_MAX_SIZE];
137
138     vlc_mutex_lock( &p_input->stream.stream_lock );
139     p_input->stream.p_selected_area->i_seek = i_position;
140
141     intf_WarnMsg( 3, "input: seeking position %lld/%lld (%s/%s)", i_position,
142                   p_input->stream.p_selected_area->i_size,
143                   input_OffsetToTime( p_input, psz_time1, i_position ),
144                   input_OffsetToTime( p_input, psz_time2,
145                               p_input->stream.p_selected_area->i_size ) );
146
147     vlc_cond_signal( &p_input->stream.stream_wait );
148     vlc_mutex_unlock( &p_input->stream.stream_lock );
149 }
150
151 /*****************************************************************************
152  * input_OffsetToTime : converts an off_t value to a time indicator, using
153  *                      mux_rate
154  *****************************************************************************
155  * BEWARE : this function assumes that you already own the lock on
156  * p_input->stream.stream_lock
157  *****************************************************************************/
158 char * input_OffsetToTime( input_thread_t * p_input, char * psz_buffer,
159                            off_t i_offset )
160 {
161     mtime_t         i_seconds;
162
163     if( p_input->stream.i_mux_rate )
164     {
165         i_seconds = i_offset / 50 / p_input->stream.i_mux_rate;
166         snprintf( psz_buffer, OFFSETTOTIME_MAX_SIZE, "%d:%02d:%02d",
167                  (int) (i_seconds / (60 * 60)),
168                  (int) (i_seconds / 60 % 60),
169                  (int) (i_seconds % 60) );
170         return( psz_buffer );
171     }
172     else
173     {
174         /* Divide by zero is not my friend. */
175         sprintf( psz_buffer, "-:--:--" );
176         return( psz_buffer );
177     }
178 }
179
180 /*****************************************************************************
181  * input_DumpStream: dumps the contents of a stream descriptor
182  *****************************************************************************
183  * BEWARE : this function assumes that you already own the lock on
184  * p_input->stream.stream_lock
185  *****************************************************************************/
186 void input_DumpStream( input_thread_t * p_input )
187 {
188     int         i, j;
189     char        psz_time1[OFFSETTOTIME_MAX_SIZE];
190     char        psz_time2[OFFSETTOTIME_MAX_SIZE];
191
192 #define S   p_input->stream
193     intf_Msg( "input info: Dumping stream ID 0x%x [OK:%d/D:%d]", S.i_stream_id,
194               S.c_packets_read, S.c_packets_trashed );
195     if( S.b_seekable )
196         intf_Msg( "input info: seekable stream, position: %lld/%lld (%s/%s)",
197                   S.p_selected_area->i_tell, S.p_selected_area->i_size,
198                   input_OffsetToTime( p_input, psz_time1,
199                                       S.p_selected_area->i_tell ),
200                   input_OffsetToTime( p_input, psz_time2,
201                                       S.p_selected_area->i_size ) );
202     else
203         intf_Msg( "input info: %s", S.b_pace_control ? "pace controlled" :
204                   "pace un-controlled" );
205 #undef S
206     for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
207     {
208 #define P   p_input->stream.pp_programs[i]
209         intf_Msg( "input info: Dumping program 0x%x, version %d (%s)",
210                   P->i_number, P->i_version,
211                   P->b_is_ok ? "complete" : "partial" );
212 #undef P
213         for( j = 0; j < p_input->stream.pp_programs[i]->i_es_number; j++ )
214         {
215 #define ES  p_input->stream.pp_programs[i]->pp_es[j]
216             intf_Msg( "input info: ES 0x%x, stream 0x%x, type 0x%x, %s [OK:%d/ERR:%d]",
217                       ES->i_id, ES->i_stream_id, ES->i_type,
218                       ES->p_decoder_fifo != NULL ? "selected" : "not selected",
219                       ES->c_packets, ES->c_invalid_packets );
220 #undef ES
221         }
222     }
223 }
224
225 /*****************************************************************************
226  * input_ChangeES: answers to a user request with calls to (Un)SelectES
227  *****************************************************************************
228  * Useful since the interface plugins know p_es
229  * This functon is deprecated, use input_ToggleEs instead.
230  *****************************************************************************/
231 int input_ChangeES( input_thread_t * p_input, es_descriptor_t * p_es,
232                     u8 i_cat )
233 {
234     int                     i_index;
235     int                     i;
236
237     i_index = -1;
238
239     vlc_mutex_lock( &p_input->stream.stream_lock );
240
241     for( i = 0 ; i < p_input->stream.i_selected_es_number ; i++ )
242     {
243         if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
244         {
245             i_index = i;
246             break;
247         }
248     }
249
250
251     if( p_es != NULL )
252     {
253
254     
255         if( i_index != -1 )
256         {
257             
258             if( p_input->stream.pp_selected_es[i_index] != p_es )
259             {
260                 input_UnselectES( p_input,
261                                   p_input->stream.pp_selected_es[i_index] );
262                 input_SelectES( p_input, p_es );
263                 intf_WarnMsg( 3, "input info: es selected -> %s (0x%x)",
264                                                 p_es->psz_desc, p_es->i_id );
265             }
266         }
267         else
268         {
269             input_SelectES( p_input, p_es );
270             intf_WarnMsg( 3, "input info: es selected -> %s (0x%x)",
271                           p_es->psz_desc, p_es->i_id );
272         }
273     }
274     else
275     {
276         if( i_index != -1 )
277         {
278             intf_WarnMsg( 3, "input info: es unselected -> %s (0x%x)",
279                           p_input->stream.pp_selected_es[i_index]->psz_desc,
280                           p_input->stream.pp_selected_es[i_index]->i_id );
281
282             input_UnselectES( p_input,
283                               p_input->stream.pp_selected_es[i_index] );
284         }
285     }
286
287     vlc_mutex_unlock( &p_input->stream.stream_lock );
288
289     return 0;
290 }
291
292 /*****************************************************************************
293  * input_ToggleES: answers to a user request with calls to (Un)SelectES
294  *****************************************************************************
295  * Useful since the interface plugins know p_es.
296  * It only works for audio & spu ( to be sure nothing nasty is being done ).
297  * b_select is a boolean to know if we have to select or unselect ES
298  *****************************************************************************/
299 int input_ToggleES( input_thread_t * p_input, es_descriptor_t * p_es,
300                     boolean_t b_select )
301 {
302
303     vlc_mutex_lock( &p_input->stream.stream_lock );
304
305     if( p_es != NULL )
306     {
307         if( b_select )
308         {
309             p_input->stream.p_newly_selected_es = p_es;
310         }
311         else
312         {
313             p_input->stream.p_removed_es = p_es;
314         }
315     }
316
317     vlc_mutex_unlock( &p_input->stream.stream_lock );
318
319     return 0;
320 }
321
322 /****************************************************************************
323  * input_ChangeArea: interface request an area change
324  ****************************************************************************/
325 int input_ChangeArea( input_thread_t * p_input, input_area_t * p_area )
326 {
327     vlc_mutex_lock( &p_input->stream.stream_lock );
328
329     p_input->stream.p_new_area = p_area;
330
331     vlc_mutex_unlock( &p_input->stream.stream_lock );
332
333     return 0;
334 }
335
336 /****************************************************************************
337  * input_ChangeProgram: interface request an area change
338  ****************************************************************************/
339 int input_ChangeProgram( input_thread_t * p_input, 
340             pgrm_descriptor_t * p_program )
341 {
342     vlc_mutex_lock( &p_input->stream.stream_lock );
343
344     p_input->stream.p_new_program = p_program;
345
346     vlc_mutex_unlock( &p_input->stream.stream_lock );
347
348     return 0;
349 }
350
351 /****************************************************************************
352  * input_ToggleGrayscale: change to grayscale or color output
353  ****************************************************************************/
354 int input_ToggleGrayscale( input_thread_t * p_input )
355 {
356     /* No need to warn the input thread since only the decoders and outputs
357      * worry about it. */
358     vlc_mutex_lock( &p_input->stream.control.control_lock );
359     p_input->stream.control.b_grayscale =
360                     !p_input->stream.control.b_grayscale;
361
362     intf_WarnMsg( 3, "input warning: changing to %s output",
363             p_input->stream.control.b_grayscale ? "grayscale" : "color" );
364
365     vlc_mutex_unlock( &p_input->stream.control.control_lock );
366
367     return 0;
368 }
369
370 /****************************************************************************
371  * input_ToggleMute: activate/deactivate mute mode
372  ****************************************************************************/
373 int input_ToggleMute( input_thread_t * p_input )
374 {
375     /* We need to feed the decoders with 0, and only input can do that, so
376      * pass the message to the input thread. */
377     vlc_mutex_lock( &p_input->stream.stream_lock );
378     p_input->stream.b_new_mute = !p_input->stream.control.b_mute;
379
380     intf_WarnMsg( 3, "input warning: %s mute mode",
381             p_input->stream.control.b_mute ? "activating" : "deactivating" );
382
383     vlc_mutex_unlock( &p_input->stream.stream_lock );
384
385     return 0;
386 }
387
388 /****************************************************************************
389  * input_SetSMP: change the number of video decoder threads
390  ****************************************************************************/
391 int input_SetSMP( input_thread_t * p_input, int i_smp )
392 {
393     /* No need to warn the input thread since only the decoders
394      * worry about it. */
395     vlc_mutex_lock( &p_input->stream.control.control_lock );
396     p_input->stream.control.i_smp = i_smp;
397     vlc_mutex_unlock( &p_input->stream.control.control_lock );
398
399     return 0;
400 }
401