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