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