]> git.sesse.net Git - vlc/blob - src/control/mediacontrol_core.c
Rename vlc_input_item_* functions to input_Item* for consistency
[vlc] / src / control / mediacontrol_core.c
1 /*****************************************************************************
2  * core.c: Core functions : init, playlist, stream management
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Olivier Aubert <olivier.aubert@liris.univ-lyon1.fr>
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 <mediacontrol_internal.h>
25 #include <vlc/mediacontrol.h>
26
27 #include <vlc/libvlc.h>
28 #include <vlc/intf.h>
29 #include <vlc/vout.h>
30 #include <vlc/aout.h>
31 #include <vlc_demux.h>
32
33 #include <vlc_osd.h>
34
35 #define HAS_SNAPSHOT 1
36
37 #ifdef HAS_SNAPSHOT
38 #include <snapshot.h>
39 #endif
40
41 #include <stdlib.h>                                      /* malloc(), free() */
42 #include <string.h>
43
44 #include <errno.h>                                                 /* ENOMEM */
45 #include <stdio.h>
46 #include <ctype.h>
47
48 #ifdef HAVE_UNISTD_H
49 #    include <unistd.h>
50 #endif
51 #ifdef HAVE_SYS_TIME_H
52 #    include <sys/time.h>
53 #endif
54 #ifdef HAVE_SYS_TYPES_H
55 #    include <sys/types.h>
56 #endif
57
58 mediacontrol_Instance* mediacontrol_new( char** args, mediacontrol_Exception *exception )
59 {
60     mediacontrol_Instance* retval;
61     libvlc_exception_t ex;
62     char **ppsz_argv;
63     int i_count = 0;
64     int i_index;
65     char **p_tmp;
66
67     libvlc_exception_init( &ex );
68     exception=mediacontrol_exception_init( exception );
69
70     /* Copy args array */
71     if( args )
72     {
73         for ( p_tmp = args ; *p_tmp != NULL ; p_tmp++ )
74             i_count++;
75     }
76
77     ppsz_argv = malloc( ( i_count + 2 ) * sizeof( char * ) ) ;
78     if( ! ppsz_argv )
79     {
80         RAISE_NULL( mediacontrol_InternalException, "out of memory" );
81     }
82     ppsz_argv[0] = "vlc";
83     for ( i_index = 0; i_index < i_count; i_index++ )
84     {
85         ppsz_argv[i_index + 1] = strdup( args[i_index] );
86         if( ! ppsz_argv[i_index + 1] )
87         {
88             RAISE_NULL( mediacontrol_InternalException, "out of memory" );
89         }
90     }
91
92     ppsz_argv[i_count + 2] = NULL;
93
94     retval = ( mediacontrol_Instance* )malloc( sizeof( mediacontrol_Instance ) );
95     if( ! retval )
96     { 
97         RAISE_NULL( mediacontrol_InternalException, "out of memory" );
98     }
99
100     retval->p_instance = libvlc_new( i_count + 1, ppsz_argv, &ex );
101     retval->p_playlist = retval->p_instance->p_libvlc_int->p_playlist;
102     HANDLE_LIBVLC_EXCEPTION_NULL( &ex );
103     return retval;  
104 };
105
106 void
107 mediacontrol_exit( mediacontrol_Instance *self )
108 {
109     libvlc_exception_t ex;
110     libvlc_exception_init( &ex );
111
112     libvlc_destroy( self->p_instance, &ex );
113 }
114
115 libvlc_instance_t*
116 mediacontrol_get_libvlc_instance( mediacontrol_Instance *self )
117 {
118   return self->p_instance;
119 }
120
121 mediacontrol_Instance *
122 mediacontrol_new_from_instance( libvlc_instance_t* p_instance,
123                                 mediacontrol_Exception *exception )
124 {
125   mediacontrol_Instance* retval;
126
127   retval = ( mediacontrol_Instance* )malloc( sizeof( mediacontrol_Instance ) );
128   if( ! retval )
129   { 
130       RAISE_NULL( mediacontrol_InternalException, "out of memory" );
131   }
132   retval->p_instance = p_instance;
133   retval->p_playlist = retval->p_instance->p_libvlc_int->p_playlist;
134   return retval;  
135 }
136
137 /**************************************************************************
138  * Playback management
139  **************************************************************************/
140 mediacontrol_Position*
141 mediacontrol_get_media_position( mediacontrol_Instance *self,
142                                  const mediacontrol_PositionOrigin an_origin,
143                                  const mediacontrol_PositionKey a_key,
144                                  mediacontrol_Exception *exception )
145 {
146     mediacontrol_Position* retval = NULL;
147     libvlc_exception_t ex;
148     vlc_int64_t pos;
149     libvlc_input_t * p_input;
150
151     exception = mediacontrol_exception_init( exception );
152     libvlc_exception_init( &ex );
153
154     retval = ( mediacontrol_Position* )malloc( sizeof( mediacontrol_Position ) );
155     retval->origin = an_origin;
156     retval->key = a_key;
157
158     p_input = libvlc_playlist_get_input( self->p_instance, &ex);
159     HANDLE_LIBVLC_EXCEPTION_NULL( &ex );
160
161     if(  an_origin != mediacontrol_AbsolutePosition )
162     {
163         libvlc_input_free( p_input );
164         /* Relative or ModuloPosition make no sense */
165         RAISE_NULL( mediacontrol_PositionOriginNotSupported,
166                     "Only absolute position is valid." );
167     }
168
169     /* We are asked for an AbsolutePosition. */
170     pos = libvlc_input_get_time( p_input, &ex );
171
172     if( a_key == mediacontrol_MediaTime )
173     {
174         retval->value = pos / 1000;
175     }
176     else
177     {
178         if( ! self->p_playlist->p_input ) 
179         {
180             libvlc_input_free( p_input );
181             RAISE_NULL( mediacontrol_InternalException,
182                         "No input" );
183         }
184         retval->value = mediacontrol_unit_convert( self->p_playlist->p_input,
185                                                    mediacontrol_MediaTime,
186                                                    a_key,
187                                                    pos / 1000 );
188     }
189     libvlc_input_free( p_input );
190     return retval;
191 }
192
193 /* Sets the media position */
194 void
195 mediacontrol_set_media_position( mediacontrol_Instance *self,
196                                  const mediacontrol_Position * a_position,
197                                  mediacontrol_Exception *exception )
198 {
199     libvlc_input_t * p_input;
200     libvlc_exception_t ex;
201     vlc_int64_t i_pos;
202
203     libvlc_exception_init( &ex );
204     mediacontrol_exception_init( exception );
205
206     p_input = libvlc_playlist_get_input( self->p_instance, &ex);
207     HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
208
209     i_pos = mediacontrol_position2microsecond( self->p_playlist->p_input, a_position );
210     libvlc_input_set_time( p_input, i_pos, &ex );
211     libvlc_input_free( p_input );
212     HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
213 }
214
215 /* Starts playing a stream */
216 /*
217  * Known issues: since moving in the playlist using playlist_Next
218  * or playlist_Prev implies starting to play items, the a_position
219  * argument will be only honored for the 1st item in the list.
220  * 
221  * XXX:FIXME split moving in the playlist and playing items two
222  * different actions or make playlist_<Next|Prev> accept a time
223  * value to start to play from.
224  */
225 void
226 mediacontrol_start( mediacontrol_Instance *self,
227                     const mediacontrol_Position * a_position,
228                     mediacontrol_Exception *exception )
229 {
230     playlist_t * p_playlist = self->p_playlist;
231
232     exception = mediacontrol_exception_init( exception );
233     if( ! p_playlist )
234     {
235         RAISE( mediacontrol_PlaylistException, "No available playlist" );
236         return;
237     }
238
239     vlc_mutex_lock( &p_playlist->object_lock );
240     if( p_playlist->i_size )
241     {
242         int i_from;
243         char *psz_from = NULL;
244
245         psz_from = ( char * )malloc( 20 * sizeof( char ) );
246         if( psz_from && p_playlist->status.p_item )
247         {
248             i_from = mediacontrol_position2microsecond( p_playlist->p_input, a_position ) / 1000000;
249
250             /* Set start time */
251             snprintf( psz_from, 20, "start-time=%i", i_from );
252             input_ItemAddOption( p_playlist->status.p_item->p_input, psz_from );
253             free( psz_from );
254         }
255
256         vlc_mutex_unlock( &p_playlist->object_lock );
257         playlist_Play( p_playlist );
258     }
259     else
260     {
261         RAISE( mediacontrol_PlaylistException, "Empty playlist." );
262         vlc_mutex_unlock( &p_playlist->object_lock );
263     }
264 }
265
266 void
267 mediacontrol_pause( mediacontrol_Instance *self,
268                     const mediacontrol_Position * a_position,
269                     mediacontrol_Exception *exception )
270 {
271     input_thread_t *p_input = self->p_playlist->p_input;
272
273     /* FIXME: use the a_position parameter */
274     exception=mediacontrol_exception_init( exception );
275     if( p_input != NULL )
276     {
277         var_SetInteger( p_input, "state", PAUSE_S );
278     }
279     else
280     {
281         RAISE( mediacontrol_InternalException, "No input" );
282     }
283 }
284
285 void
286 mediacontrol_resume( mediacontrol_Instance *self,
287                      const mediacontrol_Position * a_position,
288                      mediacontrol_Exception *exception )
289 {
290     input_thread_t *p_input = self->p_playlist->p_input;
291
292     /* FIXME: use the a_position parameter */
293     exception=mediacontrol_exception_init( exception );
294     if( p_input != NULL )
295     {
296         var_SetInteger( p_input, "state", PAUSE_S );
297     }
298     else
299     {
300         RAISE( mediacontrol_InternalException, "No input" );
301     }
302 }
303
304 void
305 mediacontrol_stop( mediacontrol_Instance *self,
306                    const mediacontrol_Position * a_position,
307                    mediacontrol_Exception *exception )
308 {
309     /* FIXME: use the a_position parameter */
310     exception=mediacontrol_exception_init( exception );
311     if( !self->p_playlist )
312     {
313         RAISE( mediacontrol_PlaylistException, "No playlist" );
314     }
315     else
316         playlist_Stop( self->p_playlist );
317 }
318
319 /**************************************************************************
320  * Playlist management
321  **************************************************************************/
322
323 void
324 mediacontrol_playlist_add_item( mediacontrol_Instance *self,
325                                 const char * psz_file,
326                                 mediacontrol_Exception *exception )
327 {
328     libvlc_exception_t ex;
329
330     mediacontrol_exception_init( exception );
331     libvlc_exception_init( &ex );
332
333     libvlc_playlist_add( self->p_instance, psz_file, psz_file, &ex );
334     HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
335 }
336
337 void
338 mediacontrol_playlist_next_item( mediacontrol_Instance *self,
339                                  mediacontrol_Exception *exception )
340 {
341     libvlc_exception_t ex;
342
343     mediacontrol_exception_init( exception );
344     libvlc_exception_init( &ex );
345
346     libvlc_playlist_next( self->p_instance, &ex );
347     HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
348 }
349
350 void
351 mediacontrol_playlist_clear( mediacontrol_Instance *self,
352                              mediacontrol_Exception *exception )
353 {
354     libvlc_exception_t ex;
355
356     mediacontrol_exception_init( exception );
357     libvlc_exception_init( &ex );
358
359     libvlc_playlist_clear( self->p_instance, &ex );
360     HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
361 }
362
363 mediacontrol_PlaylistSeq *
364 mediacontrol_playlist_get_list( mediacontrol_Instance *self,
365                                 mediacontrol_Exception *exception )
366 {
367     mediacontrol_PlaylistSeq *retval = NULL;
368     int i_index;
369     playlist_t * p_playlist = self->p_playlist;
370     int i_playlist_size;
371
372     exception=mediacontrol_exception_init( exception );
373     if( !p_playlist )
374     {
375         RAISE( mediacontrol_PlaylistException, "No playlist" );
376         return NULL;
377     }
378
379     vlc_mutex_lock( &p_playlist->object_lock );
380     i_playlist_size = p_playlist->i_size;
381
382     retval = mediacontrol_PlaylistSeq__alloc( i_playlist_size );
383
384     for( i_index = 0 ; i_index < i_playlist_size ; i_index++ )
385     {
386         retval->data[i_index] = strdup( p_playlist->pp_items[i_index]->p_input->psz_uri );
387     }
388     vlc_mutex_unlock( &p_playlist->object_lock );
389
390     return retval;
391 }
392
393 /***************************************************************************
394  * Status feedback
395  ***************************************************************************/
396
397 mediacontrol_StreamInformation *
398 mediacontrol_get_stream_information( mediacontrol_Instance *self,
399                                      mediacontrol_PositionKey a_key,
400                                      mediacontrol_Exception *exception )
401 {
402     mediacontrol_StreamInformation *retval = NULL;
403     input_thread_t *p_input = self->p_playlist->p_input;
404     vlc_value_t val;
405
406     retval = ( mediacontrol_StreamInformation* )
407                             malloc( sizeof( mediacontrol_StreamInformation ) );
408     if( ! retval )
409     {
410         RAISE( mediacontrol_InternalException, "Out of memory" );
411         return NULL;
412     }
413
414     if( ! p_input )
415     {
416         /* No p_input defined */
417         retval->streamstatus = mediacontrol_UndefinedStatus;
418         retval->url          = strdup( "None" );
419         retval->position     = 0;
420         retval->length       = 0;
421     }
422     else
423     {
424         switch( var_GetInteger( p_input, "state" ) )
425         {
426         case PLAYING_S     :
427             retval->streamstatus = mediacontrol_PlayingStatus;
428             break;
429         case PAUSE_S       :
430             retval->streamstatus = mediacontrol_PauseStatus;
431             break;
432         case INIT_S        :
433             retval->streamstatus = mediacontrol_InitStatus;
434             break;
435         case END_S         :
436             retval->streamstatus = mediacontrol_EndStatus;
437             break;
438         default :
439             retval->streamstatus = mediacontrol_UndefinedStatus;
440             break;
441         }
442
443         retval->url = strdup( p_input->input.p_item->psz_uri );
444
445         /* TIME and LENGTH are in microseconds. We want them in ms */
446         var_Get( p_input, "time", &val);
447         retval->position = val.i_time / 1000;
448
449         var_Get( p_input, "length", &val);
450         retval->length = val.i_time / 1000;
451
452         retval->position = mediacontrol_unit_convert( p_input,
453                                          mediacontrol_MediaTime, a_key,
454                                          retval->position );
455         retval->length   = mediacontrol_unit_convert( p_input,
456                                          mediacontrol_MediaTime, a_key,
457                                          retval->length );
458     }
459     return retval;
460 }