]> git.sesse.net Git - vlc/blob - bindings/python/vlcglue.c
python/vlcglue.c: exception-related code fixes
[vlc] / bindings / python / vlcglue.c
1 /*****************************************************************************
2  * vlcglue.c: VLC Module
3  *****************************************************************************
4  * Copyright (C) 1998-2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Olivier Aubert <oaubert at bat710.univ-lyon1.fr>
8  *          ClĂ©ment Stenac <zorglub@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24 #include "vlcglue.h"
25
26 /**************************************************************************
27  * VLC Module
28  **************************************************************************/
29
30 #ifndef vlcMODINIT_FUNC /* declarations for DLL import/export */
31 #define vlcMODINIT_FUNC void
32 #endif
33
34 static PyMethodDef vlc_methods[] = {
35     {NULL}  /* Sentinel */
36 };
37
38 /* Module globals */
39 PyObject* MediaControl_InternalException          = NULL;
40 PyObject* MediaControl_PositionKeyNotSupported    = NULL;
41 PyObject *MediaControl_PositionOriginNotSupported = NULL;
42 PyObject* MediaControl_InvalidPosition            = NULL;
43 PyObject *MediaControl_PlaylistException          = NULL;
44
45 vlcMODINIT_FUNC  initvlc(void)
46 {
47     PyObject* m;
48
49     PyPosition_Type.tp_new = PyType_GenericNew;
50     PyPosition_Type.tp_alloc = PyType_GenericAlloc;
51
52         /*  PyEval_InitThreads(); */
53
54         /* Have a look at
55 http://base.bel-epa.com/pyapache/Python/MySQL-python/MySQL-python-0.3.0/_mysqlmodule.c */
56
57     m = Py_InitModule3( "vlc", vlc_methods,
58                         "VLC media player embedding module.");
59  
60     if (! m)
61       return;
62
63     if (PyType_Ready(&PyPosition_Type) < 0)
64         return;
65     if (PyType_Ready(&MediaControl_Type) < 0)
66         return;
67 #ifdef VLCOBJECT_SUPPORT
68     if (PyType_Ready(&vlcObject_Type) < 0)
69         return;
70 #endif
71
72     /* Exceptions */
73     MediaControl_InternalException =
74             PyErr_NewException("vlc.InternalException", NULL, NULL);
75     Py_INCREF(MediaControl_InternalException);
76     PyModule_AddObject(m, "InternalException", MediaControl_InternalException);
77
78     MediaControl_PositionKeyNotSupported =
79             PyErr_NewException("vlc.PositionKeyNotSupported", NULL, NULL);
80     Py_INCREF(MediaControl_PositionKeyNotSupported);
81     PyModule_AddObject(m, "PositionKeyNotSupported",
82                     MediaControl_PositionKeyNotSupported);
83
84     MediaControl_PositionOriginNotSupported=
85             PyErr_NewException("vlc.InvalidPosition", NULL, NULL);
86     Py_INCREF(MediaControl_PositionOriginNotSupported);
87     PyModule_AddObject(m, "PositionOriginNotSupported",
88                     MediaControl_PositionOriginNotSupported);
89
90     MediaControl_InvalidPosition =
91             PyErr_NewException("vlc.InvalidPosition", NULL, NULL);
92     Py_INCREF(MediaControl_InvalidPosition);
93     PyModule_AddObject(m, "InvalidPosition", MediaControl_InvalidPosition);
94
95     MediaControl_PlaylistException =
96             PyErr_NewException("vlc.PlaylistException", NULL, NULL);
97     Py_INCREF(MediaControl_PlaylistException);
98     PyModule_AddObject(m, "PlaylistException", MediaControl_PlaylistException);
99
100     /* Types */
101     Py_INCREF(&PyPosition_Type);
102     PyModule_AddObject(m, "Position", (PyObject *)&PyPosition_Type);
103
104     Py_INCREF(&MediaControl_Type);
105     PyModule_AddObject(m, "MediaControl", (PyObject *)&MediaControl_Type);
106
107 #ifdef VLCOBJECT_SUPPORT
108     Py_INCREF(&vlcObject_Type);
109     PyModule_AddObject(m, "Object", (PyObject *)&vlcObject_Type);
110 #endif
111
112     /* Constants */
113     PyModule_AddIntConstant(m, "AbsolutePosition",
114                     mediacontrol_AbsolutePosition);
115     PyModule_AddIntConstant(m, "RelativePosition",
116                     mediacontrol_RelativePosition);
117     PyModule_AddIntConstant(m, "ModuloPosition",
118                     mediacontrol_ModuloPosition);
119
120     PyModule_AddIntConstant(m, "ByteCount",        mediacontrol_ByteCount);
121     PyModule_AddIntConstant(m, "SampleCount",      mediacontrol_SampleCount);
122     PyModule_AddIntConstant(m, "MediaTime",        mediacontrol_MediaTime);
123     PyModule_AddIntConstant(m, "PlayingStatus",    mediacontrol_PlayingStatus);
124     PyModule_AddIntConstant(m, "PauseStatus", mediacontrol_PauseStatus);
125     PyModule_AddIntConstant(m, "ForwardStatus", mediacontrol_ForwardStatus);
126     PyModule_AddIntConstant(m, "BackwardStatus", mediacontrol_BackwardStatus);
127     PyModule_AddIntConstant(m, "InitStatus", mediacontrol_InitStatus);
128     PyModule_AddIntConstant(m, "EndStatus", mediacontrol_EndStatus);
129     PyModule_AddIntConstant(m, "UndefinedStatus", mediacontrol_UndefinedStatus);
130 }
131
132
133 /* Make libpostproc happy... */
134 void * fast_memcpy(void * to, const void * from, size_t len)
135 {
136   return memcpy(to, from, len);
137 }
138
139
140 /*****************************************************************************
141  * VLCObject implementation
142  *****************************************************************************/
143
144 #ifdef VLCOBJECT_SUPPORT
145
146 static PyObject *vlcObject_new(
147                 PyTypeObject *type, PyObject *args, PyObject *kwds)
148 {
149     vlcObject *self;
150     vlc_object_t *p_object;
151     int i_id;
152
153     self = PyObject_New(vlcObject, &vlcObject_Type);
154
155     if ( !PyArg_ParseTuple(args, "i", &i_id) )
156       return NULL;
157
158     /* Maybe we were already initialized */
159     p_object = (vlc_object_t*)vlc_current_object(i_id);
160
161     if (! p_object)
162     {
163         /* Try to initialize */
164         i_id = VLC_Create();
165         p_object = (vlc_object_t*)vlc_current_object(i_id);
166     }
167
168     if (! p_object)
169     {
170         PyErr_SetString(PyExc_StandardError, "Unable to get object.");
171         return NULL;
172     }
173
174     self->p_object = p_object;
175     self->b_released = 0;
176
177     Py_INCREF( self ); /* Ah bon ? */
178     return (PyObject *)self;
179 }
180
181 static PyObject * vlcObject_release( PyObject *self )
182 {
183     if( VLCSELF->b_released == 0 )
184     {
185         vlc_object_release( VLCSELF->p_object );
186         VLCSELF->b_released = 1;
187     }
188     Py_INCREF( Py_None);
189     return Py_None;
190 }
191
192 static void  vlcObject_dealloc(PyObject *self)
193 {
194     vlcObject_release( self );
195     PyMem_DEL(self);
196 }
197
198 static PyObject * vlcObject_find_object(PyObject *self, PyObject *args)
199 {
200     vlcObject *retval;
201     vlc_object_t *p_obj;
202     char *psz_name;
203     int i_object_type;
204
205     if ( !PyArg_ParseTuple(args, "s", &psz_name) )
206       return NULL;
207
208     /* psz_name is in
209        (aout, decoder, input, httpd, intf, playlist, root, vlc, vout)
210     */
211     switch (psz_name[0])
212     {
213         case 'a':
214             i_object_type = VLC_OBJECT_AOUT;
215             break;
216         case 'd':
217             i_object_type = VLC_OBJECT_DECODER;
218             break;
219         case 'h':
220             i_object_type = VLC_OBJECT_HTTPD;
221             break;
222         case 'i':
223             if (strlen(psz_name) < 3)
224                     i_object_type = VLC_OBJECT_INTF;
225             else if (psz_name[2] == 't')
226                     i_object_type = VLC_OBJECT_INTF;
227             else
228                     i_object_type = VLC_OBJECT_INPUT;
229             break;
230         case 'p':
231             i_object_type = VLC_OBJECT_PLAYLIST;
232             break;
233         case 'r':
234             i_object_type = VLC_OBJECT_ROOT;
235             break;
236         case 'v':
237             if (strlen(psz_name) < 3)
238                     i_object_type = VLC_OBJECT_VLC;
239             else if (psz_name[1] == 'l')
240                     i_object_type = VLC_OBJECT_VLC;
241             else
242                     i_object_type = VLC_OBJECT_VOUT;
243             break;
244         default:
245             /* FIXME: raise an exception */
246             return Py_None;
247     }
248
249     p_obj = vlc_object_find( VLCSELF->p_object, i_object_type, FIND_ANYWHERE );
250
251     if (! p_obj)
252     {
253         Py_INCREF(Py_None);
254         return Py_None;
255     }
256
257     retval = PyObject_New(vlcObject, &vlcObject_Type);
258
259     retval->p_object = p_obj;
260
261     return (PyObject *)retval;
262 }
263
264 static PyObject * vlcObject_info(PyObject *self, PyObject *args)
265 {
266     PyObject *retval;
267     vlc_object_t *p_obj;
268
269     p_obj = VLCSELF->p_object;
270
271     /* Return information about the object as a dict. */
272     retval = PyDict_New();
273
274     PyDict_SetItemString(retval, "object-id",
275                     Py_BuildValue("l", p_obj->i_object_id));
276     PyDict_SetItemString(retval, "object-type",
277                   Py_BuildValue("s", p_obj->psz_object_type));
278     PyDict_SetItemString(retval, "object-name",
279                   Py_BuildValue("s", p_obj->psz_object_name));
280     PyDict_SetItemString(retval, "thread",
281                   PyBool_FromLong(p_obj->b_thread));
282     PyDict_SetItemString(retval, "thread-id",
283                   PyLong_FromLongLong(p_obj->thread_id));
284     PyDict_SetItemString(retval, "refcount",
285                   PyInt_FromLong(p_obj->i_refcount));
286
287     return retval;
288 }
289
290 static PyObject * vlcObject_find_id(PyObject *self, PyObject *args)
291 {
292     vlcObject *retval;
293     vlc_object_t* p_object;
294     int i_id;
295
296     if ( !PyArg_ParseTuple(args, "i", &i_id) )
297         return NULL;
298
299     p_object = (vlc_object_t*)vlc_current_object(i_id);
300
301     if (! p_object)
302     {
303         Py_INCREF(Py_None);
304         return Py_None;
305     }
306
307     retval = PyObject_NEW(vlcObject, &vlcObject_Type);
308
309     retval->p_object = p_object;
310
311     return (PyObject *)retval;
312 }
313
314 /* Do a var_Get call on the object. Parameter: the variable name. */
315 /* FIXME: We should make them attributes */
316 static PyObject * vlcObject_var_get(PyObject *self, PyObject *args)
317 {
318     PyObject *retval;
319     vlc_value_t value;
320     char *psz_name;
321     int i_type;
322
323     if ( !PyArg_ParseTuple(args, "s", &psz_name) )
324         return NULL;
325
326     if( var_Get( VLCSELF->p_object, psz_name, &value ) != VLC_SUCCESS )
327     {
328             PyErr_SetString(PyExc_StandardError, "Error: no variable name was given.\n");
329             return NULL;
330     }
331
332     i_type = var_Type (VLCSELF->p_object, psz_name);
333
334     switch (i_type)
335     {
336             case VLC_VAR_VOID   :
337                     retval = PyString_FromString("A void variable");
338                     break;
339             case VLC_VAR_BOOL      :
340                     retval = PyBool_FromLong(value.b_bool);
341                     break;
342             case VLC_VAR_INTEGER   :
343                     retval = PyInt_FromLong((long)value.i_int);
344                     break;
345             case VLC_VAR_HOTKEY   :
346                     retval = PyString_FromFormat("A hotkey variable (%d)", value.i_int);
347                     break;
348             case VLC_VAR_FILE      :
349             case VLC_VAR_STRING    :
350             case VLC_VAR_DIRECTORY :
351             case VLC_VAR_VARIABLE  :
352                     retval = PyString_FromString(value.psz_string);
353                     break;
354             case VLC_VAR_MODULE   :
355                     retval = (PyObject*)PyObject_New(vlcObject, &vlcObject_Type);
356                     ((vlcObject*)retval)->p_object = value.p_object;
357                     break;
358             case VLC_VAR_FLOAT     :
359                     retval = PyFloat_FromDouble((double)value.f_float);
360                     break;
361             case VLC_VAR_TIME      :
362                     retval = PyLong_FromLongLong(value.i_time);
363                     break;
364             case VLC_VAR_ADDRESS   :
365                     retval = PyString_FromString("A VLC address (not handled yet)");
366                     break;
367             case VLC_VAR_LIST      :
368                     retval = PyString_FromString("A VLC list (not handled yet)");
369                     break;
370             case VLC_VAR_MUTEX :
371                     retval = PyString_FromString("A mutex");
372                     break;
373             default:
374                     retval = Py_None;
375     }
376
377     Py_INCREF(retval);
378     return retval;
379 }
380
381 static PyObject * vlcObject_var_type(PyObject *self,
382                 PyObject *args)
383 {
384         char *psz_name;
385         PyObject *retval;
386         int i_type;
387
388         if ( !PyArg_ParseTuple(args, "s", &psz_name))
389             return NULL;
390
391         i_type = var_Type(VLCSELF->p_object, psz_name);
392
393         switch (i_type)
394         {
395                 case VLC_VAR_VOID   :
396                         retval = PyString_FromString("Void");
397                         break;
398                 case VLC_VAR_BOOL      :
399                         retval = PyString_FromString("Boolean");
400                         break;
401                 case VLC_VAR_INTEGER   :
402                         retval = PyString_FromString("Integer");
403                         break;
404                 case VLC_VAR_HOTKEY   :
405                         retval = PyString_FromString("Hotkey");
406                         break;
407                 case VLC_VAR_FILE      :
408                         retval = PyString_FromString("File");
409                         break;
410                 case VLC_VAR_STRING    :
411                         retval = PyString_FromString("String");
412                         break;
413                 case VLC_VAR_DIRECTORY :
414                         retval = PyString_FromString("Directory");
415                         break;
416                 case VLC_VAR_VARIABLE  :
417                         retval = PyString_FromString("Variable");
418                         break;
419                 case VLC_VAR_MODULE   :
420                         retval = PyString_FromString("Module");
421                         break;
422                 case VLC_VAR_FLOAT     :
423                         retval = PyString_FromString("Float");
424                         break;
425                 case VLC_VAR_TIME      :
426                         retval = PyString_FromString("Time");
427                         break;
428                 case VLC_VAR_ADDRESS   :
429                         retval = PyString_FromString("Address");
430                         break;
431                 case VLC_VAR_LIST      :
432                         retval = PyString_FromString("List");
433                         break;
434                 case VLC_VAR_MUTEX :
435                         retval = PyString_FromString("Mutex");
436                         break;
437                 default:
438                         retval = PyString_FromString("Unknown");
439         }
440         return retval;
441 }
442
443 /* Do a var_Set call on the object. Parameter: the variable name. */
444 /* FIXME: We should make them attributes */
445 static PyObject * vlcObject_var_set(PyObject *self,
446                 PyObject *args)
447 {
448         vlc_value_t value;
449         char *psz_name;
450         PyObject *py_value;
451         int i_type;
452         vlc_object_t *p_obj;
453
454         if ( !PyArg_ParseTuple(args, "sO", &psz_name, &py_value) )
455             return NULL;
456
457         p_obj = VLCSELF->p_object;
458         i_type = var_Type(p_obj, psz_name);
459
460         switch (i_type)
461         {
462                 case VLC_VAR_VOID   :
463                         break;
464                 case VLC_VAR_BOOL      :
465                         value.b_bool = PyInt_AsLong(py_value);
466                         break;
467                 case VLC_VAR_INTEGER   :
468                 case VLC_VAR_HOTKEY   :
469                         value.i_int = PyInt_AsLong(py_value);
470                         break;
471                 case VLC_VAR_FILE      :
472                 case VLC_VAR_STRING    :
473                 case VLC_VAR_DIRECTORY :
474                 case VLC_VAR_VARIABLE  :
475                         value.psz_string = strdup(PyString_AsString(py_value));
476                         break;
477                 case VLC_VAR_MODULE   :
478                         /* FIXME: we should check the PyObject type and get its p_object */
479                         value.p_object = ((vlcObject*)p_obj)->p_object;
480                         break;
481                 case VLC_VAR_FLOAT     :
482                         value.f_float = PyFloat_AsDouble(py_value);
483                         break;
484                 case VLC_VAR_TIME      :
485                         value.i_time = PyLong_AsLongLong(py_value);
486                         break;
487                 case VLC_VAR_ADDRESS   :
488                         value.p_address = (char*)PyLong_AsVoidPtr(py_value);
489                         break;
490                 case VLC_VAR_LIST      :
491                         /* FIXME */
492                         value.p_list = NULL;
493                         break;
494                 case VLC_VAR_MUTEX :
495                         break;
496         }
497
498         var_Set(p_obj, psz_name, value);
499
500         Py_INCREF(Py_None);
501         return Py_None;
502 }
503
504 static PyObject * vlcObject_var_list(PyObject *self,
505                 PyObject *args)
506 {
507         PyObject *retval;
508         int i_size;
509         int i_index;
510
511         i_size = VLCSELF->p_object->i_vars;
512         retval = PyTuple_New(i_size);
513
514         for (i_index = 0 ; i_index < i_size ; i_index++)
515         {
516                 PyTuple_SetItem(retval, i_index, 
517                                 Py_BuildValue("s", VLCSELF->p_object->p_vars[i_index].psz_name));
518         }
519
520         /* Py_INCREF(retval); */
521         return retval;
522 }
523
524 /* Do a config_Get call on the object. Parameter: the variable name. */
525 static PyObject * vlcObject_config_get(PyObject *self,
526                 PyObject *args)
527 {
528         PyObject *retval;
529         vlc_value_t value;
530         char *psz_name;
531         module_config_t *p_config;
532
533         if ( !PyArg_ParseTuple(args, "s", &psz_name) )
534             return NULL;
535
536         p_config = config_FindConfig( VLCSELF->p_object, psz_name );
537
538         if( !p_config )
539         {
540                 PyErr_SetString(PyExc_StandardError, "Error: config variable does not exist.\n");
541                 Py_INCREF(Py_None);
542                 return Py_None;
543         }
544
545         switch (p_config->i_type)
546         {
547                 case CONFIG_ITEM_BOOL      :
548                         retval = PyBool_FromLong(p_config->i_value);
549                         break;
550                 case CONFIG_ITEM_INTEGER   :
551                         retval = PyInt_FromLong((long)p_config->i_value);
552                         break;
553                 case CONFIG_ITEM_KEY   :
554                         retval = PyString_FromFormat("A hotkey variable (%d)", p_config->i_value);
555                         break;
556                 case CONFIG_ITEM_FILE      :
557                 case CONFIG_ITEM_STRING    :
558                 case CONFIG_ITEM_DIRECTORY :
559                 case CONFIG_ITEM_MODULE    :
560                         vlc_mutex_lock( p_config->p_lock );
561                         if( p_config->psz_value )
562                                 retval = PyString_FromString( p_config->psz_value );
563                         else
564                                 retval = PyString_FromString( "" );
565                         vlc_mutex_unlock( p_config->p_lock );
566                         break;
567                         retval = (PyObject*)PyObject_New(vlcObject, &vlcObject_Type);
568                         ((vlcObject*)retval)->p_object = value.p_object;
569                         break;
570                 case CONFIG_ITEM_FLOAT     :
571                         retval = PyFloat_FromDouble((double)p_config->f_value);
572                         break;
573                 default:
574                         retval = Py_None;
575                         Py_INCREF(retval);
576         }
577
578         return retval;
579 }
580
581 /* Do a var_Set call on the object. Parameter: the variable name. */
582 /* FIXME: We should make them attributes */
583 static PyObject * vlcObject_config_set(PyObject *self,
584                 PyObject *args)
585 {
586         char *psz_name;
587         PyObject *py_value;
588         vlc_object_t *p_obj;
589         module_config_t *p_config;
590
591
592         if ( !PyArg_ParseTuple(args, "sO", &psz_name, &py_value) )
593             return NULL;
594
595         p_obj = VLCSELF->p_object;
596         p_config = config_FindConfig( p_obj, psz_name );
597         /* sanity checks */
598         if( !p_config )
599         {
600             PyErr_SetString(PyExc_StandardError,
601                             "Error: option does not exist.\n");
602             Py_INCREF(Py_None);
603             return Py_None;
604         }
605
606         switch (p_config->i_type)
607         {
608                 case CONFIG_ITEM_BOOL      :
609                 case CONFIG_ITEM_INTEGER   :
610                 case CONFIG_ITEM_KEY       :
611                         config_PutInt(p_obj, psz_name, PyInt_AsLong(py_value));
612                         break;
613                 case CONFIG_ITEM_FILE      :
614                 case CONFIG_ITEM_STRING    :
615                 case CONFIG_ITEM_DIRECTORY :
616                 case CONFIG_ITEM_MODULE   :
617                         config_PutPsz(p_obj, psz_name, PyString_AsString(py_value));
618                         break;
619                 case CONFIG_ITEM_FLOAT     :
620                         config_PutFloat(p_obj, psz_name, PyFloat_AsDouble(py_value));
621                         break;
622         }
623         Py_INCREF(Py_None);
624         return Py_None;
625 }
626
627 static PyObject * vlcObject_children(PyObject *self,
628                 PyObject *args)
629 {
630         PyObject *retval;
631         int i_size;
632         int i_index;
633
634         i_size = VLCSELF->p_object->i_children;
635         retval = PyTuple_New(i_size);
636
637         for (i_index = 0 ; i_index < i_size ; i_index++)
638         {
639             PyTuple_SetItem(retval, i_index,
640                  Py_BuildValue("i",
641                       VLCSELF->p_object->pp_children[i_index]->i_object_id));
642         }
643
644         /* Py_INCREF(retval); */
645         return retval;
646 }
647
648
649 /* Method table */
650 static PyMethodDef vlcObject_methods[] =
651 {
652     { "get", vlcObject_var_get, METH_VARARGS,
653       "get(str) -> value   Get a variable value."},
654     { "set", vlcObject_var_set, METH_VARARGS,
655       "set(str, value)     Set a variable value" },
656     { "config_get", vlcObject_config_get, METH_VARARGS,
657       "config_get(str) -> value   Get a configuration option." },
658     { "config_set", vlcObject_config_set, METH_VARARGS,
659       "config_set(str, value)     Set a configuration option" },
660     { "type", vlcObject_var_type, METH_VARARGS,
661       "type(str) -> str     Get a variable type" },
662     { "list", vlcObject_var_list, METH_VARARGS,
663       "list()             List the available variables" },
664     { "children", vlcObject_children, METH_VARARGS,
665       "children()             List the children ids" },
666     { "find_object", vlcObject_find_object, METH_VARARGS,
667       "find_object(str) -> Object     Find the object of a given type.\n\nAvailable types are : aout, decoder, input, httpd, intf, playlist, root, vlc, vout"},
668     { "find_id", vlcObject_find_id, METH_VARARGS,
669       "find_id(int) -> Object      Find an object by id" },
670     { "info", vlcObject_info, METH_VARARGS,
671        "info() -> dict    Return information about the object" },
672     { "release", vlcObject_release, METH_VARARGS,
673       "release() ->     Release the VLC Object" },
674     { NULL, NULL, 0, NULL },
675 };
676
677 static PyTypeObject vlcObject_Type =
678 {
679     PyObject_HEAD_INIT(NULL)
680     0,                         /*ob_size*/
681     "vlc.Object",       /*tp_name*/
682     sizeof(vlcObject_Type), /*tp_basicsize*/
683     0,                         /*tp_itemsize*/
684     (destructor)vlcObject_dealloc,      /*tp_dealloc*/
685     0,                         /*tp_print*/
686     0,                         /*tp_getattr*/
687     0,                         /*tp_setattr*/
688     0,                         /*tp_compare*/
689     0,                         /*tp_repr*/
690     0,                         /*tp_as_number*/
691     0,                         /*tp_as_sequence*/
692     0,                         /*tp_as_mapping*/
693     0,                         /*tp_hash */
694     0,                         /*tp_call*/
695     0,                         /*tp_str*/
696     0,                         /*tp_getattro*/
697     0,                         /*tp_setattro*/
698     0,                         /*tp_as_buffer*/
699     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
700     "Explore VLC objects.",  /* tp_doc */
701     0,                     /* tp_traverse */
702     0,                     /* tp_clear */
703     0,                     /* tp_richcompare */
704     0,                     /* tp_weaklistoffset */
705     0,                     /* tp_iter */
706     0,                     /* tp_iternext */
707     vlcObject_methods,             /* tp_methods */
708     0,             /* tp_members */
709     0,                         /* tp_getset */
710     0,                         /* tp_base */
711     0,                         /* tp_dict */
712     0,                         /* tp_descr_get */
713     0,                         /* tp_descr_set */
714     0,                         /* tp_dictoffset */
715     0,                         /* tp_init */
716     0,                         /* tp_alloc */
717     vlcObject_new,          /* tp_new */
718 };
719
720 #endif
721
722
723 /*****************************************************************************
724  * VLC MediaControl object implementation
725  *****************************************************************************/
726
727 static PyObject *MediaControl_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
728 {
729     MediaControl *self;
730     mediacontrol_Exception *exception = NULL;
731     PyObject* py_list = NULL;
732     char** ppsz_args = NULL;
733
734     self = PyObject_New(MediaControl, &MediaControl_Type);
735
736     if (PyArg_ParseTuple(args, "O", &py_list))
737     {
738         int i_size;
739         int i_index;
740
741         Py_INCREF(py_list);
742         if (! PySequence_Check(py_list))
743         {
744             PyErr_SetString(PyExc_TypeError, "Parameter must be a sequence.");
745             return NULL;
746         }
747         i_size = PySequence_Size(py_list);
748         ppsz_args = malloc(i_size + 1);
749         if (! ppsz_args)
750         {
751             PyErr_SetString(PyExc_MemoryError, "Out of memory");
752             return NULL;
753         }
754
755         for ( i_index = 0; i_index < i_size; i_index++ )
756         {
757             ppsz_args[i_index] =
758                strdup( PyString_AsString( PyObject_Str(
759                                                PySequence_GetItem(py_list,
760                                                     i_index ) ) ) );
761         }
762         ppsz_args[i_size] = NULL;
763         Py_DECREF(py_list);
764     }
765     else
766     {
767         /* No arguments were given. Clear the exception raised
768            by PyArg_ParseTuple. */
769         PyErr_Clear();
770     }
771
772     Py_BEGIN_ALLOW_THREADS
773     MC_TRY;
774     self->mc = mediacontrol_new( ppsz_args, exception );
775     MC_EXCEPT;
776     Py_END_ALLOW_THREADS
777
778     Py_INCREF(self);
779     return (PyObject *)self;
780 }
781
782 static void MediaControl_dealloc(PyObject *self)
783 {
784     PyMem_DEL(self);
785 }
786
787 /**
788  *  Returns the current position in the stream. The returned value can
789    be relative or absolute (according to PositionOrigin) and the unit
790    is set by PositionKey
791  */
792 static PyObject * MediaControl_get_media_position(
793                                       PyObject *self, PyObject *args)
794 {
795     mediacontrol_Position* pos;
796     mediacontrol_Exception* exception = NULL;
797     PyObject *py_origin;
798     PyObject *py_key;
799     PyObject *py_retval;
800     mediacontrol_PositionOrigin origin;
801     mediacontrol_PositionKey key;
802
803     if( !PyArg_ParseTuple( args, "OO", &py_origin, &py_key ) )
804         return NULL;
805
806     origin = positionOrigin_py_to_c(py_origin);
807     key    = positionKey_py_to_c(py_key);
808
809     Py_BEGIN_ALLOW_THREADS
810     MC_TRY;
811     pos = mediacontrol_get_media_position(SELF->mc, origin, key, exception);
812     Py_END_ALLOW_THREADS
813     MC_EXCEPT;
814
815     py_retval = (PyObject*)position_c_to_py(pos);
816     free( pos );
817     return py_retval;
818 }
819
820 /** Sets the media position */
821 static PyObject *MediaControl_set_media_position(
822                                         PyObject *self, PyObject *args )
823 {
824     mediacontrol_Exception* exception = NULL;
825     mediacontrol_Position *a_position;
826     PyObject *py_pos;
827
828     if( !PyArg_ParseTuple( args, "O", &py_pos ) )
829         return NULL;
830
831     a_position = position_py_to_c(py_pos);
832     if (!a_position )
833     {
834         PyErr_SetString(PyExc_MemoryError, "Out of memory");
835         return NULL;
836     }
837
838     Py_BEGIN_ALLOW_THREADS
839     MC_TRY;
840     mediacontrol_set_media_position( SELF->mc, a_position, exception );
841     free( a_position );
842     Py_END_ALLOW_THREADS
843     MC_EXCEPT;
844
845     Py_INCREF(Py_None);
846     return Py_None;
847 }
848
849 static PyObject *MediaControl_start(PyObject *self, PyObject *args)
850 {
851     mediacontrol_Position *a_position;
852     mediacontrol_Exception *exception = NULL;
853     PyObject *py_pos;
854
855     if( !PyArg_ParseTuple(args, "O", &py_pos ) )
856         return NULL;
857
858     a_position = position_py_to_c(py_pos);
859     if ( !a_position )
860         return NULL;
861
862     Py_BEGIN_ALLOW_THREADS
863     MC_TRY;
864     mediacontrol_start(SELF->mc, a_position, exception);
865     free(a_position);
866     Py_END_ALLOW_THREADS
867     MC_EXCEPT;
868
869     Py_INCREF(Py_None);
870     return Py_None;
871 }
872
873 static PyObject *MediaControl_pause(PyObject *self, PyObject *args)
874 {
875     mediacontrol_Position *a_position;
876     mediacontrol_Exception *exception = NULL;
877     PyObject *py_pos;
878
879     if( !PyArg_ParseTuple(args, "O", &py_pos ) )
880         return NULL;
881
882     a_position = position_py_to_c(py_pos);
883
884     Py_BEGIN_ALLOW_THREADS
885     MC_TRY;
886     mediacontrol_pause(SELF->mc, a_position, exception);
887     free(a_position);
888     Py_END_ALLOW_THREADS
889     MC_EXCEPT;
890
891   Py_INCREF( Py_None );
892   return Py_None;
893 }
894
895 static PyObject * MediaControl_resume(PyObject *self, PyObject *args)
896 {
897     mediacontrol_Position *a_position;
898     mediacontrol_Exception *exception = NULL;
899     PyObject *py_pos;
900
901     if( !PyArg_ParseTuple(args, "O", &py_pos ) )
902         return NULL;
903
904     a_position = position_py_to_c(py_pos);
905
906     Py_BEGIN_ALLOW_THREADS
907     MC_TRY;
908     mediacontrol_start(SELF->mc, a_position, exception);
909     free(a_position);
910     Py_END_ALLOW_THREADS
911     MC_EXCEPT;
912
913     Py_INCREF(Py_None);
914     return Py_None;
915 }
916
917 static PyObject *MediaControl_stop(PyObject *self, PyObject *args)
918 {
919     mediacontrol_Position *a_position;
920     mediacontrol_Exception *exception = NULL;
921     PyObject *py_pos;
922
923     if( !PyArg_ParseTuple(args, "O", &py_pos ) )
924         return NULL;
925
926     a_position = position_py_to_c(py_pos);
927
928     Py_BEGIN_ALLOW_THREADS
929     MC_TRY;
930     mediacontrol_stop(SELF->mc, a_position, exception);
931     free(a_position);
932     Py_END_ALLOW_THREADS
933     MC_EXCEPT;
934
935     Py_INCREF(Py_None);
936     return Py_None;
937 }
938
939 static PyObject *MediaControl_exit(PyObject *self, PyObject *args)
940 {
941     mediacontrol_exit(SELF->mc);
942     Py_INCREF(Py_None);
943     return Py_None;
944 }
945
946 static PyObject *MediaControl_playlist_add_item(PyObject *self, PyObject *args)
947 {
948     char *psz_file;
949     mediacontrol_Exception *exception = NULL;
950
951     if ( !PyArg_ParseTuple(args, "s", &psz_file) )
952       return NULL;
953
954     Py_BEGIN_ALLOW_THREADS
955     MC_TRY;
956     mediacontrol_playlist_add_item(SELF->mc, psz_file, exception);
957     Py_END_ALLOW_THREADS
958     MC_EXCEPT;
959
960     Py_INCREF(Py_None);
961     return Py_None;
962 }
963
964 static PyObject * MediaControl_playlist_clear( PyObject *self,
965                                                 PyObject *args)
966 {
967     mediacontrol_Exception *exception = NULL;
968
969     Py_BEGIN_ALLOW_THREADS
970     MC_TRY;
971     mediacontrol_playlist_clear(SELF->mc, exception);
972     Py_END_ALLOW_THREADS
973     MC_EXCEPT;
974
975     Py_INCREF(Py_None);
976     return Py_None;
977 }
978
979 static PyObject * MediaControl_playlist_get_list( PyObject *self,
980                                                   PyObject *args )
981 {
982     PyObject *py_retval;
983     mediacontrol_Exception *exception = NULL;
984     mediacontrol_PlaylistSeq* pl;
985     int i_index;
986     int i_playlist_size;
987
988     Py_BEGIN_ALLOW_THREADS
989     MC_TRY;
990     pl = mediacontrol_playlist_get_list(SELF->mc, exception);
991     Py_END_ALLOW_THREADS
992     MC_EXCEPT;
993
994     i_playlist_size = pl->size;
995
996     py_retval = PyList_New( i_playlist_size );
997
998     for (i_index = 0 ; i_index < i_playlist_size ; i_index++)
999     {
1000         PyList_SetItem( py_retval, i_index,
1001                         Py_BuildValue("s", pl->data[i_index] ) );
1002     }
1003     mediacontrol_PlaylistSeq__free(pl);
1004
1005     return py_retval;
1006 }
1007
1008
1009 static PyObject * MediaControl_snapshot(PyObject *self, PyObject *args)
1010 {
1011     mediacontrol_RGBPicture *retval  = NULL;
1012     mediacontrol_Exception* exception = NULL;
1013     mediacontrol_Position *a_position    = NULL;
1014     PyObject *py_pos        = NULL;
1015     PyObject *py_obj        = NULL;
1016
1017     if( !PyArg_ParseTuple(args, "O", &py_pos))
1018       return NULL;
1019
1020     a_position = position_py_to_c(py_pos);
1021
1022     Py_BEGIN_ALLOW_THREADS
1023     MC_TRY;
1024     retval = mediacontrol_snapshot(SELF->mc, a_position, exception);
1025     free( a_position );
1026     Py_END_ALLOW_THREADS
1027     MC_EXCEPT;
1028
1029     if( !retval )
1030     {
1031         Py_INCREF( Py_None );
1032         return Py_None;
1033     }
1034
1035     /* FIXME: create a real RGBPicture object */
1036     py_obj = PyDict_New();
1037
1038     PyDict_SetItemString(py_obj, "width",
1039                     Py_BuildValue("i", retval->width) );
1040     PyDict_SetItemString(py_obj, "height",
1041                     Py_BuildValue("i", retval->height) );
1042     PyDict_SetItemString(py_obj, "type",
1043                     Py_BuildValue("i", retval->type) );
1044     PyDict_SetItemString(py_obj, "data",
1045                   Py_BuildValue("s#", retval->data, retval->size) );
1046
1047     /*  Py_INCREF(py_obj); */
1048     return py_obj;
1049 }
1050
1051 static PyObject* MediaControl_display_text(PyObject *self, PyObject *args)
1052 {
1053     mediacontrol_Exception* exception = NULL;
1054     PyObject *py_begin, *py_end;
1055     char* message;
1056     mediacontrol_Position * begin;
1057     mediacontrol_Position * end;
1058
1059     if( !PyArg_ParseTuple(args, "sOO", &message, &py_begin, &py_end))
1060       return NULL;
1061
1062     begin = position_py_to_c(py_begin);
1063     end   = position_py_to_c(py_end);
1064
1065     Py_BEGIN_ALLOW_THREADS
1066     MC_TRY;
1067     mediacontrol_display_text(SELF->mc, message, begin, end, exception);
1068     Py_END_ALLOW_THREADS
1069     MC_EXCEPT;
1070
1071     free(begin);
1072     free(end);
1073
1074     Py_INCREF(Py_None);
1075     return Py_None;
1076 }
1077
1078 static PyObject* MediaControl_get_stream_information(
1079                         PyObject *self, PyObject *args)
1080 {
1081     mediacontrol_StreamInformation *retval  = NULL;
1082     mediacontrol_Exception* exception = NULL;
1083     PyObject *py_obj;
1084
1085     Py_BEGIN_ALLOW_THREADS
1086     MC_TRY;
1087     retval = mediacontrol_get_stream_information(
1088                                 SELF->mc, mediacontrol_MediaTime, exception);
1089     Py_END_ALLOW_THREADS
1090     MC_EXCEPT;
1091
1092     py_obj = PyDict_New();
1093
1094      /* FIXME: create a real StreamInformation object */
1095     PyDict_SetItemString(py_obj, "status",
1096                   Py_BuildValue("i", retval->streamstatus));
1097     PyDict_SetItemString(py_obj, "url",
1098                   Py_BuildValue("s", retval->url));
1099     PyDict_SetItemString(py_obj, "position",
1100                   Py_BuildValue("L", retval->position));
1101     PyDict_SetItemString(py_obj, "length",
1102                   Py_BuildValue("L", retval->length));
1103
1104     free(retval->url);
1105     free(retval);
1106
1107     /* Py_INCREF(py_obj); */
1108     return py_obj;
1109 }
1110
1111 static PyObject* MediaControl_sound_set_volume(PyObject *self, PyObject *args)
1112 {
1113     mediacontrol_Exception* exception = NULL;
1114     unsigned short volume;
1115
1116     if (!PyArg_ParseTuple(args, "H", &volume))
1117        return NULL;
1118
1119     Py_BEGIN_ALLOW_THREADS
1120     MC_TRY;
1121     mediacontrol_sound_set_volume(SELF->mc, volume, exception);
1122     Py_END_ALLOW_THREADS
1123     MC_EXCEPT;
1124
1125     Py_INCREF(Py_None);
1126     return Py_None;
1127 }
1128
1129 static PyObject* MediaControl_sound_get_volume(PyObject *self, PyObject *args)
1130 {
1131     mediacontrol_Exception* exception = NULL;
1132     PyObject *py_retval;
1133     unsigned short volume;
1134
1135     Py_BEGIN_ALLOW_THREADS
1136     MC_TRY;
1137     volume=mediacontrol_sound_get_volume(SELF->mc, exception);
1138     Py_END_ALLOW_THREADS
1139     MC_EXCEPT;
1140
1141     py_retval = Py_BuildValue("H", volume);
1142     return py_retval;
1143 }
1144
1145 static PyObject* MediaControl_set_visual(PyObject *self, PyObject *args)
1146 {
1147     mediacontrol_Exception* exception = NULL;
1148     WINDOWHANDLE visual;
1149
1150     if (!PyArg_ParseTuple(args, "i", &visual))
1151        return NULL;
1152
1153     Py_BEGIN_ALLOW_THREADS
1154     MC_TRY;
1155     mediacontrol_set_visual(SELF->mc, visual, exception);
1156     Py_END_ALLOW_THREADS
1157     MC_EXCEPT;
1158
1159     Py_INCREF(Py_None);
1160     return Py_None;
1161 }
1162
1163 static PyMethodDef MediaControl_methods[] =
1164 {
1165     {"get_media_position", MediaControl_get_media_position, METH_VARARGS,
1166      "get_media_position(origin, key) -> Position    Get current media position." },
1167     { "set_media_position", MediaControl_set_media_position, METH_VARARGS,
1168       "set_media_position(Position)            Set media position" },
1169     { "start", MediaControl_start, METH_VARARGS, 
1170       "start(Position)         Start the player." },
1171     { "pause", MediaControl_pause, METH_VARARGS,
1172       "pause(Position)         Pause the player." },
1173     { "resume", MediaControl_resume, METH_VARARGS,
1174       "resume(Position)        Resume the player" },
1175     { "stop", MediaControl_stop, METH_VARARGS,
1176       "stop(Position)              Stop the player" },
1177     { "exit", MediaControl_exit, METH_VARARGS,
1178       "exit()                     Exit the player" },
1179     { "playlist_add_item", MediaControl_playlist_add_item, METH_VARARGS,
1180       "playlist_add_item(str)               Add an item to the playlist" },
1181     { "playlist_get_list", MediaControl_playlist_get_list, METH_VARARGS,
1182       "playlist_get_list() -> list       Get the contents of the playlist" },
1183     { "playlist_clear", MediaControl_playlist_clear, METH_VARARGS,
1184       "clear()         Clear the playlist." },
1185     { "snapshot", MediaControl_snapshot, METH_VARARGS,
1186       "snapshot(Position) -> dict        Take a snapshot" },
1187     { "display_text", MediaControl_display_text, METH_VARARGS,
1188       "display_text(str, Position, Position)    Display a text on the video" },
1189     { "get_stream_information", MediaControl_get_stream_information,
1190       METH_VARARGS,
1191       "get_stream_information() -> dict      Get information about the stream"},
1192     { "sound_get_volume", MediaControl_sound_get_volume, METH_VARARGS,
1193       "sound_get_volume() -> int       Get the volume" },
1194     { "sound_set_volume", MediaControl_sound_set_volume, METH_VARARGS,
1195       "sound_set_volume(int)           Set the volume" },
1196     { "set_visual", MediaControl_set_visual, METH_VARARGS,
1197       "set_visual(int)           Set the embedding window visual ID" },  
1198     { NULL, NULL, 0, NULL },
1199 };
1200
1201 static PyTypeObject MediaControl_Type =
1202 {
1203     PyObject_HEAD_INIT(NULL)
1204     0,                         /*ob_size*/
1205     "vlc.MediaControl",        /*tp_name*/
1206     sizeof(MediaControl_Type), /*tp_basicsize*/
1207     0,                         /*tp_itemsize*/
1208     (destructor)MediaControl_dealloc,      /*tp_dealloc*/
1209     0,                         /*tp_print*/
1210     0,                         /*tp_getattr*/
1211     0,                         /*tp_setattr*/
1212     0,                         /*tp_compare*/
1213     0,                         /*tp_repr*/
1214     0,                         /*tp_as_number*/
1215     0,                         /*tp_as_sequence*/
1216     0,                         /*tp_as_mapping*/
1217     0,                         /*tp_hash */
1218     0,                         /*tp_call*/
1219     0,                         /*tp_str*/
1220     0,                         /*tp_getattro*/
1221     0,                         /*tp_setattro*/
1222     0,                         /*tp_as_buffer*/
1223     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1224     "Control of a VLC instance.",  /* tp_doc */
1225     0,                     /* tp_traverse */
1226     0,                     /* tp_clear */
1227     0,                     /* tp_richcompare */
1228     0,                     /* tp_weaklistoffset */
1229     0,                     /* tp_iter */
1230     0,                     /* tp_iternext */
1231     MediaControl_methods,             /* tp_methods */
1232     0,             /* tp_members */
1233     0,                         /* tp_getset */
1234     0,                         /* tp_base */
1235     0,                         /* tp_dict */
1236     0,                         /* tp_descr_get */
1237     0,                         /* tp_descr_set */
1238     0,                         /* tp_dictoffset */
1239     0,                         /* tp_init */
1240     0,                         /* tp_alloc */
1241     MediaControl_new,          /* tp_new */
1242 };
1243
1244 /***********************************************************************
1245  * Position
1246  ***********************************************************************/
1247
1248
1249 static int PyPosition_init( PyPosition *self, PyObject *args, PyObject *kwds )
1250 {
1251     self->origin = mediacontrol_AbsolutePosition;
1252     self->key    = mediacontrol_MediaTime;
1253     self->value  = 0;
1254     return 0;
1255 }
1256
1257 mediacontrol_PositionKey positionKey_py_to_c( PyObject * py_key )
1258 {
1259     mediacontrol_PositionKey key_position = mediacontrol_MediaTime;
1260     int key;
1261
1262     if( !PyArg_Parse( py_key, "i", &key ) )
1263     {
1264         PyErr_SetString (MediaControl_InternalException, "Invalid key value"); 
1265         return key_position;
1266     }
1267
1268     switch (key)
1269     {
1270         case 0: key = mediacontrol_ByteCount;   break;
1271         case 1: key = mediacontrol_SampleCount; break;
1272         case 2: key = mediacontrol_MediaTime;   break;
1273     }
1274     return key_position;
1275 }
1276
1277 mediacontrol_PositionOrigin positionOrigin_py_to_c( PyObject * py_origin )
1278 {
1279     mediacontrol_PositionOrigin  origin_position =
1280             mediacontrol_AbsolutePosition;
1281     int origin;
1282
1283     if(!PyArg_Parse(py_origin,"i", &origin))
1284     {
1285         PyErr_SetString( MediaControl_InternalException,
1286                          "Invalid origin value");
1287         return origin_position;
1288     }
1289
1290     switch (origin)
1291     {
1292        case 0: origin_position = mediacontrol_AbsolutePosition; break;
1293        case 1: origin_position = mediacontrol_RelativePosition; break;
1294        case 2: origin_position = mediacontrol_ModuloPosition;   break;
1295     }
1296
1297     return origin_position;
1298 }
1299
1300 /* Methods for transforming the Position Python object to Position structure*/
1301 mediacontrol_Position* position_py_to_c( PyObject * py_position )
1302 {
1303     mediacontrol_Position * a_position = NULL;
1304     PyPosition *pos = (PyPosition*)py_position;
1305
1306     a_position = (mediacontrol_Position*)malloc(sizeof(mediacontrol_Position));
1307     if (! a_position)
1308     {
1309         PyErr_SetString(PyExc_MemoryError, "Out of memory");
1310         return NULL;
1311     }
1312
1313     if (PyObject_IsInstance(py_position, (PyObject*)&PyPosition_Type))
1314     {
1315         a_position->origin = pos->origin;
1316         a_position->key    = pos->key;
1317         a_position->value  = pos->value;
1318     }
1319     else
1320     {
1321         /* Feature: if we give an integer, it will be considered as
1322            a relative position in mediatime */
1323         a_position->origin = mediacontrol_RelativePosition;
1324         a_position->key    = mediacontrol_MediaTime;
1325         a_position->value  = PyLong_AsLongLong(py_position);
1326     }
1327     return a_position;
1328 }
1329
1330 PyPosition* position_c_to_py(mediacontrol_Position *position)
1331 {
1332     PyPosition* py_retval;
1333
1334     py_retval = PyObject_New(PyPosition, &PyPosition_Type);
1335     py_retval->origin = position->origin;
1336     py_retval->key    = position->key;
1337     py_retval->value  = position->value;
1338
1339     return py_retval;
1340 }
1341
1342 static PyMethodDef PyPosition_methods[] =
1343 {
1344     { NULL }  /* Sentinel */
1345 };
1346
1347 static PyMemberDef PyPosition_members[] =
1348 {
1349     { "origin", T_INT, offsetof(PyPosition, origin), 0, "Position origin" },
1350     { "key",    T_INT, offsetof(PyPosition, key),    0, "Position key" },
1351     { "value",  T_ULONG, offsetof(PyPosition, value), 0, "Position value" },
1352     { NULL }  /* Sentinel */
1353 };
1354
1355 static PyTypeObject PyPosition_Type =
1356 {
1357     PyObject_HEAD_INIT(NULL)
1358     0,                         /*ob_size*/
1359     "vlc.Position",            /*tp_name*/
1360     sizeof(PyPosition_Type),   /*tp_basicsize*/
1361     0,                         /*tp_itemsize*/
1362     0,                         /*tp_dealloc*/
1363     0,                         /*tp_print*/
1364     0,                         /*tp_getattr*/
1365     0,                         /*tp_setattr*/
1366     0,                         /*tp_compare*/
1367     0,                         /*tp_repr*/
1368     0,                         /*tp_as_number*/
1369     0,                         /*tp_as_sequence*/
1370     0,                         /*tp_as_mapping*/
1371     0,                         /*tp_hash */
1372     0,                         /*tp_call*/
1373     0,                         /*tp_str*/
1374     0,                         /*tp_getattro*/
1375     0,                         /*tp_setattro*/
1376     0,                         /*tp_as_buffer*/
1377     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1378     "Represent a Position with origin, key and value",  /* tp_doc */
1379     0,                        /* tp_traverse */
1380     0,                        /* tp_clear */
1381     0,                         /* tp_richcompare */
1382     0,                         /* tp_weaklistoffset */
1383     0,                         /* tp_iter */
1384     0,                          /* tp_iternext */
1385     PyPosition_methods,             /* tp_methods */
1386     PyPosition_members,             /* tp_members */
1387     0,                         /* tp_getset */
1388     0,                         /* tp_base */
1389     0,                         /* tp_dict */
1390     0,                         /* tp_descr_get */
1391     0,                         /* tp_descr_set */
1392     0,                         /* tp_dictoffset */
1393     (initproc)PyPosition_init, /* tp_init */
1394     0,                         /* tp_alloc */
1395     0,                         /* tp_new */
1396 };