1 /*****************************************************************************
2 * media_instance.c: Libvlc API Media Instance management functions
3 *****************************************************************************
4 * Copyright (C) 2005 the VideoLAN team
7 * Authors: Clément Stenac <zorglub@videolan.org>
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
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"
31 * Release the associated input thread
33 static void release_input_thread( libvlc_media_instance_t *p_mi )
35 input_thread_t *p_input_thread;
36 vlc_bool_t should_destroy;
37 libvlc_exception_t p_e;
40 libvlc_exception_init( &p_e );
42 p_input_thread = libvlc_get_input_thread( p_mi, &p_e );
44 p_mi->i_input_id = -1;
46 if( libvlc_exception_raised( &p_e ) )
49 /* release for previous libvlc_get_input_thread */
50 vlc_object_release( p_input_thread );
52 should_destroy = p_input_thread->i_refcount == 1;
54 /* release for initial p_input_thread yield (see _new()) */
55 vlc_object_release( p_input_thread );
57 /* No one is tracking this input_thread appart us. Destroy it */
59 input_DestroyThread( p_input_thread );
63 * Retrieve the input thread. Be sure to release the object
64 * once you are done with it. (libvlc Internal)
66 input_thread_t *libvlc_get_input_thread( libvlc_media_instance_t *p_mi,
67 libvlc_exception_t *p_e )
69 input_thread_t *p_input_thread;
71 if( !p_mi || p_mi->i_input_id == -1 )
72 RAISENULL( "Input is NULL" );
74 p_input_thread = (input_thread_t*)vlc_object_get(
75 p_mi->p_libvlc_instance->p_libvlc_int,
78 RAISENULL( "Input does not exist" );
80 return p_input_thread;
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 )
91 libvlc_media_instance_t * p_mi;
93 if( !p_libvlc_instance )
95 libvlc_exception_raise( p_e, "invalid libvlc instance" );
99 p_mi = malloc( sizeof(libvlc_media_instance_t) );
101 p_mi->p_libvlc_instance = p_libvlc_instance;
102 p_mi->i_input_id = -1;
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 )
115 libvlc_media_instance_t * p_mi;
119 libvlc_exception_raise( p_e, "invalid media descriptor" );
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;
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 )
139 libvlc_media_instance_t * p_mi;
141 p_mi = malloc( sizeof(libvlc_media_instance_t) );
142 p_mi->p_md = libvlc_media_descriptor_new_from_input_item(
144 p_input->p->input.p_item, p_e );
146 if( libvlc_exception_raised( p_e ) )
152 p_mi->p_libvlc_instance = p_libvlc_instance;
153 p_mi->i_input_id = p_input->i_object_id;
155 /* will be released in media_instance_release() */
156 vlc_object_yield( p_input );
161 /**************************************************************************
162 * Destroy a Media Instance object
163 **************************************************************************/
164 void libvlc_media_instance_destroy( libvlc_media_instance_t *p_mi )
166 input_thread_t *p_input_thread;
167 libvlc_exception_t p_e;
170 libvlc_exception_init( &p_e );
175 p_input_thread = libvlc_get_input_thread( p_mi, &p_e );
177 if( libvlc_exception_raised( &p_e ) )
178 return; /* no need to worry about no input thread */
180 input_DestroyThread( p_input_thread );
182 libvlc_media_descriptor_destroy( p_mi->p_md );
187 /**************************************************************************
188 * Release a Media Instance object
189 **************************************************************************/
190 void libvlc_media_instance_release( libvlc_media_instance_t *p_mi )
197 release_input_thread( p_mi );
199 libvlc_media_descriptor_destroy( p_mi->p_md );
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 )
219 release_input_thread( p_mi );
221 libvlc_media_descriptor_destroy( p_mi->p_md );
226 return; /* It is ok to pass a NULL md */
229 p_mi->p_md = libvlc_media_descriptor_duplicate( p_md );
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;
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 )
250 return libvlc_media_descriptor_duplicate( p_mi->p_md );
253 /**************************************************************************
255 **************************************************************************/
256 void libvlc_media_instance_play( libvlc_media_instance_t *p_mi,
257 libvlc_exception_t *p_e )
259 input_thread_t * p_input_thread;
261 if( p_mi->i_input_id != -1)
264 val.i_int = PLAYING_S;
266 /* A thread alread exists, send it a play message */
267 p_input_thread = libvlc_get_input_thread( p_mi, p_e );
269 if( libvlc_exception_raised( p_e ) )
272 input_Control( p_input_thread, INPUT_CONTROL_SET_STATE, PLAYING_S );
273 vlc_object_release( p_input_thread );
279 libvlc_exception_raise( p_e, "no associated media descriptor" );
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;
287 /* will be released in media_instance_release() */
288 vlc_object_yield( p_input_thread );
291 /**************************************************************************
293 **************************************************************************/
294 void libvlc_media_instance_pause( libvlc_media_instance_t *p_mi,
295 libvlc_exception_t *p_e )
297 input_thread_t * p_input_thread;
301 p_input_thread = libvlc_get_input_thread( p_mi, p_e );
303 if( libvlc_exception_raised( p_e ) )
306 input_Control( p_input_thread, INPUT_CONTROL_SET_STATE, val );
307 vlc_object_release( p_input_thread );
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 )
317 input_thread_t *p_input_thread;
320 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
321 if( !p_input_thread )
324 var_Get( p_input_thread, "length", &val );
325 vlc_object_release( p_input_thread );
327 return (val.i_time+500LL)/1000LL;
330 vlc_int64_t libvlc_media_instance_get_time(
331 libvlc_media_instance_t *p_mi,
332 libvlc_exception_t *p_e )
334 input_thread_t *p_input_thread;
337 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
338 if( !p_input_thread )
341 var_Get( p_input_thread , "time", &val );
342 vlc_object_release( p_input_thread );
343 return (val.i_time+500LL)/1000LL;
346 void libvlc_media_instance_set_time(
347 libvlc_media_instance_t *p_mi,
349 libvlc_exception_t *p_e )
351 input_thread_t *p_input_thread;
354 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
355 if( !p_input_thread )
358 value.i_time = time*1000LL;
359 var_Set( p_input_thread, "time", value );
360 vlc_object_release( p_input_thread );
363 void libvlc_media_instance_set_position(
364 libvlc_media_instance_t *p_mi,
366 libvlc_exception_t *p_e )
368 input_thread_t *p_input_thread;
370 val.f_float = position;
372 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
373 if( !p_input_thread )
376 var_Set( p_input_thread, "position", val );
377 vlc_object_release( p_input_thread );
380 float libvlc_media_instance_get_position(
381 libvlc_media_instance_t *p_mi,
382 libvlc_exception_t *p_e )
384 input_thread_t *p_input_thread;
387 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
388 if( !p_input_thread )
391 var_Get( p_input_thread, "position", &val );
392 vlc_object_release( p_input_thread );
397 float libvlc_media_instance_get_fps(
398 libvlc_media_instance_t *p_mi,
399 libvlc_exception_t *p_e)
402 input_thread_t *p_input_thread;
404 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
405 if( !p_input_thread )
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 )
412 vlc_object_release( p_input_thread );
417 vlc_object_release( p_input_thread );
422 vlc_bool_t libvlc_media_instance_will_play(
423 libvlc_media_instance_t *p_mi,
424 libvlc_exception_t *p_e)
426 input_thread_t *p_input_thread =
427 libvlc_get_input_thread ( p_mi, p_e);
428 if ( !p_input_thread )
431 if ( !p_input_thread->b_die && !p_input_thread->b_dead )
433 vlc_object_release( p_input_thread );
436 vlc_object_release( p_input_thread );
440 void libvlc_media_instance_set_rate(
441 libvlc_media_instance_t *p_mi,
443 libvlc_exception_t *p_e )
445 input_thread_t *p_input_thread;
449 RAISEVOID( "Rate value is invalid" );
451 val.i_int = 1000.0f/rate;
453 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
454 if ( !p_input_thread )
457 var_Set( p_input_thread, "rate", val );
458 vlc_object_release( p_input_thread );
461 float libvlc_media_instance_get_rate(
462 libvlc_media_instance_t *p_mi,
463 libvlc_exception_t *p_e )
465 input_thread_t *p_input_thread;
468 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
469 if ( !p_input_thread )
472 var_Get( p_input_thread, "rate", &val );
473 vlc_object_release( p_input_thread );
475 return (float)1000.0f/val.i_int;
478 int libvlc_media_instance_get_state(
479 libvlc_media_instance_t *p_mi,
480 libvlc_exception_t *p_e )
482 input_thread_t *p_input_thread;
485 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
486 if ( !p_input_thread )
489 var_Get( p_input_thread, "state", &val );
490 vlc_object_release( p_input_thread );