]> git.sesse.net Git - vlc/blob - bindings/python/vlc_mediacontrol.c
python bindings: use mediacontrol_StreamInformation__free + fix
[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     mediacontrol_RGBPicture__free( p_retval );
410
411     return py_obj;
412 }
413
414 static PyObject*
415 MediaControl_display_text( PyObject *self, PyObject *args )
416 {
417     mediacontrol_Exception* exception = NULL;
418     PyObject *py_begin, *py_end;
419     char* message;
420     mediacontrol_Position * begin;
421     mediacontrol_Position * end;
422
423     if( !PyArg_ParseTuple( args, "sOO", &message, &py_begin, &py_end ) )
424         return NULL;
425
426     begin = position_py_to_c( py_begin );
427     end   = position_py_to_c( py_end );
428
429     Py_BEGIN_ALLOW_THREADS
430     MC_TRY;
431     mediacontrol_display_text( SELF->mc, message, begin, end, exception );
432     Py_END_ALLOW_THREADS
433     MC_EXCEPT;
434
435     free( begin );
436     free( end );
437
438     Py_INCREF( Py_None );
439     return Py_None;
440 }
441
442 static PyObject*
443 MediaControl_get_stream_information( PyObject *self, PyObject *args )
444 {
445     mediacontrol_StreamInformation *retval  = NULL;
446     mediacontrol_Exception* exception = NULL;
447     PyObject *py_obj;
448
449     Py_BEGIN_ALLOW_THREADS
450     MC_TRY;
451     retval = mediacontrol_get_stream_information(
452         SELF->mc, mediacontrol_MediaTime, exception );
453     Py_END_ALLOW_THREADS
454     MC_EXCEPT;
455
456     py_obj = PyDict_New( );
457
458      /* FIXME: create a real StreamInformation object */
459     PyDict_SetItemString( py_obj, "status",
460                   Py_BuildValue( "i", retval->streamstatus ) );
461     PyDict_SetItemString( py_obj, "url",
462                   Py_BuildValue( "s", retval->url ) );
463     PyDict_SetItemString( py_obj, "position",
464                   Py_BuildValue( "L", retval->position ) );
465     PyDict_SetItemString( py_obj, "length",
466                   Py_BuildValue( "L", retval->length ) );
467
468     mediacontrol_StreamInformation__free( retval );
469
470     return py_obj;
471 }
472
473 static PyObject*
474 MediaControl_sound_set_volume( PyObject *self, PyObject *args )
475 {
476     mediacontrol_Exception* exception = NULL;
477     unsigned short volume;
478
479     if( !PyArg_ParseTuple( args, "H", &volume ) )
480         return NULL;
481
482     Py_BEGIN_ALLOW_THREADS
483     MC_TRY;
484     mediacontrol_sound_set_volume( SELF->mc, volume, exception );
485     Py_END_ALLOW_THREADS
486     MC_EXCEPT;
487
488     Py_INCREF( Py_None );
489     return Py_None;
490 }
491
492 static PyObject*
493 MediaControl_sound_get_volume( PyObject *self, PyObject *args )
494 {
495     mediacontrol_Exception* exception = NULL;
496     PyObject *py_retval;
497     unsigned short volume;
498
499     Py_BEGIN_ALLOW_THREADS
500     MC_TRY;
501     volume = mediacontrol_sound_get_volume( SELF->mc, exception );
502     Py_END_ALLOW_THREADS
503     MC_EXCEPT;
504
505     py_retval = Py_BuildValue( "H", volume );
506     return py_retval;
507 }
508
509 static PyObject*
510 MediaControl_set_rate( PyObject *self, PyObject *args )
511 {
512     mediacontrol_Exception* exception = NULL;
513     int rate;
514
515     if( !PyArg_ParseTuple( args, "i", &rate ) )
516         return NULL;
517
518     Py_BEGIN_ALLOW_THREADS
519     MC_TRY;
520     mediacontrol_set_rate( SELF->mc, rate, exception );
521     Py_END_ALLOW_THREADS
522     MC_EXCEPT;
523
524     Py_INCREF( Py_None );
525     return Py_None;
526 }
527
528 static PyObject*
529 MediaControl_get_rate( PyObject *self, PyObject *args )
530 {
531     mediacontrol_Exception* exception = NULL;
532     PyObject *py_retval;
533     int rate;
534
535     Py_BEGIN_ALLOW_THREADS
536     MC_TRY;
537     rate = mediacontrol_get_rate( SELF->mc, exception );
538     Py_END_ALLOW_THREADS
539     MC_EXCEPT;
540
541     py_retval = Py_BuildValue( "i", rate );
542     return py_retval;
543 }
544
545 static PyObject*
546 MediaControl_set_fullscreen( PyObject *self, PyObject *args )
547 {
548     mediacontrol_Exception* exception = NULL;
549     int fs;
550
551     if( !PyArg_ParseTuple( args, "i", &fs ) )
552         return NULL;
553
554     Py_BEGIN_ALLOW_THREADS
555     MC_TRY;
556     mediacontrol_set_fullscreen( SELF->mc, fs, exception );
557     Py_END_ALLOW_THREADS
558     MC_EXCEPT;
559
560     Py_INCREF( Py_None );
561     return Py_None;
562 }
563
564 static PyObject*
565 MediaControl_get_fullscreen( PyObject *self, PyObject *args )
566 {
567     mediacontrol_Exception* exception = NULL;
568     PyObject *py_retval;
569     int fs;
570
571     Py_BEGIN_ALLOW_THREADS
572     MC_TRY;
573     fs = mediacontrol_get_fullscreen( SELF->mc, exception );
574     Py_END_ALLOW_THREADS
575     MC_EXCEPT;
576
577     py_retval = Py_BuildValue( "i", fs );
578     return py_retval;
579 }
580
581 static PyObject*
582 MediaControl_set_visual( PyObject *self, PyObject *args )
583 {
584     mediacontrol_Exception* exception = NULL;
585     WINDOWHANDLE visual;
586
587     if( !PyArg_ParseTuple( args, "i", &visual ) )
588        return NULL;
589
590     Py_BEGIN_ALLOW_THREADS
591     MC_TRY;
592     mediacontrol_set_visual( SELF->mc, visual, exception );
593     Py_END_ALLOW_THREADS
594     MC_EXCEPT;
595
596     Py_INCREF( Py_None );
597     return Py_None;
598 }
599
600 static PyMethodDef MediaControl_methods[] =
601 {
602     { "get_vlc_instance", MediaControl_get_vlc_instance, METH_VARARGS,
603       "get_vlc_instance( ) -> Instance    Get matching vlc.Instance." },
604     { "get_media_position", MediaControl_get_media_position, METH_VARARGS,
605       "get_media_position( origin, key ) -> Position    Get current media position." },
606     { "set_media_position", MediaControl_set_media_position, METH_VARARGS,
607       "set_media_position( Position )            Set media position" },
608     { "start", MediaControl_start, METH_VARARGS,
609       "start( Position )         Start the player." },
610     { "pause", MediaControl_pause, METH_VARARGS,
611       "pause( Position )         Pause the player." },
612     { "resume", MediaControl_resume, METH_VARARGS,
613       "resume( Position )        Resume the player" },
614     { "stop", MediaControl_stop, METH_VARARGS,
615       "stop( Position )              Stop the player" },
616     { "exit", MediaControl_exit, METH_VARARGS,
617       "exit( )                     Exit the player" },
618     { "playlist_add_item", MediaControl_playlist_add_item, METH_VARARGS,
619       "playlist_add_item( str )               Add an item to the playlist" },
620     { "playlist_get_list", MediaControl_playlist_get_list, METH_VARARGS,
621       "playlist_get_list( ) -> list       Get the contents of the playlist" },
622     { "playlist_clear", MediaControl_playlist_clear, METH_VARARGS,
623       "clear( )         Clear the playlist." },
624     { "snapshot", MediaControl_snapshot, METH_VARARGS,
625       "snapshot( Position ) -> dict        Take a snapshot" },
626     { "display_text", MediaControl_display_text, METH_VARARGS,
627       "display_text( str, Position, Position )    Display a text on the video" },
628     { "get_stream_information", MediaControl_get_stream_information,
629       METH_VARARGS,
630       "get_stream_information( ) -> dict      Get information about the stream"},
631     { "sound_get_volume", MediaControl_sound_get_volume, METH_VARARGS,
632       "sound_get_volume( ) -> int       Get the volume" },
633     { "sound_set_volume", MediaControl_sound_set_volume, METH_VARARGS,
634       "sound_set_volume( int )           Set the volume" },
635     { "set_visual", MediaControl_set_visual, METH_VARARGS,
636       "set_visual( int )           Set the embedding window visual ID" },
637     { "get_rate", MediaControl_get_rate, METH_VARARGS,
638       "get_rate( ) -> int       Get the rate" },
639     { "set_rate", MediaControl_set_rate, METH_VARARGS,
640       "set_rate( int )              Set the rate" },
641     { "get_fullscreen", MediaControl_get_fullscreen, METH_VARARGS,
642       "get_fullscreen( ) -> int       Get the fullscreen status" },
643     { "set_fullscreen", MediaControl_set_fullscreen, METH_VARARGS,
644       "set_fullscreen( int )              Set the fullscreen status" },
645     { NULL, NULL, 0, NULL },
646 };
647
648 static PyTypeObject MediaControl_Type =
649 {
650     PyObject_HEAD_INIT( NULL )
651     0,                         /*ob_size*/
652     "vlc.MediaControl",        /*tp_name*/
653     sizeof( MediaControl_Type ), /*tp_basicsize*/
654     0,                         /*tp_itemsize*/
655     ( destructor )MediaControl_dealloc,      /*tp_dealloc*/
656     0,                         /*tp_print*/
657     0,                         /*tp_getattr*/
658     0,                         /*tp_setattr*/
659     0,                         /*tp_compare*/
660     0,                         /*tp_repr*/
661     0,                         /*tp_as_number*/
662     0,                         /*tp_as_sequence*/
663     0,                         /*tp_as_mapping*/
664     0,                         /*tp_hash */
665     0,                         /*tp_call*/
666     0,                         /*tp_str*/
667     0,                         /*tp_getattro*/
668     0,                         /*tp_setattro*/
669     0,                         /*tp_as_buffer*/
670     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
671     "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 */
672     0,                     /* tp_traverse */
673     0,                     /* tp_clear */
674     0,                     /* tp_richcompare */
675     0,                     /* tp_weaklistoffset */
676     0,                     /* tp_iter */
677     0,                     /* tp_iternext */
678     MediaControl_methods,             /* tp_methods */
679     0,             /* tp_members */
680     0,                         /* tp_getset */
681     0,                         /* tp_base */
682     0,                         /* tp_dict */
683     0,                         /* tp_descr_get */
684     0,                         /* tp_descr_set */
685     0,                         /* tp_dictoffset */
686     0,                         /* tp_init */
687     0,                         /* tp_alloc */
688     MediaControl_new,          /* tp_new */
689 };