]> git.sesse.net Git - vlc/blob - src/control/media_instance.c
Libvlc: Make media_instance_destroy private.
[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     p_mi = malloc( sizeof(libvlc_media_instance_t) );
142     p_mi->p_md = libvlc_media_descriptor_new_from_input_item(
143                     p_libvlc_instance,
144                     p_input->p->input.p_item, p_e );
145
146     if( libvlc_exception_raised( p_e ) )
147     {
148         free( p_mi );
149         return NULL;
150     }
151
152     p_mi->p_libvlc_instance = p_libvlc_instance;
153     p_mi->i_input_id = p_input->i_object_id;
154
155     /* will be released in media_instance_release() */
156     vlc_object_yield( p_input );
157
158     return p_mi;
159 }
160
161 /**************************************************************************
162  * Destroy a Media Instance object (libvlc internal)
163  **************************************************************************/
164 void libvlc_media_instance_destroy( libvlc_media_instance_t *p_mi )
165 {
166     input_thread_t *p_input_thread;
167     libvlc_exception_t p_e;
168
169     /* XXX: locking */
170     libvlc_exception_init( &p_e );
171
172     if( !p_mi )
173         return;
174
175     p_input_thread = libvlc_get_input_thread( p_mi, &p_e );
176
177     if( libvlc_exception_raised( &p_e ) )
178         return; /* no need to worry about no input thread */
179     
180     input_DestroyThread( p_input_thread );
181
182     libvlc_media_descriptor_destroy( p_mi->p_md );
183
184     free( p_mi );
185 }
186
187 /**************************************************************************
188  * Release a Media Instance object
189  **************************************************************************/
190 void libvlc_media_instance_release( libvlc_media_instance_t *p_mi )
191 {
192     /* XXX: locking */
193
194     if( !p_mi )
195         return;
196
197     release_input_thread( p_mi );
198
199     libvlc_media_descriptor_destroy( p_mi->p_md );
200
201     free( p_mi );
202 }
203
204 /**************************************************************************
205  * Set the Media descriptor associated with the instance
206  **************************************************************************/
207 void libvlc_media_instance_set_media_descriptor(
208                             libvlc_media_instance_t *p_mi,
209                             libvlc_media_descriptor_t *p_md,
210                             libvlc_exception_t *p_e )
211 {
212     (void)p_e;
213
214     /* XXX : lock */
215
216     if( !p_mi )
217         return;
218
219     release_input_thread( p_mi );
220
221     libvlc_media_descriptor_destroy( p_mi->p_md );
222
223     if( !p_md )
224     {
225         p_mi->p_md = NULL;
226         return; /* It is ok to pass a NULL md */
227     }
228
229     p_mi->p_md = libvlc_media_descriptor_duplicate( p_md );
230     
231     /* The policy here is to ignore that we were created using a different
232      * libvlc_instance, because we don't really care */
233     p_mi->p_libvlc_instance = p_md->p_libvlc_instance;
234
235 }
236
237 /**************************************************************************
238  * Set the Media descriptor associated with the instance
239  **************************************************************************/
240 libvlc_media_descriptor_t *
241 libvlc_media_instance_get_media_descriptor(
242                             libvlc_media_instance_t *p_mi,
243                             libvlc_exception_t *p_e )
244 {
245     (void)p_e;
246
247     if( !p_mi->p_md )
248         return NULL;
249
250     return libvlc_media_descriptor_duplicate( p_mi->p_md );
251 }
252
253 /**************************************************************************
254  * Play
255  **************************************************************************/
256 void libvlc_media_instance_play( libvlc_media_instance_t *p_mi,
257                                  libvlc_exception_t *p_e )
258 {
259     input_thread_t * p_input_thread;
260
261     if( p_mi->i_input_id != -1) 
262     {
263         vlc_value_t val;
264         val.i_int = PLAYING_S;
265
266         /* A thread alread exists, send it a play message */
267         p_input_thread = libvlc_get_input_thread( p_mi, p_e );
268
269         if( libvlc_exception_raised( p_e ) )
270             return;
271
272         input_Control( p_input_thread, INPUT_CONTROL_SET_STATE, PLAYING_S );
273         vlc_object_release( p_input_thread );
274         return;
275     }
276
277     if( !p_mi->p_md )
278     {
279         libvlc_exception_raise( p_e, "no associated media descriptor" );
280         return;
281     }
282
283     p_input_thread = input_CreateThread( p_mi->p_libvlc_instance->p_libvlc_int,
284                                          p_mi->p_md->p_input_item );
285     p_mi->i_input_id = p_input_thread->i_object_id;
286
287     /* will be released in media_instance_release() */
288     vlc_object_yield( p_input_thread );
289 }
290
291 /**************************************************************************
292  * Pause
293  **************************************************************************/
294 void libvlc_media_instance_pause( libvlc_media_instance_t *p_mi,
295                                   libvlc_exception_t *p_e )
296 {
297     input_thread_t * p_input_thread;
298     vlc_value_t val;
299     val.i_int = PAUSE_S;
300
301     p_input_thread = libvlc_get_input_thread( p_mi, p_e );
302
303     if( libvlc_exception_raised( p_e ) )
304         return;
305
306     input_Control( p_input_thread, INPUT_CONTROL_SET_STATE, val );
307     vlc_object_release( p_input_thread );
308 }
309
310 /**************************************************************************
311  * Getters for stream information
312  **************************************************************************/
313 vlc_int64_t libvlc_media_instance_get_length(
314                              libvlc_media_instance_t *p_mi,
315                              libvlc_exception_t *p_e )
316 {
317     input_thread_t *p_input_thread;
318     vlc_value_t val;
319
320     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
321     if( !p_input_thread )
322         return -1;
323
324     var_Get( p_input_thread, "length", &val );
325     vlc_object_release( p_input_thread );
326
327     return (val.i_time+500LL)/1000LL;
328 }
329
330 vlc_int64_t libvlc_media_instance_get_time(
331                                    libvlc_media_instance_t *p_mi,
332                                    libvlc_exception_t *p_e )
333 {
334     input_thread_t *p_input_thread;
335     vlc_value_t val;
336
337     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
338     if( !p_input_thread )
339         return -1;
340
341     var_Get( p_input_thread , "time", &val );
342     vlc_object_release( p_input_thread );
343     return (val.i_time+500LL)/1000LL;
344 }
345
346 void libvlc_media_instance_set_time(
347                                  libvlc_media_instance_t *p_mi,
348                                  vlc_int64_t time,
349                                  libvlc_exception_t *p_e )
350 {
351     input_thread_t *p_input_thread;
352     vlc_value_t value;
353
354     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
355     if( !p_input_thread )
356         return;
357
358     value.i_time = time*1000LL;
359     var_Set( p_input_thread, "time", value );
360     vlc_object_release( p_input_thread );
361 }
362
363 void libvlc_media_instance_set_position(
364                                 libvlc_media_instance_t *p_mi,
365                                 float position,
366                                 libvlc_exception_t *p_e ) 
367 {
368     input_thread_t *p_input_thread;
369     vlc_value_t val;
370     val.f_float = position;
371
372     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
373     if( !p_input_thread )
374         return;
375
376     var_Set( p_input_thread, "position", val );
377     vlc_object_release( p_input_thread );
378 }
379
380 float libvlc_media_instance_get_position(
381                                  libvlc_media_instance_t *p_mi,
382                                  libvlc_exception_t *p_e )
383 {
384     input_thread_t *p_input_thread;
385     vlc_value_t val;
386
387     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
388     if( !p_input_thread )
389         return -1.0;
390
391     var_Get( p_input_thread, "position", &val );
392     vlc_object_release( p_input_thread );
393
394     return val.f_float;
395 }
396
397 float libvlc_media_instance_get_fps(
398                                  libvlc_media_instance_t *p_mi,
399                                  libvlc_exception_t *p_e) 
400 {
401     double f_fps = 0.0;
402     input_thread_t *p_input_thread;
403
404     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
405     if( !p_input_thread )
406         return 0.0;
407
408     if( (NULL == p_input_thread->p->input.p_demux)
409         || demux2_Control( p_input_thread->p->input.p_demux, DEMUX_GET_FPS, &f_fps )
410         || f_fps < 0.1 )
411     {
412         vlc_object_release( p_input_thread );
413         return 0.0;
414     }
415     else
416     {
417         vlc_object_release( p_input_thread );
418         return( f_fps );
419     }
420 }
421
422 vlc_bool_t libvlc_media_instance_will_play(
423                                  libvlc_media_instance_t *p_mi,
424                                  libvlc_exception_t *p_e) 
425 {
426     input_thread_t *p_input_thread =
427                             libvlc_get_input_thread ( p_mi, p_e);
428     if ( !p_input_thread )
429         return VLC_FALSE;
430
431     if ( !p_input_thread->b_die && !p_input_thread->b_dead ) 
432     {
433         vlc_object_release( p_input_thread );
434         return VLC_TRUE;
435     }
436     vlc_object_release( p_input_thread );
437     return VLC_FALSE;
438 }
439
440 void libvlc_media_instance_set_rate(
441                                  libvlc_media_instance_t *p_mi,
442                                  float rate,
443                                  libvlc_exception_t *p_e ) 
444 {
445     input_thread_t *p_input_thread;
446     vlc_value_t val;
447
448     if( rate <= 0 )
449         RAISEVOID( "Rate value is invalid" );
450
451     val.i_int = 1000.0f/rate;
452
453     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
454     if ( !p_input_thread )
455         return;
456
457     var_Set( p_input_thread, "rate", val );
458     vlc_object_release( p_input_thread );
459 }
460
461 float libvlc_media_instance_get_rate(
462                                  libvlc_media_instance_t *p_mi,
463                                  libvlc_exception_t *p_e )
464 {
465     input_thread_t *p_input_thread;
466     vlc_value_t val;
467
468     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
469     if ( !p_input_thread )
470         return -1.0;
471
472     var_Get( p_input_thread, "rate", &val );
473     vlc_object_release( p_input_thread );
474
475     return (float)1000.0f/val.i_int;
476 }
477
478 int libvlc_media_instance_get_state(
479                                  libvlc_media_instance_t *p_mi,
480                                  libvlc_exception_t *p_e )
481 {
482     input_thread_t *p_input_thread;
483     vlc_value_t val;
484
485     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
486     if ( !p_input_thread )
487         return 0;
488
489     var_Get( p_input_thread, "state", &val );
490     vlc_object_release( p_input_thread );
491
492     return val.i_int;
493 }
494