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