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