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