]> git.sesse.net Git - vlc/blob - src/control/media_instance.c
- libvlc APIs: bug fixing, and please note that exception argument is OPTIONAL (can...
[vlc] / src / control / media_instance.c
1 /*****************************************************************************
2  * media_instance.c: Libvlc API Media Instance management functions
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include "libvlc_internal.h"
25 #include <vlc/libvlc.h>
26 #include <vlc_demux.h>
27 #include <vlc_input.h>
28 #include "input/input_internal.h"
29
30 /*
31  * Release the associated input thread
32  */
33 static void release_input_thread( libvlc_media_instance_t *p_mi ) 
34 {
35     input_thread_t *p_input_thread;
36     vlc_bool_t should_destroy;
37     libvlc_exception_t p_e;
38
39     /* XXX: locking */
40     libvlc_exception_init( &p_e );
41
42     p_input_thread = libvlc_get_input_thread( p_mi, &p_e );
43
44     p_mi->i_input_id = -1;
45
46     if( libvlc_exception_raised( &p_e ) )
47         return;
48
49     /* release for previous libvlc_get_input_thread */
50     vlc_object_release( p_input_thread );
51
52     should_destroy = p_input_thread->i_refcount == 1;
53
54     /* release for initial p_input_thread yield (see _new()) */
55     vlc_object_release( p_input_thread );
56
57     /* No one is tracking this input_thread appart us. Destroy it */
58     if( should_destroy )
59         input_DestroyThread( p_input_thread );
60 }
61
62 /*
63  * Retrieve the input thread. Be sure to release the object
64  * once you are done with it. (libvlc Internal)
65  */
66 input_thread_t *libvlc_get_input_thread( libvlc_media_instance_t *p_mi,
67                                          libvlc_exception_t *p_e ) 
68 {
69     input_thread_t *p_input_thread;
70
71     if( !p_mi || p_mi->i_input_id == -1 )
72         RAISENULL( "Input is NULL" );
73
74     p_input_thread = (input_thread_t*)vlc_object_get(
75                                              p_mi->p_libvlc_instance->p_libvlc_int,
76                                              p_mi->i_input_id );
77     if( !p_input_thread )
78         RAISENULL( "Input does not exist" );
79
80     return p_input_thread;
81 }
82
83
84 /**************************************************************************
85  * Create a Media Instance object
86  **************************************************************************/
87 libvlc_media_instance_t *
88 libvlc_media_instance_new( libvlc_instance_t * p_libvlc_instance,
89                            libvlc_exception_t *p_e )
90 {
91     libvlc_media_instance_t * p_mi;
92
93     if( !p_libvlc_instance )
94     {
95         libvlc_exception_raise( p_e, "invalid libvlc instance" );
96         return NULL;
97     }
98
99     p_mi = malloc( sizeof(libvlc_media_instance_t) );
100     p_mi->p_md = NULL;
101     p_mi->p_libvlc_instance = p_libvlc_instance;
102     p_mi->i_input_id = -1;
103
104     return p_mi;
105 }
106
107 /**************************************************************************
108  * Create a Media Instance object with a media descriptor
109  **************************************************************************/
110 libvlc_media_instance_t *
111 libvlc_media_instance_new_from_media_descriptor(
112                                     libvlc_media_descriptor_t * p_md,
113                                     libvlc_exception_t *p_e )
114 {
115     libvlc_media_instance_t * p_mi;
116
117     if( !p_md )
118     {
119         libvlc_exception_raise( p_e, "invalid media descriptor" );
120         return NULL;
121     }
122
123     p_mi = malloc( sizeof(libvlc_media_instance_t) );
124     p_mi->p_md = libvlc_media_descriptor_duplicate( p_md );
125     p_mi->p_libvlc_instance = p_mi->p_md->p_libvlc_instance;
126     p_mi->i_input_id = -1;
127
128     return p_mi;
129 }
130
131 /**************************************************************************
132  * Create a new media instance object from an input_thread (Libvlc Internal)
133  **************************************************************************/
134 libvlc_media_instance_t * libvlc_media_instance_new_from_input_thread(
135                                    struct libvlc_instance_t *p_libvlc_instance,
136                                    input_thread_t *p_input,
137                                    libvlc_exception_t *p_e )
138 {
139     libvlc_media_instance_t * p_mi;
140
141     if( !p_input )
142     {
143         libvlc_exception_raise( p_e, "invalid input thread" );
144         return NULL;
145     }
146
147     p_mi = malloc( sizeof(libvlc_media_instance_t) );
148     p_mi->p_md = libvlc_media_descriptor_new_from_input_item(
149                     p_libvlc_instance,
150                     p_input->p->input.p_item, p_e );
151
152     if( !p_mi->p_md )
153     {
154         free( p_mi );
155         return NULL;
156     }
157
158     p_mi->p_libvlc_instance = p_libvlc_instance;
159     p_mi->i_input_id = p_input->i_object_id;
160
161     /* will be released in media_instance_release() */
162     vlc_object_yield( p_input );
163
164     return p_mi;
165 }
166
167 /**************************************************************************
168  * Destroy a Media Instance object (libvlc internal)
169  **************************************************************************/
170 void libvlc_media_instance_destroy( libvlc_media_instance_t *p_mi )
171 {
172     input_thread_t *p_input_thread;
173     libvlc_exception_t p_e;
174
175     /* XXX: locking */
176     libvlc_exception_init( &p_e );
177
178     if( !p_mi )
179         return;
180
181     p_input_thread = libvlc_get_input_thread( p_mi, &p_e );
182
183     if( libvlc_exception_raised( &p_e ) )
184         return; /* no need to worry about no input thread */
185     
186     input_DestroyThread( p_input_thread );
187
188     libvlc_media_descriptor_destroy( p_mi->p_md );
189
190     free( p_mi );
191 }
192
193 /**************************************************************************
194  * Release a Media Instance object
195  **************************************************************************/
196 void libvlc_media_instance_release( libvlc_media_instance_t *p_mi )
197 {
198     /* XXX: locking */
199
200     if( !p_mi )
201         return;
202
203     release_input_thread( p_mi );
204
205     libvlc_media_descriptor_destroy( p_mi->p_md );
206
207     free( p_mi );
208 }
209
210 /**************************************************************************
211  * Set the Media descriptor associated with the instance
212  **************************************************************************/
213 void libvlc_media_instance_set_media_descriptor(
214                             libvlc_media_instance_t *p_mi,
215                             libvlc_media_descriptor_t *p_md,
216                             libvlc_exception_t *p_e )
217 {
218     (void)p_e;
219
220     /* XXX : lock */
221
222     if( !p_mi )
223         return;
224
225     release_input_thread( p_mi );
226
227     libvlc_media_descriptor_destroy( p_mi->p_md );
228
229     if( !p_md )
230     {
231         p_mi->p_md = NULL;
232         return; /* It is ok to pass a NULL md */
233     }
234
235     p_mi->p_md = libvlc_media_descriptor_duplicate( p_md );
236     
237     /* The policy here is to ignore that we were created using a different
238      * libvlc_instance, because we don't really care */
239     p_mi->p_libvlc_instance = p_md->p_libvlc_instance;
240
241 }
242
243 /**************************************************************************
244  * Set the Media descriptor associated with the instance
245  **************************************************************************/
246 libvlc_media_descriptor_t *
247 libvlc_media_instance_get_media_descriptor(
248                             libvlc_media_instance_t *p_mi,
249                             libvlc_exception_t *p_e )
250 {
251     (void)p_e;
252
253     if( !p_mi->p_md )
254         return NULL;
255
256     return libvlc_media_descriptor_duplicate( p_mi->p_md );
257 }
258
259 /**************************************************************************
260  * Play
261  **************************************************************************/
262 void libvlc_media_instance_play( libvlc_media_instance_t *p_mi,
263                                  libvlc_exception_t *p_e )
264 {
265     input_thread_t * p_input_thread;
266
267     if( p_mi->i_input_id != -1) 
268     {
269         vlc_value_t val;
270         val.i_int = PLAYING_S;
271
272         /* A thread alread exists, send it a play message */
273         p_input_thread = libvlc_get_input_thread( p_mi, p_e );
274
275         if( !p_input_thread )
276             return;
277
278         input_Control( p_input_thread, INPUT_CONTROL_SET_STATE, PLAYING_S );
279         vlc_object_release( p_input_thread );
280         return;
281     }
282
283     if( !p_mi->p_md )
284     {
285         libvlc_exception_raise( p_e, "no associated media descriptor" );
286         return;
287     }
288
289     p_input_thread = input_CreateThread( p_mi->p_libvlc_instance->p_libvlc_int,
290                                          p_mi->p_md->p_input_item );
291     p_mi->i_input_id = p_input_thread->i_object_id;
292
293     /* will be released in media_instance_release() */
294     vlc_object_yield( p_input_thread );
295 }
296
297 /**************************************************************************
298  * Pause
299  **************************************************************************/
300 void libvlc_media_instance_pause( libvlc_media_instance_t *p_mi,
301                                   libvlc_exception_t *p_e )
302 {
303     input_thread_t * p_input_thread;
304     vlc_value_t val;
305     val.i_int = PAUSE_S;
306
307     p_input_thread = libvlc_get_input_thread( p_mi, p_e );
308
309     if( !p_input_thread )
310         return;
311
312     input_Control( p_input_thread, INPUT_CONTROL_SET_STATE, val );
313     vlc_object_release( p_input_thread );
314 }
315
316 /**************************************************************************
317  * Getters for stream information
318  **************************************************************************/
319 vlc_int64_t libvlc_media_instance_get_length(
320                              libvlc_media_instance_t *p_mi,
321                              libvlc_exception_t *p_e )
322 {
323     input_thread_t *p_input_thread;
324     vlc_value_t val;
325
326     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
327     if( !p_input_thread )
328         return -1;
329
330     var_Get( p_input_thread, "length", &val );
331     vlc_object_release( p_input_thread );
332
333     return (val.i_time+500LL)/1000LL;
334 }
335
336 vlc_int64_t libvlc_media_instance_get_time(
337                                    libvlc_media_instance_t *p_mi,
338                                    libvlc_exception_t *p_e )
339 {
340     input_thread_t *p_input_thread;
341     vlc_value_t val;
342
343     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
344     if( !p_input_thread )
345         return -1;
346
347     var_Get( p_input_thread , "time", &val );
348     vlc_object_release( p_input_thread );
349     return (val.i_time+500LL)/1000LL;
350 }
351
352 void libvlc_media_instance_set_time(
353                                  libvlc_media_instance_t *p_mi,
354                                  vlc_int64_t time,
355                                  libvlc_exception_t *p_e )
356 {
357     input_thread_t *p_input_thread;
358     vlc_value_t value;
359
360     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
361     if( !p_input_thread )
362         return;
363
364     value.i_time = time*1000LL;
365     var_Set( p_input_thread, "time", value );
366     vlc_object_release( p_input_thread );
367 }
368
369 void libvlc_media_instance_set_position(
370                                 libvlc_media_instance_t *p_mi,
371                                 float position,
372                                 libvlc_exception_t *p_e ) 
373 {
374     input_thread_t *p_input_thread;
375     vlc_value_t val;
376     val.f_float = position;
377
378     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
379     if( !p_input_thread )
380         return;
381
382     var_Set( p_input_thread, "position", val );
383     vlc_object_release( p_input_thread );
384 }
385
386 float libvlc_media_instance_get_position(
387                                  libvlc_media_instance_t *p_mi,
388                                  libvlc_exception_t *p_e )
389 {
390     input_thread_t *p_input_thread;
391     vlc_value_t val;
392
393     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
394     if( !p_input_thread )
395         return -1.0;
396
397     var_Get( p_input_thread, "position", &val );
398     vlc_object_release( p_input_thread );
399
400     return val.f_float;
401 }
402
403 float libvlc_media_instance_get_fps(
404                                  libvlc_media_instance_t *p_mi,
405                                  libvlc_exception_t *p_e) 
406 {
407     double f_fps = 0.0;
408     input_thread_t *p_input_thread;
409
410     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
411     if( !p_input_thread )
412         return 0.0;
413
414     if( (NULL == p_input_thread->p->input.p_demux)
415         || demux2_Control( p_input_thread->p->input.p_demux, DEMUX_GET_FPS, &f_fps )
416         || f_fps < 0.1 )
417     {
418         vlc_object_release( p_input_thread );
419         return 0.0;
420     }
421     else
422     {
423         vlc_object_release( p_input_thread );
424         return( f_fps );
425     }
426 }
427
428 vlc_bool_t libvlc_media_instance_will_play(
429                                  libvlc_media_instance_t *p_mi,
430                                  libvlc_exception_t *p_e) 
431 {
432     input_thread_t *p_input_thread =
433                             libvlc_get_input_thread ( p_mi, p_e);
434     if ( !p_input_thread )
435         return VLC_FALSE;
436
437     if ( !p_input_thread->b_die && !p_input_thread->b_dead ) 
438     {
439         vlc_object_release( p_input_thread );
440         return VLC_TRUE;
441     }
442     vlc_object_release( p_input_thread );
443     return VLC_FALSE;
444 }
445
446 void libvlc_media_instance_set_rate(
447                                  libvlc_media_instance_t *p_mi,
448                                  float rate,
449                                  libvlc_exception_t *p_e ) 
450 {
451     input_thread_t *p_input_thread;
452     vlc_value_t val;
453
454     if( rate <= 0 )
455         RAISEVOID( "Rate value is invalid" );
456
457     val.i_int = 1000.0f/rate;
458
459     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
460     if ( !p_input_thread )
461         return;
462
463     var_Set( p_input_thread, "rate", val );
464     vlc_object_release( p_input_thread );
465 }
466
467 float libvlc_media_instance_get_rate(
468                                  libvlc_media_instance_t *p_mi,
469                                  libvlc_exception_t *p_e )
470 {
471     input_thread_t *p_input_thread;
472     vlc_value_t val;
473
474     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
475     if ( !p_input_thread )
476         return -1.0;
477
478     var_Get( p_input_thread, "rate", &val );
479     vlc_object_release( p_input_thread );
480
481     return (float)1000.0f/val.i_int;
482 }
483
484 int libvlc_media_instance_get_state(
485                                  libvlc_media_instance_t *p_mi,
486                                  libvlc_exception_t *p_e )
487 {
488     input_thread_t *p_input_thread;
489     vlc_value_t val;
490
491     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
492     if ( !p_input_thread )
493         return 0;
494
495     var_Get( p_input_thread, "state", &val );
496     vlc_object_release( p_input_thread );
497
498     return val.i_int;
499 }
500