]> git.sesse.net Git - vlc/blob - src/control/core.c
* ALL: WinCE EVC compilation fixes.
[vlc] / src / control / core.c
1 /*****************************************************************************
2  * core.c: Core functions : init, playlist, stream management
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  * $Id: vlc.c 10786 2005-04-23 23:19:17Z zorglub $
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include <vlc/control.h>
25
26 #include <vlc/intf.h>
27 #include <vlc/vout.h>
28 #include <vlc/aout.h>
29 #include <vlc_demux.h>
30
31 #include <vlc_osd.h>
32
33 #define HAS_SNAPSHOT 1
34
35 #ifdef HAS_SNAPSHOT
36 #include <snapshot.h>
37 #endif
38
39 #include <stdlib.h>                                      /* malloc(), free() */
40 #include <string.h>
41
42 #include <errno.h>                                                 /* ENOMEM */
43 #include <stdio.h>
44 #include <ctype.h>
45
46 #ifdef HAVE_UNISTD_H
47 #    include <unistd.h>
48 #endif
49 #ifdef HAVE_SYS_TIME_H
50 #    include <sys/time.h>
51 #endif
52 #ifdef HAVE_SYS_TYPES_H
53 #    include <sys/types.h>
54 #endif
55
56 #define RAISE( c, m )  exception->code = c; \
57                        exception->message = strdup(m);
58
59
60 mediacontrol_Instance* mediacontrol_new_from_object( vlc_object_t* p_object,
61                                                      mediacontrol_Exception *exception )
62 {
63     mediacontrol_Instance* retval;
64     vlc_object_t *p_vlc;
65
66     p_vlc = vlc_object_find( p_object, VLC_OBJECT_ROOT, FIND_PARENT );
67     if( ! p_vlc )
68     {
69         RAISE( mediacontrol_InternalException, "Unable to initialize VLC" );
70         return NULL;
71     }
72     retval = ( mediacontrol_Instance* )malloc( sizeof( mediacontrol_Instance ) );
73     retval->p_vlc = p_vlc;
74     retval->vlc_object_id = p_vlc->i_object_id;
75
76     /* We can keep references on these, which should not change. Is it true ? */
77     retval->p_playlist = vlc_object_find( p_vlc, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
78     retval->p_intf = vlc_object_find( p_vlc, VLC_OBJECT_INTF, FIND_ANYWHERE );
79
80     if( ! retval->p_playlist || ! retval->p_intf )
81     {
82         RAISE( mediacontrol_InternalException, "No available interface" );
83         return NULL;
84     }
85     return retval;
86 };
87
88
89 /**************************************************************************
90  * Playback management
91  **************************************************************************/
92 mediacontrol_Position*
93 mediacontrol_get_media_position( mediacontrol_Instance *self,
94                                  const mediacontrol_PositionOrigin an_origin,
95                                  const mediacontrol_PositionKey a_key,
96                                  mediacontrol_Exception *exception )
97 {
98     mediacontrol_Position* retval;
99     vlc_value_t val;
100     input_thread_t * p_input = self->p_playlist->p_input;
101
102     exception = mediacontrol_exception_init( exception );
103
104     retval = ( mediacontrol_Position* )malloc( sizeof( mediacontrol_Position ) );
105     retval->origin = an_origin;
106     retval->key = a_key;
107
108     if( ! p_input )
109     {
110         /*
111            RAISE( mediacontrol_InternalException, "No input thread." );
112            return( NULL );
113         */
114         retval->value = 0;
115         return retval;
116     }
117
118     if(  an_origin == mediacontrol_RelativePosition
119          || an_origin == mediacontrol_ModuloPosition )
120     {
121         /* Relative or ModuloPosition make no sense */
122         retval->value = 0;
123         return retval;
124     }
125
126     /* We are asked for an AbsolutePosition. */
127     val.i_time = 0;
128     var_Get( p_input, "time", &val );
129     /* FIXME: check val.i_time > 0 */
130
131     retval->value = mediacontrol_unit_convert( p_input,
132                                                mediacontrol_MediaTime,
133                                                a_key,
134                                                val.i_time / 1000 );
135     return retval;
136 }
137
138 /* Sets the media position */
139 void
140 mediacontrol_set_media_position( mediacontrol_Instance *self,
141                                  const mediacontrol_Position * a_position,
142                                  mediacontrol_Exception *exception )
143 {
144     vlc_value_t val;
145     input_thread_t * p_input = self->p_playlist->p_input;
146
147     exception=mediacontrol_exception_init( exception );
148     if( ! p_input )
149     {
150         RAISE( mediacontrol_InternalException, "No input thread." );
151         return;
152     }
153
154     if( !var_GetBool( p_input, "seekable" ) )
155     {
156         RAISE( mediacontrol_InvalidPosition, "Stream not seekable" );
157         return;
158     }
159
160     val.i_time = mediacontrol_position2microsecond( p_input, a_position );
161     var_Set( p_input, "time", val );
162     return;
163 }
164
165 /* Starts playing a stream */
166 void
167 mediacontrol_start( mediacontrol_Instance *self,
168                     const mediacontrol_Position * a_position,
169                     mediacontrol_Exception *exception )
170 {
171     playlist_t * p_playlist = self->p_playlist;
172
173     exception = mediacontrol_exception_init( exception );
174     if( ! p_playlist )
175     {
176         RAISE( mediacontrol_PlaylistException, "No available playlist" );
177         return;
178     }
179
180     vlc_mutex_lock( &p_playlist->object_lock );
181     if( p_playlist->i_size )
182     {
183         vlc_value_t val;
184
185         vlc_mutex_unlock( &p_playlist->object_lock );
186
187         /* Set start time */
188         val.i_int = mediacontrol_position2microsecond( p_playlist->p_input, a_position ) / 1000000;
189         var_Set( p_playlist, "start-time", val );
190
191         playlist_Play( p_playlist );
192     }
193     else
194     {
195         RAISE( mediacontrol_PlaylistException, "Empty playlist." );
196         vlc_mutex_unlock( &p_playlist->object_lock );
197         return;
198     }
199
200     return;
201 }
202
203 void
204 mediacontrol_pause( mediacontrol_Instance *self,
205                     const mediacontrol_Position * a_position,
206                     mediacontrol_Exception *exception )
207 {
208     input_thread_t *p_input = self->p_playlist->p_input;;
209
210     /* FIXME: use the a_position parameter */
211     exception=mediacontrol_exception_init( exception );
212     if( p_input != NULL )
213     {
214         var_SetInteger( p_input, "state", PAUSE_S );
215     }
216     else
217     {
218         RAISE( mediacontrol_InternalException, "No input" );
219     }
220
221     return;
222 }
223
224 void
225 mediacontrol_resume( mediacontrol_Instance *self,
226                      const mediacontrol_Position * a_position,
227                      mediacontrol_Exception *exception )
228 {
229     input_thread_t *p_input = self->p_playlist->p_input;
230
231     /* FIXME: use the a_position parameter */
232     exception=mediacontrol_exception_init( exception );
233     if( p_input != NULL )
234     {
235         var_SetInteger( p_input, "state", PAUSE_S );
236     }
237     else
238     {
239         RAISE( mediacontrol_InternalException, "No input" );
240     }
241 }
242
243 void
244 mediacontrol_stop( mediacontrol_Instance *self,
245                    const mediacontrol_Position * a_position,
246                    mediacontrol_Exception *exception )
247 {
248     /* FIXME: use the a_position parameter */
249     exception=mediacontrol_exception_init( exception );
250     if( !self->p_playlist )
251     {
252         RAISE( mediacontrol_PlaylistException, "No playlist" );
253         return;
254     }
255
256     playlist_Stop( self->p_playlist );
257 }
258
259 /**************************************************************************
260  * Playlist management
261  **************************************************************************/
262
263 void
264 mediacontrol_playlist_add_item( mediacontrol_Instance *self,
265                                 const char * psz_file,
266                                 mediacontrol_Exception *exception )
267 {
268     exception=mediacontrol_exception_init( exception );
269     if( !self->p_playlist )
270     {
271         RAISE( mediacontrol_InternalException, "No playlist" );
272         return;
273     }
274
275     playlist_Add( self->p_playlist, psz_file, psz_file , PLAYLIST_REPLACE, 0 );
276 }
277
278 void
279 mediacontrol_playlist_clear( mediacontrol_Instance *self,
280                              mediacontrol_Exception *exception )
281 {
282     exception=mediacontrol_exception_init( exception );
283     if( !self->p_playlist )
284     {
285         RAISE( mediacontrol_PlaylistException, "No playlist" );
286         return;
287     }
288
289     playlist_Clear( self->p_playlist );
290
291     return;
292 }
293
294 mediacontrol_PlaylistSeq *
295 mediacontrol_playlist_get_list( mediacontrol_Instance *self,
296                                 mediacontrol_Exception *exception )
297 {
298     mediacontrol_PlaylistSeq *retval;
299     int i_index;
300     playlist_t * p_playlist = self->p_playlist;
301     int i_playlist_size;
302
303     exception=mediacontrol_exception_init( exception );
304     if( !p_playlist )
305     {
306         RAISE( mediacontrol_PlaylistException, "No playlist" );
307         return NULL;
308     }
309
310     vlc_mutex_lock( &p_playlist->object_lock );
311     i_playlist_size = p_playlist->i_size;
312
313     retval = mediacontrol_PlaylistSeq__alloc( i_playlist_size );
314
315     for( i_index = 0 ; i_index < i_playlist_size ; i_index++ )
316     {
317         retval->data[i_index] = strdup( p_playlist->pp_items[i_index]->input.psz_uri );
318     }
319     vlc_mutex_unlock( &p_playlist->object_lock );
320
321     return retval;
322 }
323
324 /***************************************************************************
325  * Status feedback
326  ***************************************************************************/
327
328 mediacontrol_StreamInformation *
329 mediacontrol_get_stream_information( mediacontrol_Instance *self,
330                                      mediacontrol_PositionKey a_key,
331                                      mediacontrol_Exception *exception )
332 {
333     mediacontrol_StreamInformation *retval;
334     input_thread_t *p_input = self->p_playlist->p_input;
335     vlc_value_t val;
336
337     retval = ( mediacontrol_StreamInformation* )malloc( sizeof( mediacontrol_StreamInformation ) );
338     if( ! retval )
339     {
340         RAISE( mediacontrol_InternalException, "Out of memory" );
341         return NULL;
342     }
343
344     if( ! p_input )
345     {
346         /* No p_input defined */
347         retval->streamstatus = mediacontrol_UndefinedStatus;
348         retval->url          = strdup( "None" );
349         retval->position     = 0;
350         retval->length       = 0;
351     }
352     else
353     {
354         switch( var_GetInteger( p_input, "state" ) )
355         {
356         case PLAYING_S     :
357             retval->streamstatus = mediacontrol_PlayingStatus;
358             break;
359         case PAUSE_S       :
360             retval->streamstatus = mediacontrol_PauseStatus;
361             break;
362         case INIT_S        :
363             retval->streamstatus = mediacontrol_InitStatus;
364             break;
365         case END_S         :
366             retval->streamstatus = mediacontrol_EndStatus;
367             break;
368         default :
369             retval->streamstatus = mediacontrol_UndefinedStatus;
370             break;
371         }
372
373         retval->url = strdup( p_input->input.p_item->psz_uri );
374
375         /* TIME and LENGTH are in microseconds. We want them in ms */
376         var_Get( p_input, "time", &val);
377         retval->position = val.i_time / 1000;
378
379         var_Get( p_input, "length", &val);
380         retval->length = val.i_time / 1000;
381
382         retval->position = mediacontrol_unit_convert( p_input,
383                                                       mediacontrol_MediaTime, a_key,
384                                                       retval->position );
385         retval->length   = mediacontrol_unit_convert( p_input,
386                                                       mediacontrol_MediaTime, a_key,
387                                                       retval->length );
388     }
389     return retval;
390 }