b5b51ff98959b9d93442b1ad3e93a8a262f64594
[vlc.git] / bindings / python / vlc_mediacontrol.c
1 /*****************************************************************************
2  * vlc_mediacontrol.c: vlc.MediaControl binding
3  *****************************************************************************
4  * Copyright (C) 2006 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Olivier Aubert <oaubert at bat710.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 #include "vlcglue.h"
24
25 /*****************************************************************************
26  * VLC MediaControl object implementation
27  *****************************************************************************/
28
29 /* The MediaControl constructor takes either an existing vlc.Instance or a
30    list of strings */
31 static PyObject *
32 MediaControl_new( PyTypeObject *type, PyObject *args, PyObject *kwds )
33 {
34     MediaControl *self;
35     mediacontrol_Exception *exception = NULL;
36     PyObject* py_param = NULL;
37     char** ppsz_args = NULL;
38     libvlc_instance_t* p_instance = NULL;
39     Py_ssize_t i_size = 0;
40
41     self = PyObject_New( MediaControl, &MediaControl_Type );
42
43     fprintf (stderr, "Instanciating mediacontrol\n");
44     if( PyArg_ParseTuple( args, "O", &py_param ) )
45     {
46         if( PyObject_TypeCheck( py_param, &vlcInstance_Type ) == 1 )
47         {
48             p_instance = ((vlcInstance*)py_param)->p_instance;
49         }
50         else
51         {
52             Py_ssize_t i_index;
53
54             Py_INCREF( py_param );
55             if( ! PySequence_Check( py_param ) )
56             {
57                 PyErr_SetString( PyExc_TypeError, "Parameter must be a vlc.Instance or a sequence of strings." );
58                 Py_DECREF( py_param );
59                 return NULL;
60             }
61             i_size = PySequence_Size( py_param );
62             ppsz_args = malloc( ( i_size + 1 ) * sizeof( char * ) );
63             if( ! ppsz_args )
64             {
65                 PyErr_SetString( PyExc_MemoryError, "Out of memory" );
66                 Py_DECREF( py_param );
67                 return NULL;
68             }
69
70             for ( i_index = 0; i_index < i_size; i_index++ )
71             {
72                 ppsz_args[i_index] =
73                     strdup( PyString_AsString( PyObject_Str(
74                                                    PySequence_GetItem( py_param,
75                                                                        i_index ) ) ) );
76             }
77             ppsz_args[i_size] = NULL;
78             Py_DECREF( py_param );
79         }
80     }
81     else
82     {
83         /* No arguments were given. Clear the exception raised
84            by PyArg_ParseTuple. */
85         PyErr_Clear( );
86     }
87
88     Py_BEGIN_ALLOW_THREADS
89     MC_TRY;
90     if( p_instance )
91     {
92         self->mc = mediacontrol_new_from_instance( p_instance, exception );
93         Py_INCREF( py_param );
94         self->vlc_instance = ( vlcInstance* ) py_param;
95     }
96     else
97     {
98         self->mc = mediacontrol_new( i_size, ppsz_args, exception );
99         self->vlc_instance = PyObject_New( vlcInstance, &vlcInstance_Type );
100         self->vlc_instance->p_instance = mediacontrol_get_libvlc_instance( SELF->mc );
101     }
102     MC_EXCEPT;
103     Py_END_ALLOW_THREADS
104
105     Py_INCREF( self );
106     return ( PyObject * )self;
107 }
108
109 static void
110 MediaControl_dealloc( PyObject *self )
111 {
112     fprintf(stderr, "MC dealloc\n");
113     Py_DECREF( SELF->vlc_instance );
114     PyObject_DEL( self );
115 }
116
117 static PyObject *
118 MediaControl_get_vlc_instance( PyObject *self, PyObject *args )
119 {
120     vlcInstance *p_ret;
121
122     p_ret = SELF->vlc_instance;
123     Py_INCREF( p_ret );
124     return ( PyObject * )p_ret;
125 }
126
127 static PyObject *
128 MediaControl_get_mediaplayer( PyObject *self, PyObject *args )
129 {
130     vlcMediaPlayer *p_ret;
131
132     p_ret = PyObject_New( vlcMediaPlayer, &vlcMediaPlayer_Type );
133     p_ret->p_mp = mediacontrol_get_media_player( SELF->mc );
134     Py_INCREF( p_ret );
135     return ( PyObject * )p_ret;
136 }
137
138 /**
139  *  Return the current position in the stream. The returned value can
140    be relative or absolute ( according to PositionOrigin ) and the unit
141    is set by PositionKey
142  */
143 static PyObject *
144 MediaControl_get_media_position( PyObject *self, PyObject *args )
145 {
146     mediacontrol_Position* pos;
147     mediacontrol_Exception* exception = NULL;
148     PyObject *py_origin;
149     PyObject *py_key;
150     PyObject *py_retval;
151     mediacontrol_PositionOrigin origin;
152     mediacontrol_PositionKey key;
153
154     if( !PyArg_ParseTuple( args, "OO", &py_origin, &py_key ) )
155         return NULL;
156
157     origin = positionOrigin_py_to_c( py_origin );
158     key    = positionKey_py_to_c( py_key );
159
160     Py_BEGIN_ALLOW_THREADS
161     MC_TRY;
162     pos = mediacontrol_get_media_position( SELF->mc, origin, key, exception );
163     Py_END_ALLOW_THREADS
164     MC_EXCEPT;
165
166     py_retval = ( PyObject* )position_c_to_py( pos );
167     free( pos );
168     return py_retval;
169 }
170
171 /** Set the media position */
172 static PyObject *
173 MediaControl_set_media_position( PyObject *self, PyObject *args )
174 {
175     mediacontrol_Exception* exception = NULL;
176     mediacontrol_Position *a_position;
177     PyObject *py_pos;
178
179     if( !PyArg_ParseTuple( args, "O", &py_pos ) )
180         return NULL;
181
182     a_position = position_py_to_c( py_pos );
183     if( !a_position )
184     {
185         PyErr_SetString( PyExc_MemoryError, "Out of memory" );
186         return NULL;
187     }
188
189     Py_BEGIN_ALLOW_THREADS
190     MC_TRY;
191     mediacontrol_set_media_position( SELF->mc, a_position, exception );
192     free( a_position );
193     Py_END_ALLOW_THREADS
194     MC_EXCEPT;
195
196     Py_INCREF( Py_None );
197     return Py_None;
198 }
199
200 static PyObject *
201 MediaControl_start( PyObject *self, PyObject *args )
202 {
203     mediacontrol_Position *a_position;
204     mediacontrol_Exception *exception = NULL;
205     PyObject *py_pos;
206
207     if( !PyArg_ParseTuple( args, "O", &py_pos ) )
208     {
209         /* No argument. Use a default 0 value. */
210         PyErr_Clear( );
211         py_pos = NULL;
212     }
213     a_position = position_py_to_c( py_pos );
214     if( !a_position )
215         return NULL;
216
217     Py_BEGIN_ALLOW_THREADS
218     MC_TRY;
219     mediacontrol_start( SELF->mc, a_position, exception );
220     free( a_position );
221     Py_END_ALLOW_THREADS
222     MC_EXCEPT;
223
224     Py_INCREF( Py_None );
225     return Py_None;
226 }
227
228 static PyObject *
229 MediaControl_pause( PyObject *self, PyObject *args )
230 {
231     mediacontrol_Exception *exception = NULL;
232
233     Py_BEGIN_ALLOW_THREADS
234     MC_TRY;
235     mediacontrol_pause( SELF->mc, exception );
236     Py_END_ALLOW_THREADS
237     MC_EXCEPT;
238
239   Py_INCREF( Py_None );
240   return Py_None;
241 }
242
243 static PyObject *
244 MediaControl_resume( PyObject *self, PyObject *args )
245 {
246     mediacontrol_Exception *exception = NULL;
247
248     Py_BEGIN_ALLOW_THREADS
249     MC_TRY;
250     mediacontrol_resume( SELF->mc, exception );
251     Py_END_ALLOW_THREADS
252     MC_EXCEPT;
253
254     Py_INCREF( Py_None );
255     return Py_None;
256 }
257
258 static PyObject *
259 MediaControl_stop( PyObject *self, PyObject *args )
260 {
261     mediacontrol_Exception *exception = NULL;
262
263     Py_BEGIN_ALLOW_THREADS
264     MC_TRY;
265     mediacontrol_stop( SELF->mc, exception );
266     Py_END_ALLOW_THREADS
267     MC_EXCEPT;
268
269     Py_INCREF( Py_None );
270     return Py_None;
271 }
272
273 static PyObject *
274 MediaControl_exit( PyObject *self, PyObject *args )
275 {
276     mediacontrol_exit( SELF->mc );
277     Py_INCREF( Py_None );
278     return Py_None;
279 }
280
281 static PyObject *
282 MediaControl_set_mrl( PyObject *self, PyObject *args )
283 {
284     char *psz_file;
285     mediacontrol_Exception *exception = NULL;
286
287     if( !PyArg_ParseTuple( args, "s", &psz_file ) )
288       return NULL;
289
290     Py_BEGIN_ALLOW_THREADS
291     MC_TRY;
292     mediacontrol_set_mrl( SELF->mc, psz_file, exception );
293     Py_END_ALLOW_THREADS
294     MC_EXCEPT;
295
296     Py_INCREF( Py_None );
297     return Py_None;
298 }
299
300 static PyObject *
301 MediaControl_get_mrl( PyObject *self, PyObject *args )
302 {
303     PyObject *py_retval;
304     char* psz_file;
305     mediacontrol_Exception *exception = NULL;
306
307     Py_BEGIN_ALLOW_THREADS
308     MC_TRY;
309     psz_file = mediacontrol_get_mrl( SELF->mc, exception );
310     Py_END_ALLOW_THREADS
311     MC_EXCEPT;
312
313     py_retval = Py_BuildValue( "s", psz_file );
314     free( psz_file );
315     return py_retval;
316 }
317
318 static PyObject *
319 MediaControl_snapshot( PyObject *self, PyObject *args )
320 {
321     mediacontrol_RGBPicture *p_retval = NULL;
322     mediacontrol_Exception* exception = NULL;
323     mediacontrol_Position *a_position = NULL;
324     PyObject *py_pos = NULL;
325     PyObject *py_obj = NULL;
326
327     if( !PyArg_ParseTuple( args, "O", &py_pos ) )
328       return NULL;
329
330     a_position = position_py_to_c( py_pos );
331
332     Py_BEGIN_ALLOW_THREADS
333     MC_TRY;
334     p_retval = mediacontrol_snapshot( SELF->mc, a_position, exception );
335     free( a_position );
336     Py_END_ALLOW_THREADS
337     MC_EXCEPT;
338
339     if( !p_retval )
340     {
341         Py_INCREF( Py_None );
342         return Py_None;
343     }
344
345     /* FIXME: create a real RGBPicture object */
346     py_obj = PyDict_New();
347
348     PyDict_SetItemString( py_obj, "width",
349                           Py_BuildValue( "i", p_retval->width ) );
350     PyDict_SetItemString( py_obj, "height",
351                           Py_BuildValue( "i", p_retval->height ) );
352     PyDict_SetItemString( py_obj, "type",
353                           Py_BuildValue( "i", p_retval->type ) );
354     PyDict_SetItemString( py_obj, "data",
355                           Py_BuildValue( "s#", p_retval->data, p_retval->size ) );
356     PyDict_SetItemString( py_obj, "date",
357                           Py_BuildValue( "L", p_retval->date ) );
358
359     mediacontrol_RGBPicture__free( p_retval );
360
361     return py_obj;
362 }
363
364 static PyObject*
365 MediaControl_display_text( PyObject *self, PyObject *args )
366 {
367     mediacontrol_Exception* exception = NULL;
368     PyObject *py_begin, *py_end;
369     char* message;
370     mediacontrol_Position * begin;
371     mediacontrol_Position * end;
372
373     if( !PyArg_ParseTuple( args, "sOO", &message, &py_begin, &py_end ) )
374         return NULL;
375
376     begin = position_py_to_c( py_begin );
377     end   = position_py_to_c( py_end );
378
379     Py_BEGIN_ALLOW_THREADS
380     MC_TRY;
381     mediacontrol_display_text( SELF->mc, message, begin, end, exception );
382     Py_END_ALLOW_THREADS
383     MC_EXCEPT;
384
385     free( begin );
386     free( end );
387
388     Py_INCREF( Py_None );
389     return Py_None;
390 }
391
392 static PyObject*
393 MediaControl_get_stream_information( PyObject *self, PyObject *args )
394 {
395     mediacontrol_StreamInformation *retval  = NULL;
396     mediacontrol_Exception* exception = NULL;
397     PyObject *py_obj;
398
399     Py_BEGIN_ALLOW_THREADS
400     MC_TRY;
401     retval = mediacontrol_get_stream_information(
402         SELF->mc, mediacontrol_MediaTime, exception );
403     Py_END_ALLOW_THREADS
404     MC_EXCEPT;
405
406     py_obj = PyDict_New( );
407
408      /* FIXME: create a real StreamInformation object */
409     PyDict_SetItemString( py_obj, "status",
410                   Py_BuildValue( "i", retval->streamstatus ) );
411     PyDict_SetItemString( py_obj, "url",
412                   Py_BuildValue( "s", retval->url ) );
413     PyDict_SetItemString( py_obj, "position",
414                   Py_BuildValue( "L", retval->position ) );
415     PyDict_SetItemString( py_obj, "length",
416                   Py_BuildValue( "L", retval->length ) );
417
418     mediacontrol_StreamInformation__free( retval );
419
420     return py_obj;
421 }
422
423 static PyObject*
424 MediaControl_sound_set_volume( PyObject *self, PyObject *args )
425 {
426     mediacontrol_Exception* exception = NULL;
427     unsigned short volume;
428
429     if( !PyArg_ParseTuple( args, "H", &volume ) )
430         return NULL;
431
432     Py_BEGIN_ALLOW_THREADS
433     MC_TRY;
434     mediacontrol_sound_set_volume( SELF->mc, volume, exception );
435     Py_END_ALLOW_THREADS
436     MC_EXCEPT;
437
438     Py_INCREF( Py_None );
439     return Py_None;
440 }
441
442 static PyObject*
443 MediaControl_sound_get_volume( PyObject *self, PyObject *args )
444 {
445     mediacontrol_Exception* exception = NULL;
446     PyObject *py_retval;
447     unsigned short volume;
448
449     Py_BEGIN_ALLOW_THREADS
450     MC_TRY;
451     volume = mediacontrol_sound_get_volume( SELF->mc, exception );
452     Py_END_ALLOW_THREADS
453     MC_EXCEPT;
454
455     py_retval = Py_BuildValue( "H", volume );
456     return py_retval;
457 }
458
459 static PyObject*
460 MediaControl_set_rate( PyObject *self, PyObject *args )
461 {
462     mediacontrol_Exception* exception = NULL;
463     int rate;
464
465     if( !PyArg_ParseTuple( args, "i", &rate ) )
466         return NULL;
467
468     Py_BEGIN_ALLOW_THREADS
469     MC_TRY;
470     mediacontrol_set_rate( SELF->mc, rate, exception );
471     Py_END_ALLOW_THREADS
472     MC_EXCEPT;
473
474     Py_INCREF( Py_None );
475     return Py_None;
476 }
477
478 static PyObject*
479 MediaControl_get_rate( PyObject *self, PyObject *args )
480 {
481     mediacontrol_Exception* exception = NULL;
482     PyObject *py_retval;
483     int rate;
484
485     Py_BEGIN_ALLOW_THREADS
486     MC_TRY;
487     rate = mediacontrol_get_rate( SELF->mc, exception );
488     Py_END_ALLOW_THREADS
489     MC_EXCEPT;
490
491     py_retval = Py_BuildValue( "i", rate );
492     return py_retval;
493 }
494
495 static PyObject*
496 MediaControl_set_fullscreen( PyObject *self, PyObject *args )
497 {
498     mediacontrol_Exception* exception = NULL;
499     int fs;
500
501     if( !PyArg_ParseTuple( args, "i", &fs ) )
502         return NULL;
503
504     Py_BEGIN_ALLOW_THREADS
505     MC_TRY;
506     mediacontrol_set_fullscreen( SELF->mc, fs, exception );
507     Py_END_ALLOW_THREADS
508     MC_EXCEPT;
509
510     Py_INCREF( Py_None );
511     return Py_None;
512 }
513
514 static PyObject*
515 MediaControl_get_fullscreen( PyObject *self, PyObject *args )
516 {
517     mediacontrol_Exception* exception = NULL;
518     PyObject *py_retval;
519     int fs;
520
521     Py_BEGIN_ALLOW_THREADS
522     MC_TRY;
523     fs = mediacontrol_get_fullscreen( SELF->mc, exception );
524     Py_END_ALLOW_THREADS
525     MC_EXCEPT;
526
527     py_retval = Py_BuildValue( "i", fs );
528     return py_retval;
529 }
530
531 static PyObject*
532 MediaControl_set_visual( PyObject *self, PyObject *args )
533 {
534     mediacontrol_Exception* exception = NULL;
535     WINDOWHANDLE visual;
536
537     if( !PyArg_ParseTuple( args, "i", &visual ) )
538        return NULL;
539
540     Py_BEGIN_ALLOW_THREADS
541     MC_TRY;
542     mediacontrol_set_visual( SELF->mc, visual, exception );
543     Py_END_ALLOW_THREADS
544     MC_EXCEPT;
545
546     Py_INCREF( Py_None );
547     return Py_None;
548 }
549
550 static PyMethodDef MediaControl_methods[] =
551 {
552     { "get_vlc_instance", MediaControl_get_vlc_instance, METH_VARARGS,
553       "get_vlc_instance( ) -> Instance    Get embedded vlc.Instance." },
554     { "get_mediaplayer", MediaControl_get_mediaplayer, METH_VARARGS,
555       "get_mediaplayer( ) -> MediaPlayer    Get embedded vlc.MediaPlayer." },
556     { "get_media_position", MediaControl_get_media_position, METH_VARARGS,
557       "get_media_position( origin, key ) -> Position    Get current media position." },
558     { "set_media_position", MediaControl_set_media_position, METH_VARARGS,
559       "set_media_position( Position )            Set media position" },
560     { "start", MediaControl_start, METH_VARARGS,
561       "start( Position )         Start the player." },
562     { "pause", MediaControl_pause, METH_VARARGS,
563       "pause( Position )         Pause the player." },
564     { "resume", MediaControl_resume, METH_VARARGS,
565       "resume( Position )        Resume the player" },
566     { "stop", MediaControl_stop, METH_VARARGS,
567       "stop( Position )              Stop the player" },
568     { "exit", MediaControl_exit, METH_VARARGS,
569       "exit( )                     Exit the player" },
570     { "set_mrl", MediaControl_set_mrl, METH_VARARGS,
571       "set_mrl( str )               Set the file to be played" },
572     { "get_mrl", MediaControl_get_mrl, METH_VARARGS,
573       "get_mrl( ) -> str       Get the played file" },
574     { "snapshot", MediaControl_snapshot, METH_VARARGS,
575       "snapshot( Position ) -> dict        Take a snapshot" },
576     { "display_text", MediaControl_display_text, METH_VARARGS,
577       "display_text( str, Position, Position )    Display a text on the video" },
578     { "get_stream_information", MediaControl_get_stream_information,
579       METH_VARARGS,
580       "get_stream_information( ) -> dict      Get information about the stream"},
581     { "sound_get_volume", MediaControl_sound_get_volume, METH_VARARGS,
582       "sound_get_volume( ) -> int       Get the volume" },
583     { "sound_set_volume", MediaControl_sound_set_volume, METH_VARARGS,
584       "sound_set_volume( int )           Set the volume" },
585     { "set_visual", MediaControl_set_visual, METH_VARARGS,
586       "set_visual( int )           Set the embedding window visual ID" },
587     { "get_rate", MediaControl_get_rate, METH_VARARGS,
588       "get_rate( ) -> int       Get the rate" },
589     { "set_rate", MediaControl_set_rate, METH_VARARGS,
590       "set_rate( int )              Set the rate" },
591     { "get_fullscreen", MediaControl_get_fullscreen, METH_VARARGS,
592       "get_fullscreen( ) -> int       Get the fullscreen status" },
593     { "set_fullscreen", MediaControl_set_fullscreen, METH_VARARGS,
594       "set_fullscreen( int )              Set the fullscreen status" },
595     { NULL, NULL, 0, NULL },
596 };
597
598 static PyTypeObject MediaControl_Type =
599 {
600     PyObject_HEAD_INIT( NULL )
601     0,                         /*ob_size*/
602     "vlc.MediaControl",        /*tp_name*/
603     sizeof( MediaControl_Type ), /*tp_basicsize*/
604     0,                         /*tp_itemsize*/
605     ( destructor )MediaControl_dealloc,      /*tp_dealloc*/
606     0,                         /*tp_print*/
607     0,                         /*tp_getattr*/
608     0,                         /*tp_setattr*/
609     0,                         /*tp_compare*/
610     0,                         /*tp_repr*/
611     0,                         /*tp_as_number*/
612     0,                         /*tp_as_sequence*/
613     0,                         /*tp_as_mapping*/
614     0,                         /*tp_hash */
615     0,                         /*tp_call*/
616     0,                         /*tp_str*/
617     0,                         /*tp_getattro*/
618     0,                         /*tp_setattro*/
619     0,                         /*tp_as_buffer*/
620     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
621     "Control of a VLC instance.\n\nvlc.MediaControl(args): initialisation with a list of VLC parameters.\nvlc.MediaControl(instance): initialisation with an existing vlc.Instance",  /* tp_doc */
622     0,                     /* tp_traverse */
623     0,                     /* tp_clear */
624     0,                     /* tp_richcompare */
625     0,                     /* tp_weaklistoffset */
626     0,                     /* tp_iter */
627     0,                     /* tp_iternext */
628     MediaControl_methods,             /* tp_methods */
629     0,             /* tp_members */
630     0,                         /* tp_getset */
631     0,                         /* tp_base */
632     0,                         /* tp_dict */
633     0,                         /* tp_descr_get */
634     0,                         /* tp_descr_set */
635     0,                         /* tp_dictoffset */
636     0,                         /* tp_init */
637     0,                         /* tp_alloc */
638     MediaControl_new,          /* tp_new */
639 };