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;
143 libvlc_exception_raise( p_e, "invalid input thread" );
147 p_mi = malloc( sizeof(libvlc_media_instance_t) );
148 p_mi->p_md = libvlc_media_descriptor_new_from_input_item(
150 p_input->p->input.p_item, p_e );
158 p_mi->p_libvlc_instance = p_libvlc_instance;
159 p_mi->i_input_id = p_input->i_object_id;
161 /* will be released in media_instance_release() */
162 vlc_object_yield( p_input );
167 /**************************************************************************
168 * Destroy a Media Instance object (libvlc internal)
169 **************************************************************************/
170 void libvlc_media_instance_destroy( libvlc_media_instance_t *p_mi )
172 input_thread_t *p_input_thread;
173 libvlc_exception_t p_e;
176 libvlc_exception_init( &p_e );
181 p_input_thread = libvlc_get_input_thread( p_mi, &p_e );
183 if( libvlc_exception_raised( &p_e ) )
184 return; /* no need to worry about no input thread */
186 input_DestroyThread( p_input_thread );
188 libvlc_media_descriptor_destroy( p_mi->p_md );
193 /**************************************************************************
194 * Release a Media Instance object
195 **************************************************************************/
196 void libvlc_media_instance_release( libvlc_media_instance_t *p_mi )
203 release_input_thread( p_mi );
205 libvlc_media_descriptor_destroy( p_mi->p_md );
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 )
225 release_input_thread( p_mi );
227 libvlc_media_descriptor_destroy( p_mi->p_md );
232 return; /* It is ok to pass a NULL md */
235 p_mi->p_md = libvlc_media_descriptor_duplicate( p_md );
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;
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 )
256 return libvlc_media_descriptor_duplicate( p_mi->p_md );
259 /**************************************************************************
261 **************************************************************************/
262 void libvlc_media_instance_play( libvlc_media_instance_t *p_mi,
263 libvlc_exception_t *p_e )
265 input_thread_t * p_input_thread;
267 if( p_mi->i_input_id != -1)
270 val.i_int = PLAYING_S;
272 /* A thread alread exists, send it a play message */
273 p_input_thread = libvlc_get_input_thread( p_mi, p_e );
275 if( !p_input_thread )
278 input_Control( p_input_thread, INPUT_CONTROL_SET_STATE, PLAYING_S );
279 vlc_object_release( p_input_thread );
285 libvlc_exception_raise( p_e, "no associated media descriptor" );
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;
293 /* will be released in media_instance_release() */
294 vlc_object_yield( p_input_thread );
297 /**************************************************************************
299 **************************************************************************/
300 void libvlc_media_instance_pause( libvlc_media_instance_t *p_mi,
301 libvlc_exception_t *p_e )
303 input_thread_t * p_input_thread;
307 p_input_thread = libvlc_get_input_thread( p_mi, p_e );
309 if( !p_input_thread )
312 input_Control( p_input_thread, INPUT_CONTROL_SET_STATE, val );
313 vlc_object_release( p_input_thread );
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 )
323 input_thread_t *p_input_thread;
326 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
327 if( !p_input_thread )
330 var_Get( p_input_thread, "length", &val );
331 vlc_object_release( p_input_thread );
333 return (val.i_time+500LL)/1000LL;
336 vlc_int64_t libvlc_media_instance_get_time(
337 libvlc_media_instance_t *p_mi,
338 libvlc_exception_t *p_e )
340 input_thread_t *p_input_thread;
343 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
344 if( !p_input_thread )
347 var_Get( p_input_thread , "time", &val );
348 vlc_object_release( p_input_thread );
349 return (val.i_time+500LL)/1000LL;
352 void libvlc_media_instance_set_time(
353 libvlc_media_instance_t *p_mi,
355 libvlc_exception_t *p_e )
357 input_thread_t *p_input_thread;
360 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
361 if( !p_input_thread )
364 value.i_time = time*1000LL;
365 var_Set( p_input_thread, "time", value );
366 vlc_object_release( p_input_thread );
369 void libvlc_media_instance_set_position(
370 libvlc_media_instance_t *p_mi,
372 libvlc_exception_t *p_e )
374 input_thread_t *p_input_thread;
376 val.f_float = position;
378 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
379 if( !p_input_thread )
382 var_Set( p_input_thread, "position", val );
383 vlc_object_release( p_input_thread );
386 float libvlc_media_instance_get_position(
387 libvlc_media_instance_t *p_mi,
388 libvlc_exception_t *p_e )
390 input_thread_t *p_input_thread;
393 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
394 if( !p_input_thread )
397 var_Get( p_input_thread, "position", &val );
398 vlc_object_release( p_input_thread );
403 float libvlc_media_instance_get_fps(
404 libvlc_media_instance_t *p_mi,
405 libvlc_exception_t *p_e)
408 input_thread_t *p_input_thread;
410 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
411 if( !p_input_thread )
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 )
418 vlc_object_release( p_input_thread );
423 vlc_object_release( p_input_thread );
428 vlc_bool_t libvlc_media_instance_will_play(
429 libvlc_media_instance_t *p_mi,
430 libvlc_exception_t *p_e)
432 input_thread_t *p_input_thread =
433 libvlc_get_input_thread ( p_mi, p_e);
434 if ( !p_input_thread )
437 if ( !p_input_thread->b_die && !p_input_thread->b_dead )
439 vlc_object_release( p_input_thread );
442 vlc_object_release( p_input_thread );
446 void libvlc_media_instance_set_rate(
447 libvlc_media_instance_t *p_mi,
449 libvlc_exception_t *p_e )
451 input_thread_t *p_input_thread;
455 RAISEVOID( "Rate value is invalid" );
457 val.i_int = 1000.0f/rate;
459 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
460 if ( !p_input_thread )
463 var_Set( p_input_thread, "rate", val );
464 vlc_object_release( p_input_thread );
467 float libvlc_media_instance_get_rate(
468 libvlc_media_instance_t *p_mi,
469 libvlc_exception_t *p_e )
471 input_thread_t *p_input_thread;
474 p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
475 if ( !p_input_thread )
478 var_Get( p_input_thread, "rate", &val );
479 vlc_object_release( p_input_thread );
481 return (float)1000.0f/val.i_int;
484 int libvlc_media_instance_get_state(
485 libvlc_media_instance_t *p_mi,
486 libvlc_exception_t *p_e )
488 input_thread_t *p_input_thread;
491 p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
492 if ( !p_input_thread )
495 var_Get( p_input_thread, "state", &val );
496 vlc_object_release( p_input_thread );