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 *****************************************************************************/
24 #include <mediacontrol_internal.h>
25 #include <vlc/mediacontrol.h>
27 #include <vlc/libvlc.h>
31 #include <vlc_demux.h>
35 #define HAS_SNAPSHOT 1
41 #include <stdlib.h> /* malloc(), free() */
44 #include <errno.h> /* ENOMEM */
51 #ifdef HAVE_SYS_TIME_H
52 # include <sys/time.h>
54 #ifdef HAVE_SYS_TYPES_H
55 # include <sys/types.h>
58 mediacontrol_Instance* mediacontrol_new( char** args, mediacontrol_Exception *exception )
60 mediacontrol_Instance* retval;
61 libvlc_exception_t ex;
67 libvlc_exception_init( &ex );
68 exception=mediacontrol_exception_init( exception );
73 for ( p_tmp = args ; *p_tmp != NULL ; p_tmp++ )
77 ppsz_argv = malloc( ( i_count + 2 ) * sizeof( char * ) ) ;
80 RAISE_NULL( mediacontrol_InternalException, "out of memory" );
83 for ( i_index = 0; i_index < i_count; i_index++ )
85 ppsz_argv[i_index + 1] = strdup( args[i_index] );
86 if( ! ppsz_argv[i_index + 1] )
88 RAISE_NULL( mediacontrol_InternalException, "out of memory" );
92 ppsz_argv[i_count + 2] = NULL;
94 retval = ( mediacontrol_Instance* )malloc( sizeof( mediacontrol_Instance ) );
97 RAISE_NULL( mediacontrol_InternalException, "out of memory" );
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 );
107 mediacontrol_exit( mediacontrol_Instance *self )
109 libvlc_exception_t ex;
110 libvlc_exception_init( &ex );
112 libvlc_destroy( self->p_instance, &ex );
116 mediacontrol_get_libvlc_instance( mediacontrol_Instance *self )
118 return self->p_instance;
121 mediacontrol_Instance *
122 mediacontrol_new_from_instance( libvlc_instance_t* p_instance,
123 mediacontrol_Exception *exception )
125 mediacontrol_Instance* retval;
127 retval = ( mediacontrol_Instance* )malloc( sizeof( mediacontrol_Instance ) );
130 RAISE_NULL( mediacontrol_InternalException, "out of memory" );
132 retval->p_instance = p_instance;
133 retval->p_playlist = retval->p_instance->p_libvlc_int->p_playlist;
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 )
146 mediacontrol_Position* retval = NULL;
147 libvlc_exception_t ex;
149 libvlc_input_t * p_input;
151 exception = mediacontrol_exception_init( exception );
152 libvlc_exception_init( &ex );
154 retval = ( mediacontrol_Position* )malloc( sizeof( mediacontrol_Position ) );
155 retval->origin = an_origin;
158 p_input = libvlc_playlist_get_input( self->p_instance, &ex);
159 HANDLE_LIBVLC_EXCEPTION_NULL( &ex );
161 if( an_origin != mediacontrol_AbsolutePosition )
163 libvlc_input_free( p_input );
164 /* Relative or ModuloPosition make no sense */
165 RAISE_NULL( mediacontrol_PositionOriginNotSupported,
166 "Only absolute position is valid." );
169 /* We are asked for an AbsolutePosition. */
170 pos = libvlc_input_get_time( p_input, &ex );
172 if( a_key == mediacontrol_MediaTime )
174 retval->value = pos / 1000;
178 if( ! self->p_playlist->p_input )
180 libvlc_input_free( p_input );
181 RAISE_NULL( mediacontrol_InternalException,
184 retval->value = mediacontrol_unit_convert( self->p_playlist->p_input,
185 mediacontrol_MediaTime,
189 libvlc_input_free( p_input );
193 /* Sets the media position */
195 mediacontrol_set_media_position( mediacontrol_Instance *self,
196 const mediacontrol_Position * a_position,
197 mediacontrol_Exception *exception )
199 libvlc_input_t * p_input;
200 libvlc_exception_t ex;
203 libvlc_exception_init( &ex );
204 mediacontrol_exception_init( exception );
206 p_input = libvlc_playlist_get_input( self->p_instance, &ex);
207 HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
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 );
215 /* Starts playing a stream */
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.
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.
226 mediacontrol_start( mediacontrol_Instance *self,
227 const mediacontrol_Position * a_position,
228 mediacontrol_Exception *exception )
230 playlist_t * p_playlist = self->p_playlist;
232 exception = mediacontrol_exception_init( exception );
235 RAISE( mediacontrol_PlaylistException, "No available playlist" );
239 vlc_mutex_lock( &p_playlist->object_lock );
240 if( p_playlist->i_size )
243 char *psz_from = NULL;
245 psz_from = ( char * )malloc( 20 * sizeof( char ) );
246 if( psz_from && p_playlist->status.p_item )
248 i_from = mediacontrol_position2microsecond( p_playlist->p_input, a_position ) / 1000000;
251 snprintf( psz_from, 20, "start-time=%i", i_from );
252 input_ItemAddOption( p_playlist->status.p_item->p_input, psz_from );
256 vlc_mutex_unlock( &p_playlist->object_lock );
257 playlist_Play( p_playlist );
261 RAISE( mediacontrol_PlaylistException, "Empty playlist." );
262 vlc_mutex_unlock( &p_playlist->object_lock );
267 mediacontrol_pause( mediacontrol_Instance *self,
268 const mediacontrol_Position * a_position,
269 mediacontrol_Exception *exception )
271 input_thread_t *p_input = self->p_playlist->p_input;
273 /* FIXME: use the a_position parameter */
274 exception=mediacontrol_exception_init( exception );
275 if( p_input != NULL )
277 var_SetInteger( p_input, "state", PAUSE_S );
281 RAISE( mediacontrol_InternalException, "No input" );
286 mediacontrol_resume( mediacontrol_Instance *self,
287 const mediacontrol_Position * a_position,
288 mediacontrol_Exception *exception )
290 input_thread_t *p_input = self->p_playlist->p_input;
292 /* FIXME: use the a_position parameter */
293 exception=mediacontrol_exception_init( exception );
294 if( p_input != NULL )
296 var_SetInteger( p_input, "state", PAUSE_S );
300 RAISE( mediacontrol_InternalException, "No input" );
305 mediacontrol_stop( mediacontrol_Instance *self,
306 const mediacontrol_Position * a_position,
307 mediacontrol_Exception *exception )
309 /* FIXME: use the a_position parameter */
310 exception=mediacontrol_exception_init( exception );
311 if( !self->p_playlist )
313 RAISE( mediacontrol_PlaylistException, "No playlist" );
316 playlist_Stop( self->p_playlist );
319 /**************************************************************************
320 * Playlist management
321 **************************************************************************/
324 mediacontrol_playlist_add_item( mediacontrol_Instance *self,
325 const char * psz_file,
326 mediacontrol_Exception *exception )
328 libvlc_exception_t ex;
330 mediacontrol_exception_init( exception );
331 libvlc_exception_init( &ex );
333 libvlc_playlist_add( self->p_instance, psz_file, psz_file, &ex );
334 HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
338 mediacontrol_playlist_next_item( mediacontrol_Instance *self,
339 mediacontrol_Exception *exception )
341 libvlc_exception_t ex;
343 mediacontrol_exception_init( exception );
344 libvlc_exception_init( &ex );
346 libvlc_playlist_next( self->p_instance, &ex );
347 HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
351 mediacontrol_playlist_clear( mediacontrol_Instance *self,
352 mediacontrol_Exception *exception )
354 libvlc_exception_t ex;
356 mediacontrol_exception_init( exception );
357 libvlc_exception_init( &ex );
359 libvlc_playlist_clear( self->p_instance, &ex );
360 HANDLE_LIBVLC_EXCEPTION_VOID( &ex );
363 mediacontrol_PlaylistSeq *
364 mediacontrol_playlist_get_list( mediacontrol_Instance *self,
365 mediacontrol_Exception *exception )
367 mediacontrol_PlaylistSeq *retval = NULL;
369 playlist_t * p_playlist = self->p_playlist;
372 exception=mediacontrol_exception_init( exception );
375 RAISE( mediacontrol_PlaylistException, "No playlist" );
379 vlc_mutex_lock( &p_playlist->object_lock );
380 i_playlist_size = p_playlist->i_size;
382 retval = mediacontrol_PlaylistSeq__alloc( i_playlist_size );
384 for( i_index = 0 ; i_index < i_playlist_size ; i_index++ )
386 retval->data[i_index] = strdup( p_playlist->pp_items[i_index]->p_input->psz_uri );
388 vlc_mutex_unlock( &p_playlist->object_lock );
393 /***************************************************************************
395 ***************************************************************************/
397 mediacontrol_StreamInformation *
398 mediacontrol_get_stream_information( mediacontrol_Instance *self,
399 mediacontrol_PositionKey a_key,
400 mediacontrol_Exception *exception )
402 mediacontrol_StreamInformation *retval = NULL;
403 input_thread_t *p_input = self->p_playlist->p_input;
406 retval = ( mediacontrol_StreamInformation* )
407 malloc( sizeof( mediacontrol_StreamInformation ) );
410 RAISE( mediacontrol_InternalException, "Out of memory" );
416 /* No p_input defined */
417 retval->streamstatus = mediacontrol_UndefinedStatus;
418 retval->url = strdup( "None" );
419 retval->position = 0;
424 switch( var_GetInteger( p_input, "state" ) )
427 retval->streamstatus = mediacontrol_PlayingStatus;
430 retval->streamstatus = mediacontrol_PauseStatus;
433 retval->streamstatus = mediacontrol_InitStatus;
436 retval->streamstatus = mediacontrol_EndStatus;
439 retval->streamstatus = mediacontrol_UndefinedStatus;
443 retval->url = strdup( p_input->input.p_item->psz_uri );
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;
449 var_Get( p_input, "length", &val);
450 retval->length = val.i_time / 1000;
452 retval->position = mediacontrol_unit_convert( p_input,
453 mediacontrol_MediaTime, a_key,
455 retval->length = mediacontrol_unit_convert( p_input,
456 mediacontrol_MediaTime, a_key,