1/* File : gpod.i.in */ 2 3/* 4 Copyright (C) 2007 Nick Piper <nick-gtkpod at nickpiper co uk> 5 Part of the gtkpod project. 6 7 URL: http://www.gtkpod.org/ 8 URL: http://gtkpod.sourceforge.net/ 9 10 The code contained in this file is free software; you can redistribute 11 it and/or modify it under the terms of the GNU Lesser General Public 12 License as published by the Free Software Foundation; either version 13 2.1 of the License, or (at your option) any later version. 14 15 This file 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 GNU 18 Lesser General Public License for more details. 19 20 You should have received a copy of the GNU Lesser General Public 21 License along with this code; if not, write to the Free Software 22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 24 $Id$ 25 26Please send any fixes, improvements or suggestions to 27<nick-gtkpod at nickpiper co uk>. 28 29*/ 30 31%define DOCSTRING 32"This module gives access to an iPod's content. It provides an easy to 33use API to retrieve the list of files and playlists stored on an iPod, 34modify them, and save them back to the iPod. 35 36This module implements the libgpod C API as directly as possible in 37Python. See the main gpod module for a more traditional Python 38interface." 39%enddef 40 41%pythoncode %{ 42version = "@PACKAGE_VERSION@" 43version_info = version.split(".") 44%} 45 46%module(docstring=DOCSTRING) gpod 47%{ 48#include "@top_builddir@/config.h" 49#include "db-artwork-debug.h" 50#include "db-artwork-parser.h" 51#include "db-image-parser.h" 52#include "db-itunes-parser.h" 53#include "db-parse-context.h" 54#include "itdb.h" 55#include "itdb_device.h" 56#include "itdb_private.h" 57#include <time.h> 58#include <datetime.h> 59#ifdef HAVE_GDKPIXBUF 60#ifdef HAVE_PYGOBJECT 61#include <gdk-pixbuf/gdk-pixbuf.h> 62#include <pygobject.h> 63#endif 64#endif 65 66 67/* include prototypes for all functions so builds using 68 * -Wmissing-prototypes don't fail. */ 69PyObject* sw_get_tracks(Itdb_iTunesDB *itdb); 70PyObject* sw_get_track(GList *list, gint index); 71PyObject* sw_get_rule(GList *list, gint index); 72PyObject* sw_get_playlist(GList *list, gint index); 73PyObject* sw_get_list_len(GList *list); 74PyObject* sw_get_playlists(Itdb_iTunesDB *itdb); 75PyObject* sw_get_playlist_tracks(Itdb_Playlist *pl); 76PyObject* sw_set_track_userdata(Itdb_Track *track, PyObject *data); 77PyObject* sw_get_track_userdata(Itdb_Track *track); 78PyObject* sw__track_extra_duplicate (PyObject *data); 79PyObject* sw_get_photoalbums(Itdb_PhotoDB *db); 80PyObject* sw_get_photoalbum(GList *list, gint index); 81PyObject* sw_get_photos(Itdb_PhotoDB *db); 82PyObject* sw_get_photo(GList *list, gint index); 83PyObject* sw_get_photoalbum_members(Itdb_PhotoAlbum *album); 84PyObject* sw_ipod_device_to_dict(Itdb_Device *device); 85void sw__track_extra_destroy (PyObject *data); 86void hash_table_to_pydict(gpointer key, gpointer value, gpointer user_data); 87void SWIG_init(void); 88 89PyObject* sw_get_tracks(Itdb_iTunesDB *itdb) { 90 PyObject *list; 91 gint i; 92 GList *l; 93 list = PyList_New(g_list_length(itdb->tracks)); 94 for (l = itdb->tracks, i = 0; l; l = l->next, ++i) { 95 PyList_SET_ITEM(list, i, SWIG_NewPointerObj((void*)(l->data), SWIGTYPE_p__Itdb_Track, 0)); 96 } 97 return list; 98 } 99 100PyObject* sw_get_track(GList *list, gint index) { 101 GList *position; 102 if ( (index >= g_list_length(list)) || index < 0 ) { 103 PyErr_SetString(PyExc_IndexError, "Value out of range"); 104 return NULL; 105 } 106 position = g_list_nth(list, index); 107 return SWIG_NewPointerObj((void*)(position->data), SWIGTYPE_p__Itdb_Track, 0); 108 } 109 110PyObject* sw_get_rule(GList *list, gint index) { 111 GList *position; 112 if ( (index >= g_list_length(list)) || index < 0 ) { 113 PyErr_SetString(PyExc_IndexError, "Value out of range"); 114 return NULL; 115 } 116 position = g_list_nth(list, index); 117 return SWIG_NewPointerObj((void*)(position->data), SWIGTYPE_p__Itdb_SPLRule, 0); 118 } 119 120PyObject* sw_get_playlist(GList *list, gint index) { 121 GList *position; 122 if ( (index >= g_list_length(list)) || index < 0 ) { 123 PyErr_SetString(PyExc_IndexError, "Value out of range"); 124 return NULL; 125 } 126 position = g_list_nth(list, index); 127 return SWIG_NewPointerObj((void*)(position->data), SWIGTYPE_p__Itdb_Playlist, 0); 128 } 129 130PyObject* sw_get_list_len(GList *list) { 131 return PyInt_FromLong(g_list_length(list)); 132 } 133 134PyObject* sw_get_playlist_tracks(Itdb_Playlist *pl) { 135 PyObject *list; 136 gint i; 137 GList *l; 138 list = PyList_New(g_list_length(pl->members)); 139 for (l = pl->members, i = 0; l; l = l->next, ++i) { 140 PyList_SET_ITEM(list, i, SWIG_NewPointerObj((void*)(l->data), SWIGTYPE_p__Itdb_Track, 0)); 141 } 142 return list; 143 } 144 145PyObject* sw_get_playlists(Itdb_iTunesDB *itdb) { 146 PyObject *list; 147 gint i; 148 GList *l; 149 list = PyList_New(g_list_length(itdb->playlists)); 150 for (l = itdb->playlists, i = 0; l; l = l->next, ++i) { 151 PyList_SET_ITEM(list, i, SWIG_NewPointerObj((void*)(l->data), SWIGTYPE_p__Itdb_Playlist, 0)); 152 } 153 return list; 154 } 155 156 void sw__track_extra_destroy (PyObject *data) { 157 Py_XDECREF(data); 158 } 159 160 PyObject *sw__track_extra_duplicate (PyObject *data) { 161 if (data == Py_None) { 162 Py_INCREF(Py_None); 163 return Py_None; 164 } else { 165 return PyDict_Copy(data); 166 } 167 } 168 169 PyObject *sw_set_track_userdata(Itdb_Track *track, PyObject *data) { 170 Py_INCREF(data); 171 if ((PyDict_Check(data)) || (data == Py_None)) { 172 if (track->userdata) { 173 Py_DECREF((PyObject *)track->userdata); 174 } 175 track->userdata = (gpointer) data; 176 track->userdata_duplicate = (ItdbUserDataDuplicateFunc)sw__track_extra_duplicate; 177 track->userdata_destroy = (ItdbUserDataDestroyFunc)sw__track_extra_destroy; 178 Py_INCREF(Py_None); 179 return Py_None; 180 } else { 181 PyErr_SetString(PyExc_TypeError, "userdata must be a Dictionary"); 182 return NULL; 183 } 184 } 185 186 PyObject* sw_get_track_userdata(Itdb_Track *track) { 187 if (track->userdata) { 188 Py_INCREF((PyObject *)track->userdata); 189 return (PyObject *)track->userdata; 190 } else { 191 Py_INCREF(Py_None); 192 return Py_None; 193 } 194 } 195 196 PyObject* sw_get_photoalbums(Itdb_PhotoDB *db) { 197 PyObject *list; 198 gint i; 199 GList *l; 200 list = PyList_New(g_list_length(db->photoalbums)); 201 for (l = db->photoalbums, i = 0; l; l = l->next, ++i) { 202 PyList_SET_ITEM(list, i, SWIG_NewPointerObj((void*)(l->data), 203SWIGTYPE_p__Itdb_PhotoAlbum, 0)); 204 } 205 return list; 206 } 207 208PyObject* sw_get_photoalbum(GList *list, gint index) { 209 GList *position; 210 if ( (index >= g_list_length(list)) || index < 0 ) { 211 PyErr_SetString(PyExc_IndexError, "Value out of range"); 212 return NULL; 213 } 214 position = g_list_nth(list, index); 215 return SWIG_NewPointerObj((void*)(position->data), SWIGTYPE_p__Itdb_PhotoAlbum, 0); 216 } 217 218 PyObject* sw_get_photoalbum_members(Itdb_PhotoAlbum *album) { 219 PyObject *list; 220 gint i; 221 GList *l; 222 list = PyList_New(g_list_length(album->members)); 223 for (l = album->members, i = 0; l; l = l->next, ++i) { 224 gint photo_id = GPOINTER_TO_INT(l->data); 225 PyList_SET_ITEM(list, i, PyInt_FromLong((long)photo_id)); 226 } 227 return list; 228 } 229 230 PyObject* sw_get_photos(Itdb_PhotoDB *db) { 231 PyObject *list; 232 gint i; 233 GList *l; 234 list = PyList_New(g_list_length(db->photos)); 235 for (l = db->photos, i = 0; l; l = l->next, ++i) { 236 PyList_SET_ITEM(list, i, SWIG_NewPointerObj((void*)(l->data), 237SWIGTYPE_p__Itdb_Artwork, 0)); 238 } 239 return list; 240 } 241 242PyObject* sw_get_photo(GList *list, gint index) { 243 GList *position; 244 if ( (index >= g_list_length(list)) || index < 0 ) { 245 PyErr_SetString(PyExc_IndexError, "Value out of range"); 246 return NULL; 247 } 248 position = g_list_nth(list, index); 249 return SWIG_NewPointerObj((void*)(position->data), SWIGTYPE_p__Itdb_Artwork, 0); 250 } 251 252 void hash_table_to_pydict(gpointer key, 253 gpointer value, 254 gpointer user_data) { 255 PyDict_SetItemString((PyObject *)user_data, 256 (char *)key, 257 PyString_FromString(value)); 258 } 259 260 PyObject* sw_ipod_device_to_dict(Itdb_Device *device) { 261 PyObject* sysinfo; 262 if (device == NULL) { 263 Py_INCREF(Py_None); 264 return Py_None; 265 } else { 266 sysinfo = PyDict_New(); 267 g_hash_table_foreach(device->sysinfo, 268 hash_table_to_pydict, 269 (gpointer) sysinfo); 270 return Py_BuildValue("{s:s,s:i,s:i,s:O,s:i}", 271 "mountpoint", 272 device->mountpoint, 273 "musicdirs", 274 device->musicdirs, 275 "byte_order", 276 device->byte_order, 277 "sysinfo", 278 sysinfo, 279 "timezone_shift", 280 device->timezone_shift); 281 } 282 } 283 284%} 285 286%init %{ 287#ifdef HAVE_GDKPIXBUF 288#ifdef HAVE_PYGOBJECT 289#if !GLIB_CHECK_VERSION(2, 36, 0) 290 g_type_init (); 291#endif 292 init_pygobject (); 293#endif 294#endif 295 PyDateTime_IMPORT; 296%} 297 298%include "gpod_doc.i" 299%include "@top_builddir@/config.h" 300 301# be nicer to decode these utf8 strings into Unicode objects in the C 302# layer. Here we are leaving it to the Python side, and just giving 303# them utf8 encoded Strings. 304typedef char gchar; 305 306%typemap(in) time_t { 307 struct tm tmvalue; 308 PyObject* pydatetime = NULL; 309 if (PyDateTime_Check($input)) { 310 pydatetime = $input; 311 Py_INCREF(pydatetime); 312 } else if ((PyInt_Check($input)) || (PyLong_Check($input)) || (PyFloat_Check($input))) { 313 PyObject* pyargs; 314 Py_INCREF($input); 315 pyargs = PyTuple_Pack(1, $input); 316 if ((pydatetime = PyDateTime_FromTimestamp(pyargs)) == NULL) { 317 Py_DECREF(pyargs); 318 Py_DECREF($input); 319 SWIG_fail; 320 } 321 Py_DECREF(pyargs); 322 Py_DECREF($input); 323 } else { 324 PyErr_SetString(PyExc_ValueError, "$symname: Value must be a datetime.datetime, int or float"); 325 SWIG_fail; 326 } 327 tmvalue.tm_year = PyDateTime_GET_YEAR(pydatetime) - 1900; 328 tmvalue.tm_mon = PyDateTime_GET_MONTH(pydatetime) - 1; 329 tmvalue.tm_mday = PyDateTime_GET_DAY(pydatetime); 330 tmvalue.tm_hour = PyDateTime_DATE_GET_HOUR(pydatetime); 331 tmvalue.tm_min = PyDateTime_DATE_GET_MINUTE(pydatetime); 332 tmvalue.tm_sec = PyDateTime_DATE_GET_SECOND(pydatetime); 333 334 Py_DECREF(pydatetime); 335 336 $1 = mktime(&tmvalue); 337 if ($1 == -1) { 338 PyErr_SetString(PyExc_ValueError, "$symname: Failed to parse provided time"); 339 SWIG_fail; 340 } 341} 342 343%typemap(out) time_t { 344#ifdef 0 345 /* for libgpod 0.6.x.. maybe ? */ 346 struct tm *tmvalue; 347 tmvalue = localtime(&$1); 348 $result = PyDateTime_FromDateAndTime(tmvalue->tm_year + 1900, 349 tmvalue->tm_mon + 1, 350 tmvalue->tm_mday, 351 tmvalue->tm_hour, 352 tmvalue->tm_min, 353 tmvalue->tm_sec, 354 0); 355#else 356 $result = PyLong_FromUnsignedLong((unsigned long) $1); 357#endif 358} 359 360%typemap(in) guint8 { 361 unsigned long ival; 362 ival = PyInt_AsUnsignedLongMask($input); 363 if (PyErr_Occurred()) 364 SWIG_fail; 365 if (ival > 255) { 366 PyErr_SetString(PyExc_ValueError, "$symname: Value must be between 0 and 255"); 367 SWIG_fail; 368 } else { 369 $1 = (guint8) ival; 370 } 371} 372 373%typemap(in) gint8 { 374 long ival; 375 ival = PyInt_AsInt($input); 376 if (PyErr_Occurred()) 377 SWIG_fail; 378 if ((ival < -128) || (ival > 127)) { 379 PyErr_SetString(PyExc_ValueError, "$symname: Value must be between -128 and 127"); 380 SWIG_fail; 381 } else { 382 $1 = (gint8) ival; 383 } 384} 385 386%typemap(in) guint16 { 387 unsigned long ival; 388 ival = PyInt_AsUnsignedLongMask($input); 389 if (PyErr_Occurred()) 390 SWIG_fail; 391 if (ival > 65535) { 392 PyErr_SetString(PyExc_ValueError, "$symname: Value must be between 0 and 65535"); 393 SWIG_fail; 394 } else { 395 $1 = (guint16) ival; 396 } 397} 398 399%typemap(in) gint16 { 400 long ival; 401 ival = PyInt_AsLong($input); 402 if (PyErr_Occurred()) 403 SWIG_fail; 404 if ((ival < -32768) || (ival > 32767)) { 405 PyErr_SetString(PyExc_ValueError, "$symname: Value must be between -32,768 and 32,767"); 406 SWIG_fail; 407 } else { 408 $1 = (gint16) ival; 409 } 410} 411 412%typemap(in) guint32 { 413 unsigned long ival; 414 ival = PyInt_AsUnsignedLongMask($input); 415 if (PyErr_Occurred()) 416 SWIG_fail; 417 $1 = (guint32) ival; 418} 419 420%typemap(in) gint32 { 421 long ival; 422 ival = PyInt_AsLong($input); 423 if (PyErr_Occurred()) 424 SWIG_fail; 425 $1 = (gint32) ival; 426} 427 428%typemap(in) guint64 { 429 if (PyInt_CheckExact($input)) 430 $1 = PyInt_AsUnsignedLongLongMask($input); 431 else 432 $1 = PyLong_AsUnsignedLongLong($input); 433 if (PyErr_Occurred()) 434 SWIG_fail; 435} 436 437%typemap(in) gint64 { 438 if (PyInt_CheckExact($input)) 439 $1 = PyInt_AsLong($input); 440 else 441 $1 = PyLong_AsLongLong($input); 442 if (PyErr_Occurred()) 443 SWIG_fail; 444} 445 446%typemap(out) guint64 { 447 $result = PyLong_FromUnsignedLongLong($1); 448} 449 450%typemap(out) gint64 { 451 $result = PyLong_FromLongLong($1); 452} 453 454%typemap(out) guint32 { 455 $result = PyLong_FromUnsignedLong($1); 456} 457 458%typemap(out) gint32 { 459 $result = PyLong_FromLong($1); 460} 461 462%typemap(out) guint16 { 463 $result = PyLong_FromUnsignedLong($1); 464} 465 466%typemap(out) gint16 { 467 $result = PyLong_FromLong($1); 468} 469 470%typemap(out) guint8 { 471 $result = PyInt_FromLong($1); 472} 473 474typedef int gboolean; 475typedef int gint; 476 477#ifdef HAVE_GDKPIXBUF 478#ifdef HAVE_PYGOBJECT 479%typemap(out) gpointer itdb_artwork_get_pixbuf { 480 $result = pygobject_new((GObject *)$1); 481 if ($1) { 482 g_object_unref($1); 483 } 484} 485 486%typemap(in) gpointer pixbuf { 487 $1 = GDK_PIXBUF(pygobject_get($input)); 488} 489#endif 490#endif 491 492#define G_BEGIN_DECLS 493#define G_END_DECLS 494 495PyObject* sw_get_tracks(Itdb_iTunesDB *itdb); 496PyObject* sw_get_track(GList *list, gint index); 497PyObject* sw_get_rule(GList *list, gint index); 498PyObject* sw_get_playlist(GList *list, gint index); 499PyObject* sw_get_list_len(GList *list); 500PyObject* sw_get_playlists(Itdb_iTunesDB *itdb); 501PyObject* sw_get_playlist_tracks(Itdb_Playlist *pl); 502PyObject* sw_set_track_userdata(Itdb_Track *track, PyObject *data); 503PyObject* sw_get_track_userdata(Itdb_Track *track); 504PyObject* sw_get_photoalbums(Itdb_PhotoDB *db); 505PyObject* sw_get_photoalbum(GList *list, gint index); 506PyObject* sw_get_photos(Itdb_PhotoDB *db); 507PyObject* sw_get_photo(GList *list, gint index); 508PyObject* sw_get_photoalbum_members(Itdb_PhotoAlbum *album); 509PyObject* sw_ipod_device_to_dict(Itdb_Device *device); 510 511%include "@top_srcdir@/src/itdb.h" 512