1 /*****************************************************************************
2 * core.c: Core functions : init, playlist, stream management
3 *****************************************************************************
4 * Copyright (C) 2005 the VideoLAN team
7 * Authors: Olivier Aubert <olivier.aubert@liris.univ-lyon1.fr>
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 *****************************************************************************/
25 #include <vlc/mediacontrol.h>
27 #include <vlc/libvlc.h>
28 #include <vlc_interface.h>
29 #include <vlc_playlist.h>
33 #include <vlc_input.h>
35 #include "mediacontrol_internal.h"
37 #include <stdlib.h> /* malloc(), free() */
40 #include <errno.h> /* ENOMEM */
47 #ifdef HAVE_SYS_TIME_H
48 # include <sys/time.h>
50 #ifdef HAVE_SYS_TYPES_H
51 # include <sys/types.h>
54 mediacontrol_Instance* mediacontrol_new( int argc, char** argv, mediacontrol_Exception *exception )
56 mediacontrol_Instance* retval;
57 libvlc_exception_t ex;
58 char** ppsz_argv = NULL;
61 libvlc_exception_init( &ex );
62 mediacontrol_exception_init( exception );
64 retval = ( mediacontrol_Instance* )malloc( sizeof( mediacontrol_Instance ) );
66 RAISE_NULL( mediacontrol_InternalException, "Out of memory" );
68 /* Prepend a dummy argv[0] so that users of the API do not have to
69 do it themselves, and can simply provide the args list. */
70 ppsz_argv = malloc( ( argc + 2 ) * sizeof( char * ) ) ;
72 RAISE_NULL( mediacontrol_InternalException, "Out of memory" );
74 ppsz_argv[0] = strdup("vlc");
75 for ( i_index = 0; i_index < argc; i_index++ )
76 ppsz_argv[i_index + 1] = argv[i_index];
77 ppsz_argv[argc + 1] = NULL;
79 retval->p_instance = libvlc_new( argc + 1, ppsz_argv, &ex );
80 retval->p_playlist = retval->p_instance->p_libvlc_int->p_playlist;
81 HANDLE_LIBVLC_EXCEPTION_NULL( &ex );
86 mediacontrol_exit( mediacontrol_Instance *self )
88 libvlc_exception_t ex;
89 libvlc_exception_init( &ex );
91 libvlc_destroy( self->p_instance, &ex );
95 mediacontrol_get_libvlc_instance( mediacontrol_Instance *self )
97 return self->p_instance;
100 mediacontrol_Instance *
101 mediacontrol_new_from_instance( libvlc_instance_t* p_instance,
102 mediacontrol_Exception *exception )
104 mediacontrol_Instance* retval;
106 retval = ( mediacontrol_Instance* )malloc( sizeof( mediacontrol_Instance ) );
109 RAISE_NULL( mediacontrol_InternalException, "Out of memory" );
111 retval->p_instance = p_instance;
112 retval->p_playlist = retval->p_instance->p_libvlc_int->p_playlist;
116 /**************************************************************************
117 * Playback management
118 **************************************************************************/
119 mediacontrol_Position*
120 mediacontrol_get_media_position( mediacontrol_Instance *self,
121 const mediacontrol_PositionOrigin an_origin,
122 const mediacontrol_PositionKey a_key,
123 mediacontrol_Exception *exception )
125 mediacontrol_Position* retval = NULL;
126 libvlc_exception_t ex;
128 libvlc_media_instance_t * p_mi;
130 mediacontrol_exception_init( exception );
131 libvlc_exception_init( &ex );
133 retval = ( mediacontrol_Position* )malloc( sizeof( mediacontrol_Position ) );
134 retval->origin = an_origin;
137 p_mi = libvlc_playlist_get_media_instance( self->p_instance, &ex);
138 HANDLE_LIBVLC_EXCEPTION_NULL( &ex );
140 if( an_origin != mediacontrol_AbsolutePosition )
142 libvlc_media_instance_release( p_mi );
143 /* Relative or ModuloPosition make no sense */
144 RAISE_NULL( mediacontrol_PositionOriginNotSupported,
145 "Only absolute position is valid." );
148 /* We are asked for an AbsolutePosition. */
149 pos = libvlc_media_instance_get_time( p_mi, &ex );
151 if( a_key == mediacontrol_MediaTime )
157 if( ! self->p_playlist->p_input )
159 libvlc_media_instance_release( p_mi );
160 RAISE_NULL( mediacontrol_InternalException,
163 retval->value = private_mediacontrol_unit_convert( self->p_playlist->p_input,
164 mediacontrol_MediaTime,
168 libvlc_media_instance_release( p_mi );
172 /* Sets the media position */
174 mediacontrol_set_media_position( mediacontrol_Instance *self,
175 const mediacontrol_Position * a_position,
176 mediacontrol_Exception *exception )
178 libvlc_media_instance_t * p_mi;
179 libvlc_exception_t ex;
182 libvlc_exception_init( &ex );
183 mediacontrol_exception_init( exception );
185 p_mi = libvlc_playlist_get_media_instance( self->p_instance, &ex);
186 HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
188 i_pos = private_mediacontrol_position2microsecond( self->p_playlist->p_input, a_position );
189 libvlc_media_instance_set_time( p_mi, i_pos / 1000, &ex );
190 libvlc_media_instance_release( p_mi );
191 HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
194 /* Starts playing a stream */
196 * Known issues: since moving in the playlist using playlist_Next
197 * or playlist_Prev implies starting to play items, the a_position
198 * argument will be only honored for the 1st item in the list.
200 * XXX:FIXME split moving in the playlist and playing items two
201 * different actions or make playlist_<Next|Prev> accept a time
202 * value to start to play from.
205 mediacontrol_start( mediacontrol_Instance *self,
206 const mediacontrol_Position * a_position,
207 mediacontrol_Exception *exception )
209 playlist_t * p_playlist = self->p_playlist;
211 mediacontrol_exception_init( exception );
214 RAISE( mediacontrol_PlaylistException, "No available playlist" );
218 vlc_mutex_lock( &p_playlist->object_lock );
219 if( p_playlist->items.i_size )
222 char *psz_from = NULL;
224 psz_from = ( char * )malloc( 20 * sizeof( char ) );
225 if( psz_from && p_playlist->status.p_item )
227 i_from = private_mediacontrol_position2microsecond( p_playlist->p_input, a_position ) / 1000000;
230 snprintf( psz_from, 20, "start-time=%i", i_from );
231 input_ItemAddOption( p_playlist->status.p_item->p_input, psz_from );
235 vlc_mutex_unlock( &p_playlist->object_lock );
236 playlist_Play( p_playlist );
240 RAISE( mediacontrol_PlaylistException, "Empty playlist." );
241 vlc_mutex_unlock( &p_playlist->object_lock );
246 mediacontrol_pause( mediacontrol_Instance *self,
247 const mediacontrol_Position * a_position,
248 mediacontrol_Exception *exception )
250 input_thread_t *p_input = self->p_playlist->p_input;
252 /* FIXME: use the a_position parameter */
253 mediacontrol_exception_init( exception );
254 if( p_input != NULL )
256 var_SetInteger( p_input, "state", PAUSE_S );
260 RAISE( mediacontrol_InternalException, "No input" );
265 mediacontrol_resume( mediacontrol_Instance *self,
266 const mediacontrol_Position * a_position,
267 mediacontrol_Exception *exception )
269 input_thread_t *p_input = self->p_playlist->p_input;
271 /* FIXME: use the a_position parameter */
272 mediacontrol_exception_init( exception );
273 if( p_input != NULL )
275 var_SetInteger( p_input, "state", PAUSE_S );
279 RAISE( mediacontrol_InternalException, "No input" );
284 mediacontrol_stop( mediacontrol_Instance *self,
285 const mediacontrol_Position * a_position,
286 mediacontrol_Exception *exception )
288 /* FIXME: use the a_position parameter */
289 mediacontrol_exception_init( exception );
290 if( !self->p_playlist )
292 RAISE( mediacontrol_PlaylistException, "No playlist" );
295 playlist_Stop( self->p_playlist );
298 /**************************************************************************
299 * Playlist management
300 **************************************************************************/
303 mediacontrol_playlist_add_item( mediacontrol_Instance *self,
304 const char * psz_file,
305 mediacontrol_Exception *exception )
307 libvlc_exception_t ex;
309 mediacontrol_exception_init( exception );
310 libvlc_exception_init( &ex );
312 libvlc_playlist_add( self->p_instance, psz_file, psz_file, &ex );
313 HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
317 mediacontrol_playlist_next_item( mediacontrol_Instance *self,
318 mediacontrol_Exception *exception )
320 libvlc_exception_t ex;
322 mediacontrol_exception_init( exception );
323 libvlc_exception_init( &ex );
325 libvlc_playlist_next( self->p_instance, &ex );
326 HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
330 mediacontrol_playlist_clear( mediacontrol_Instance *self,
331 mediacontrol_Exception *exception )
333 libvlc_exception_t ex;
335 mediacontrol_exception_init( exception );
336 libvlc_exception_init( &ex );
338 libvlc_playlist_clear( self->p_instance, &ex );
339 HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
342 mediacontrol_PlaylistSeq *
343 mediacontrol_playlist_get_list( mediacontrol_Instance *self,
344 mediacontrol_Exception *exception )
346 mediacontrol_PlaylistSeq *retval = NULL;
348 playlist_t * p_playlist = self->p_playlist;
351 mediacontrol_exception_init( exception );
354 RAISE( mediacontrol_PlaylistException, "No playlist" );
358 vlc_mutex_lock( &p_playlist->object_lock );
359 i_playlist_size = p_playlist->current.i_size;
361 retval = private_mediacontrol_PlaylistSeq__alloc( i_playlist_size );
363 for( i_index = 0 ; i_index < i_playlist_size ; i_index++ )
365 retval->data[i_index] = input_item_GetURI( ARRAY_VAL(p_playlist->current, i_index)->p_input );
367 vlc_mutex_unlock( &p_playlist->object_lock );
372 /***************************************************************************
374 ***************************************************************************/
376 mediacontrol_StreamInformation *
377 mediacontrol_get_stream_information( mediacontrol_Instance *self,
378 mediacontrol_PositionKey a_key,
379 mediacontrol_Exception *exception )
381 mediacontrol_StreamInformation *retval = NULL;
382 input_thread_t *p_input = self->p_playlist->p_input;
385 retval = ( mediacontrol_StreamInformation* )
386 malloc( sizeof( mediacontrol_StreamInformation ) );
389 RAISE( mediacontrol_InternalException, "Out of memory" );
395 /* No p_input defined */
396 retval->streamstatus = mediacontrol_UndefinedStatus;
397 retval->url = strdup( "None" );
398 retval->position = 0;
403 switch( var_GetInteger( p_input, "state" ) )
406 retval->streamstatus = mediacontrol_PlayingStatus;
409 retval->streamstatus = mediacontrol_PauseStatus;
412 retval->streamstatus = mediacontrol_InitStatus;
415 retval->streamstatus = mediacontrol_EndStatus;
418 retval->streamstatus = mediacontrol_UndefinedStatus;
422 retval->url = input_item_GetURI( input_GetItem( p_input ) );
424 /* TIME and LENGTH are in microseconds. We want them in ms */
425 var_Get( p_input, "time", &val);
426 retval->position = val.i_time / 1000;
428 var_Get( p_input, "length", &val);
429 retval->length = val.i_time / 1000;
431 retval->position = private_mediacontrol_unit_convert( p_input,
432 mediacontrol_MediaTime, a_key,
434 retval->length = private_mediacontrol_unit_convert( p_input,
435 mediacontrol_MediaTime, a_key,