]> git.sesse.net Git - vlc/blob - src/control/media_instance.c
Libvlc: Use exception for internal function.
[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  * Retrieve the input thread. Be sure to release the object
32  * once you are done with it. (libvlc Internal)
33  */
34 input_thread_t *libvlc_get_input_thread( libvlc_media_instance_t *p_mi,
35                                          libvlc_exception_t *p_e ) 
36 {
37     input_thread_t *p_input_thread;
38
39     if( !p_mi || p_mi->i_input_id == -1 )
40         RAISENULL( "Input is NULL" );
41
42     p_input_thread = (input_thread_t*)vlc_object_get(
43                                              p_mi->p_libvlc_instance->p_libvlc_int,
44                                              p_mi->i_input_id );
45     if( !p_input_thread )
46         RAISENULL( "Input does not exist" );
47
48     return p_input_thread;
49 }
50
51 /**************************************************************************
52  * Create a Media Instance object
53  **************************************************************************/
54 libvlc_media_instance_t *
55 libvlc_media_instance_new( libvlc_media_descriptor_t *p_md )
56 {
57     libvlc_media_instance_t * p_mi;
58
59     if( !p_md )
60         return NULL;
61
62     p_mi = malloc( sizeof(libvlc_media_instance_t) );
63     p_mi->p_md = libvlc_media_descriptor_duplicate( p_md );
64     p_mi->p_libvlc_instance = p_mi->p_md->p_libvlc_instance;
65     p_mi->i_input_id = -1;
66
67     return p_mi;
68 }
69
70 /**************************************************************************
71  * Create a new media instance object from an input_thread (Libvlc Internal)
72  **************************************************************************/
73 libvlc_media_instance_t * libvlc_media_instance_new_from_input_thread(
74                                    struct libvlc_instance_t *p_libvlc_instance,
75                                    input_thread_t *p_input,
76                                    libvlc_exception_t *p_e )
77 {
78     libvlc_media_instance_t * p_mi;
79
80     p_mi = malloc( sizeof(libvlc_media_instance_t) );
81     p_mi->p_md = libvlc_media_descriptor_new_from_input_item(
82                     p_libvlc_instance,
83                     p_input->p->input.p_item, p_e );
84
85     if( libvlc_exception_raised( p_e ) )
86     {
87         free( p_mi );
88         return NULL;
89     }
90
91     p_mi->p_libvlc_instance = p_libvlc_instance;
92     p_mi->i_input_id = p_input->i_object_id;
93
94     /* will be released in media_instance_release() */
95     vlc_object_yield( p_input );
96
97     return p_mi;
98 }
99
100 /**************************************************************************
101  * Destroy a Media Instance object
102  **************************************************************************/
103 void libvlc_media_instance_destroy( libvlc_media_instance_t *p_mi )
104 {
105     input_thread_t *p_input_thread;
106     libvlc_exception_t p_e;
107
108     /* XXX: locking */
109     libvlc_exception_init( &p_e );
110
111     if( !p_mi )
112         return;
113
114     p_input_thread = libvlc_get_input_thread( p_mi, &p_e );
115
116     if( libvlc_exception_raised( &p_e ) )
117         return; /* no need to worry about no input thread */
118     
119     input_DestroyThread( p_input_thread );
120
121     libvlc_media_descriptor_destroy( p_mi->p_md );
122
123     free( p_mi );
124 }
125
126 /**************************************************************************
127  * Release a Media Instance object
128  **************************************************************************/
129 void libvlc_media_instance_release( libvlc_media_instance_t *p_mi )
130 {
131     input_thread_t *p_input_thread;
132     libvlc_exception_t p_e;
133
134     /* XXX: locking */
135     libvlc_exception_init( &p_e );
136
137     if( !p_mi )
138         return;
139
140     p_input_thread = libvlc_get_input_thread( p_mi, &p_e );
141
142     if( !libvlc_exception_raised( &p_e ) )
143     {
144         /* release for previous libvlc_get_input_thread */
145         vlc_object_release( p_input_thread );
146
147         /* release for initial p_input_thread yield (see _new()) */
148         vlc_object_release( p_input_thread );
149
150         /* No one is tracking this input_thread appart us. Destroy it */
151         if( p_input_thread->i_refcount <= 0 )
152             input_DestroyThread( p_input_thread );
153         /* btw, we still have an XXX locking here */
154     }
155
156     libvlc_media_descriptor_destroy( p_mi->p_md );
157
158     free( p_mi );
159 }
160
161 /**************************************************************************
162  * Play
163  **************************************************************************/
164 void libvlc_media_instance_play( libvlc_media_instance_t *p_mi,
165                                  libvlc_exception_t *p_e )
166 {
167     input_thread_t * p_input_thread;
168
169     if( p_mi->i_input_id != -1) 
170     {
171         vlc_value_t val;
172         val.i_int = PLAYING_S;
173
174         /* A thread alread exists, send it a play message */
175         p_input_thread = libvlc_get_input_thread( p_mi, p_e );
176
177         if( libvlc_exception_raised( p_e ) )
178             return;
179
180         input_Control( p_input_thread, INPUT_CONTROL_SET_STATE, PLAYING_S );
181         vlc_object_release( p_input_thread );
182         return;
183     }
184
185     p_input_thread = input_CreateThread( p_mi->p_libvlc_instance->p_libvlc_int,
186                                          p_mi->p_md->p_input_item );
187     p_mi->i_input_id = p_input_thread->i_object_id;
188
189     /* will be released in media_instance_release() */
190     vlc_object_yield( p_input_thread );
191 }
192
193 /**************************************************************************
194  * Pause
195  **************************************************************************/
196 void libvlc_media_instance_pause( libvlc_media_instance_t *p_mi,
197                                   libvlc_exception_t *p_e )
198 {
199     input_thread_t * p_input_thread;
200     vlc_value_t val;
201     val.i_int = PAUSE_S;
202
203     p_input_thread = libvlc_get_input_thread( p_mi, p_e );
204
205     if( libvlc_exception_raised( p_e ) )
206         return;
207
208     input_Control( p_input_thread, INPUT_CONTROL_SET_STATE, val );
209     vlc_object_release( p_input_thread );
210 }
211
212 /**************************************************************************
213  * Getters for stream information
214  **************************************************************************/
215 vlc_int64_t libvlc_media_instance_get_length(
216                              libvlc_media_instance_t *p_mi,
217                              libvlc_exception_t *p_e )
218 {
219     input_thread_t *p_input_thread;
220     vlc_value_t val;
221
222     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
223     if( !p_input_thread )
224         return -1;
225
226     var_Get( p_input_thread, "length", &val );
227     vlc_object_release( p_input_thread );
228
229     return (val.i_time+500LL)/1000LL;
230 }
231
232 vlc_int64_t libvlc_media_instance_get_time(
233                                    libvlc_media_instance_t *p_mi,
234                                    libvlc_exception_t *p_e )
235 {
236     input_thread_t *p_input_thread;
237     vlc_value_t val;
238
239     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
240     if( !p_input_thread )
241         return -1;
242
243     var_Get( p_input_thread , "time", &val );
244     vlc_object_release( p_input_thread );
245     return (val.i_time+500LL)/1000LL;
246 }
247
248 void libvlc_media_instance_set_time(
249                                  libvlc_media_instance_t *p_mi,
250                                  vlc_int64_t time,
251                                  libvlc_exception_t *p_e )
252 {
253     input_thread_t *p_input_thread;
254     vlc_value_t value;
255
256     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
257     if( !p_input_thread )
258         return;
259
260     value.i_time = time*1000LL;
261     var_Set( p_input_thread, "time", value );
262     vlc_object_release( p_input_thread );
263 }
264
265 void libvlc_media_instance_set_position(
266                                 libvlc_media_instance_t *p_mi,
267                                 float position,
268                                 libvlc_exception_t *p_e ) 
269 {
270     input_thread_t *p_input_thread;
271     vlc_value_t val;
272     val.f_float = position;
273
274     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
275     if( !p_input_thread )
276         return;
277
278     var_Set( p_input_thread, "position", val );
279     vlc_object_release( p_input_thread );
280 }
281
282 float libvlc_media_instance_get_position(
283                                  libvlc_media_instance_t *p_mi,
284                                  libvlc_exception_t *p_e )
285 {
286     input_thread_t *p_input_thread;
287     vlc_value_t val;
288
289     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
290     if( !p_input_thread )
291         return -1.0;
292
293     var_Get( p_input_thread, "position", &val );
294     vlc_object_release( p_input_thread );
295
296     return val.f_float;
297 }
298
299 float libvlc_media_instance_get_fps(
300                                  libvlc_media_instance_t *p_mi,
301                                  libvlc_exception_t *p_e) 
302 {
303     double f_fps = 0.0;
304     input_thread_t *p_input_thread;
305
306     p_input_thread = libvlc_get_input_thread ( p_mi, p_e );
307     if( !p_input_thread )
308         return 0.0;
309
310     if( (NULL == p_input_thread->p->input.p_demux)
311         || demux2_Control( p_input_thread->p->input.p_demux, DEMUX_GET_FPS, &f_fps )
312         || f_fps < 0.1 )
313     {
314         vlc_object_release( p_input_thread );
315         return 0.0;
316     }
317     else
318     {
319         vlc_object_release( p_input_thread );
320         return( f_fps );
321     }
322 }
323
324 vlc_bool_t libvlc_media_instance_will_play(
325                                  libvlc_media_instance_t *p_mi,
326                                  libvlc_exception_t *p_e) 
327 {
328     input_thread_t *p_input_thread =
329                             libvlc_get_input_thread ( p_mi, p_e);
330     if ( !p_input_thread )
331         return VLC_FALSE;
332
333     if ( !p_input_thread->b_die && !p_input_thread->b_dead ) 
334     {
335         vlc_object_release( p_input_thread );
336         return VLC_TRUE;
337     }
338     vlc_object_release( p_input_thread );
339     return VLC_FALSE;
340 }
341
342 void libvlc_media_instance_set_rate(
343                                  libvlc_media_instance_t *p_mi,
344                                  float rate,
345                                  libvlc_exception_t *p_e ) 
346 {
347     input_thread_t *p_input_thread;
348     vlc_value_t val;
349
350     if( rate <= 0 )
351         RAISEVOID( "Rate value is invalid" );
352
353     val.i_int = 1000.0f/rate;
354
355     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
356     if ( !p_input_thread )
357         return;
358
359     var_Set( p_input_thread, "rate", val );
360     vlc_object_release( p_input_thread );
361 }
362
363 float libvlc_media_instance_get_rate(
364                                  libvlc_media_instance_t *p_mi,
365                                  libvlc_exception_t *p_e )
366 {
367     input_thread_t *p_input_thread;
368     vlc_value_t val;
369
370     p_input_thread = libvlc_get_input_thread ( p_mi, p_e);
371     if ( !p_input_thread )
372         return -1.0;
373
374     var_Get( p_input_thread, "rate", &val );
375     vlc_object_release( p_input_thread );
376
377     return (float)1000.0f/val.i_int;
378 }
379
380 int libvlc_media_instance_get_state(
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 0;
390
391     var_Get( p_input_thread, "state", &val );
392     vlc_object_release( p_input_thread );
393
394     return val.i_int;
395 }
396