1#include <boost/python.hpp>
2#include <boost/python/suite/indexing/indexing_suite.hpp>
3#include <boost/python/suite/indexing/map_indexing_suite.hpp>
4#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
5#include <boost/optional.hpp>
6#include <boost/variant.hpp>
7#include <boost/lexical_cast.hpp>
8#include <boost/cstdint.hpp>
10#include <pygtk/pygtk.h>
11#include <gdkmm/pixbuf.h>
12#include <libglademm/xml.h>
17#include "mpx/covers.hh"
21#include "mpx/library.hh"
22#include "mpx/paccess.hh"
23#include "mpx/types.hh"
24#include "mpx/tagview.hh"
26#include "audio-types.hh"
27#include "lyrics-v2.hh"
28#include "last-fm-xmlrpc.hh"
29#include "playbacksource-py.hh"
34using namespace boost::python;
40 PyGILState_STATE m_state;
44 m_state = (PyGILState_STATE)(pyg_gil_state_ensure ());
49 pyg_gil_state_release(m_state);
58 MPX_ATTRIBUTE_LOCATION,
62 MPX_ATTRIBUTE_COMMENT,
64 MPX_ATTRIBUTE_MUSICIP_PUID,
67 MPX_ATTRIBUTE_MB_TRACK_ID,
70 MPX_ATTRIBUTE_ARTIST_SORTNAME,
71 MPX_ATTRIBUTE_MB_ARTIST_ID,
74 MPX_ATTRIBUTE_MB_ALBUM_ID,
75 MPX_ATTRIBUTE_MB_RELEASE_DATE,
78 MPX_ATTRIBUTE_ALBUM_ARTIST,
79 MPX_ATTRIBUTE_ALBUM_ARTIST_SORTNAME,
80 MPX_ATTRIBUTE_MB_ALBUM_ARTIST_ID,
86 MPX_ATTRIBUTE_HAL_VOLUME_UDI,
87 MPX_ATTRIBUTE_HAL_DEVICE_UDI,
88 MPX_ATTRIBUTE_VOLUME_RELATIVE_PATH,
91 MPX_ATTRIBUTE_INSERT_PATH,
92 MPX_ATTRIBUTE_LOCATION_NAME,
99 MPX_ATTRIBUTE_BITRATE,
100 MPX_ATTRIBUTE_SAMPLERATE,
102 MPX_ATTRIBUTE_PLAYDATE,
103 MPX_ATTRIBUTE_NEW_ITEM,
104 MPX_ATTRIBUTE_IS_MB_ALBUM_ARTIST,
106 MPX_ATTRIBUTE_ACTIVE,
107 MPX_ATTRIBUTE_MPX_TRACK_ID,
116 variant_repr(MPX::Variant &self)
121 return boost::lexical_cast<std::string>(boost::get<gint64>(self));
123 return boost::lexical_cast<std::string>(boost::get<double>(self));
125 return boost::get<std::string>(self);
128 return std::string();
132 variant_setint(MPX::Variant &self, gint64 value)
138 variant_getint(MPX::Variant &self)
140 gint64 i = boost::get<gint64>(self);
145 variant_getstring(MPX::Variant &self)
147 std::string s = boost::get<std::string>(self);
152 variant_setstring(MPX::Variant &self, std::string const& value)
158 variant_getdouble(MPX::Variant &self)
160 double d = boost::get<double>(self);
165 variant_setdouble(MPX::Variant &self, double const& value)
171 opt_repr(MPX::OVariant &self)
173 return variant_repr(self.get());
177 opt_init(MPX::OVariant &self)
179 self = MPX::Variant();
183 track_getitem(MPX::Track &self, int id)
189 metadata_getitem(MPX::Metadata &self, int id)
195 track_len(MPX::Track &self)
197 return MPX::N_ATTRIBUTES_INT;
201 metadata_len(MPX::Metadata &self)
203 return MPX::N_ATTRIBUTES_INT;
207 track_repr (MPX::Track &self)
213 metadata_repr(MPX::Metadata &self)
215 return "mpx.Metadata";
223 player_get_gobject (MPX::Player & obj)
225 return pygobject_new((GObject*)(obj.gobj()));
229 player_get_library (MPX::Player & obj)
231 MPX::PAccess<MPX::Library> pa;
238 player_get_hal (MPX::Player & obj)
240 MPX::PAccess<MPX::HAL> pa;
247 player_add_widget (MPX::Player & obj, PyObject * pyobj)
249 obj.add_widget(Glib::wrap(((GtkWidget*)(((PyGObject*)(pyobj))->obj)), false));
253 player_add_info_widget (MPX::Player & obj, PyObject * pyobj, PyObject * name_py)
255 const char* name = PyString_AsString (name_py);
257 g_return_if_fail(name != NULL);
259 obj.add_info_widget(Glib::wrap(((GtkWidget*)(((PyGObject*)(pyobj))->obj)), false), name);
263 player_remove_widget (MPX::Player & obj, PyObject * pyobj)
265 obj.remove_widget(Glib::wrap(((GtkWidget*)(((PyGObject*)(pyobj))->obj)), false));
269 tag_view_get_gobject (MPX::TagView & obj)
271 return pygobject_new((GObject*)(obj.gobj()));
278 sql_row_getitem (MPX::SQL::Row & self, std::string const& key)
284 sql_row_setitem (MPX::SQL::Row & self, std::string const& key, MPX::Variant const& value)
290 sql_row_len (MPX::SQL::Row & self)
301 activate (MPX::Player&, Mcs::Mcs&)
317 class PyRequest : public Request
321 PyRequest (std::string const& url, bool post = false)
323 , m_signal0(new ::pysigc::sigc3<char const*, guint, guint>(Signals.Callback))
325 g_object_ref(G_OBJECT(gobj()));
328 ::pysigc::sigc3<char const*, guint, guint> &
334 virtual ~PyRequest ()
341 ::pysigc::sigc3<char const*, guint, guint> * m_signal0;
346BOOST_PYTHON_MODULE(mpx)
348 /*-------------------------------------------------------------------------------------*/
350 class_< ::pysigc::sigc3<char const*, guint, guint>, boost::noncopyable>("Sigc3MiniSoupCallback", boost::python::no_init)
351 .def("connect", &::pysigc::sigc3<char const*, guint, guint>::connect)
352 .def("emit", &::pysigc::sigc3<char const*, guint, guint>::emit)
353 .def("disconnect", &::pysigc::sigc3<char const*, guint, guint>::disconnect)
356 class_<MPX::Soup::PyRequest, boost::noncopyable>("MPXSoupPyRequest", boost::python::init<std::string, bool>())
357 .def("add_header", &MPX::Soup::PyRequest::add_header)
358 .def("add_request", &MPX::Soup::PyRequest::add_request)
359 .def("run", &MPX::Soup::PyRequest::run)
360 .def("cancel", &MPX::Soup::PyRequest::cancel)
361 .def("status", &MPX::Soup::PyRequest::status)
362 .def("message_status", &MPX::Soup::PyRequest::message_status)
363 .def("get_data_raw", &MPX::Soup::PyRequest::get_data_raw)
364 .def("get_data_size", &MPX::Soup::PyRequest::get_data_size)
365 .def("pysignal_callback", &MPX::Soup::PyRequest::pysignal_callback, return_internal_reference<>())
368 /*-------------------------------------------------------------------------------------*/
370 class_<MPX::OVariant>("Optional")
371 .def("val", (MPX::Variant& (MPX::OVariant::*) ()) &MPX::OVariant::get, return_internal_reference<>() /*return_value_policy<return_by_value>()*/)
372 .def("is_initialized", (bool (MPX::OVariant::*) ()) &MPX::OVariant::is_initialized, return_value_policy<return_by_value>())
373 .def("init", &mpxpy::opt_init)
374 .def("__repr__", &mpxpy::opt_repr, return_value_policy<return_by_value>())
377 /*-------------------------------------------------------------------------------------*/
379 class_<MPX::Variant >("Variant")
380 .def("get_int", &mpxpy::variant_getint, return_value_policy<return_by_value>())
381 .def("set_int", &mpxpy::variant_setint)
382 .def("get_string", &mpxpy::variant_getstring, return_value_policy<return_by_value>())
383 .def("set_string", &mpxpy::variant_setstring)
384 .def("get_double", &mpxpy::variant_getdouble, return_value_policy<return_by_value>())
385 .def("set_double", &mpxpy::variant_setdouble)
386 .def("__repr__", &mpxpy::variant_repr, return_value_policy<return_by_value>())
389 /*-------------------------------------------------------------------------------------*/
391 class_<MPX::Track >("Track")
392 .def("__getitem__", &mpxpy::track_getitem, /*return_value_policy<return_by_value>()*/ return_internal_reference<>())
393 .def("__len__", &mpxpy::track_len, return_value_policy<return_by_value>())
394 .def("__repr__", &mpxpy::track_repr, return_value_policy<return_by_value>())
395 .def("get", &mpxpy::track_getitem, return_value_policy<return_by_value>())
398 /*-------------------------------------------------------------------------------------*/
400 class_<MPX::Metadata >("Metadata")
401 .def("__getitem__", &mpxpy::metadata_getitem, /*return_value_policy<return_by_value>()*/ return_internal_reference<>())
402 .def("__len__", &mpxpy::metadata_len, return_value_policy<return_by_value>())
403 .def("__repr__", &mpxpy::metadata_repr, return_value_policy<return_by_value>())
404 .def("get", &mpxpy::metadata_getitem, /*return_value_policy<return_by_value>()*/ return_internal_reference<>())
405 .def("get_image", &MPX::Metadata::get_image)
408 /*-------------------------------------------------------------------------------------*/
410 enum_<MPX::AttributeId>("AttributeId")
411 .value("LOCATION", MPX::MPX_ATTRIBUTE_LOCATION)
412 .value("TITLE", MPX::MPX_ATTRIBUTE_TITLE)
413 .value("GENRE", MPX::MPX_ATTRIBUTE_GENRE)
414 .value("COMMENT", MPX::MPX_ATTRIBUTE_COMMENT)
415 .value("MUSICIP_PUID", MPX::MPX_ATTRIBUTE_MUSICIP_PUID)
416 .value("HASH", MPX::MPX_ATTRIBUTE_HASH)
417 .value("MB_TRACK_ID", MPX::MPX_ATTRIBUTE_MB_TRACK_ID)
418 .value("ARTIST", MPX::MPX_ATTRIBUTE_ARTIST)
419 .value("ARTIST_SORTNAME", MPX::MPX_ATTRIBUTE_ARTIST_SORTNAME)
420 .value("MB_ARTIST_ID", MPX::MPX_ATTRIBUTE_MB_ARTIST_ID)
421 .value("ALBUM", MPX::MPX_ATTRIBUTE_ALBUM)
422 .value("MB_ALBUM_ID", MPX::MPX_ATTRIBUTE_MB_ALBUM_ID)
423 .value("MB_RELEASE_DATE", MPX::MPX_ATTRIBUTE_MB_RELEASE_DATE)
424 .value("ASIN", MPX::MPX_ATTRIBUTE_ASIN)
425 .value("ALBUM_ARTIST", MPX::MPX_ATTRIBUTE_ALBUM_ARTIST)
426 .value("ALBUM_ARTIST_SORTNAME", MPX::MPX_ATTRIBUTE_ALBUM_ARTIST_SORTNAME)
427 .value("MB_ALBUM_ARTIST_ID", MPX::MPX_ATTRIBUTE_MB_ALBUM_ARTIST_ID)
428 .value("TYPE", MPX::MPX_ATTRIBUTE_TYPE)
429 .value("HAL_VOLUME_UDI", MPX::MPX_ATTRIBUTE_HAL_VOLUME_UDI)
430 .value("HAL_DEVICE_UDI", MPX::MPX_ATTRIBUTE_HAL_DEVICE_UDI)
431 .value("VOLUME_RELATIVE_PATH", MPX::MPX_ATTRIBUTE_VOLUME_RELATIVE_PATH)
432 .value("INSERT_PATH", MPX::MPX_ATTRIBUTE_INSERT_PATH)
433 .value("LOCATION_NAME", MPX::MPX_ATTRIBUTE_LOCATION_NAME)
434 .value("TRACK", MPX::MPX_ATTRIBUTE_TRACK)
435 .value("TIME", MPX::MPX_ATTRIBUTE_TIME)
436 .value("RATING", MPX::MPX_ATTRIBUTE_RATING)
437 .value("DATE", MPX::MPX_ATTRIBUTE_DATE)
438 .value("MTIME", MPX::MPX_ATTRIBUTE_MTIME)
439 .value("BITRATE", MPX::MPX_ATTRIBUTE_BITRATE)
440 .value("SAMPLERATE", MPX::MPX_ATTRIBUTE_SAMPLERATE)
441 .value("PLAYCOUNT", MPX::MPX_ATTRIBUTE_COUNT)
442 .value("PLAYDATE", MPX::MPX_ATTRIBUTE_PLAYDATE)
443 .value("IS_MB_ALBUM_ARTIST", MPX::MPX_ATTRIBUTE_IS_MB_ALBUM_ARTIST)
444 .value("ACTIVE", MPX::MPX_ATTRIBUTE_ACTIVE)
445 .value("MPX_TRACK_ID", MPX::MPX_ATTRIBUTE_MPX_TRACK_ID)
448 /*-------------------------------------------------------------------------------------*/
450 class_<MPX::Player, boost::noncopyable>("Player", boost::python::no_init)
451 .def("get_metadata", &MPX::Player::get_metadata, return_internal_reference<>())
452 .def("gobj", &mpxpy::player_get_gobject)
453 .def("play", &MPX::Player::play)
454 .def("pause", &MPX::Player::pause_ext)
455 .def("prev", &MPX::Player::prev)
456 .def("next", &MPX::Player::next)
457 .def("stop", &MPX::Player::stop)
458 .def("play_uri", &MPX::Player::play_uri)
459 .def("get_library", &mpxpy::player_get_library, return_internal_reference<>())
460 .def("get_hal", &mpxpy::player_get_hal, return_internal_reference<>())
461 .def("add_widget", &mpxpy::player_add_widget)
462 .def("add_info_widget", &mpxpy::player_add_info_widget)
463 .def("remove_widget", &mpxpy::player_remove_widget)
466 /*-------------------------------------------------------------------------------------*/
468 class_<MPX::LyricWiki::TextRequest, boost::noncopyable>("LyricWiki", boost::python::init<std::string, std::string>())
469 .def("run", &MPX::LyricWiki::TextRequest::run)
472 /*-------------------------------------------------------------------------------------*/
474 class_<MPX::LastFM::ArtistMetadataRequestSync, boost::noncopyable>("LastFMArtist", boost::python::init<std::string>())
475 .def("run", &MPX::LastFM::ArtistMetadataRequestSync::run)
478 /*-------------------------------------------------------------------------------------*/
480 class_<MPX::Plugin>("Plugin")
481 .def("activate", &MPX::Plugin::activate)
482 .def("deactivate", &MPX::Plugin::deactivate)
485 /*-------------------------------------------------------------------------------------*/
487 class_<MPX::SQL::Row>("SQLRow")
488 .def(map_indexing_suite<MPX::SQL::Row>())
491 /*-------------------------------------------------------------------------------------*/
493 class_<MPX::SQL::RowV>("SQLRowV")
494 .def(vector_indexing_suite<MPX::SQL::RowV>())
497 /*-------------------------------------------------------------------------------------*/
499 class_<MPX::Library, boost::noncopyable>("Library", boost::python::no_init)
500 .def("getSQL", &MPX::Library::getSQL)
501 .def("execSQL", &MPX::Library::execSQL)
502 .def("getMetadata", &MPX::Library::getMetadata)
505 /*-------------------------------------------------------------------------------------*/
507 enum_<MPX::PlaybackSource::Flags>("PlaybackSourceFlags")
508 .value("F_NONE", MPX::PlaybackSource::F_NONE)
509 .value("F_ASYNC", MPX::PlaybackSource::F_ASYNC)
510 .value("F_HANDLE_STREAMINFO", MPX::PlaybackSource::F_HANDLE_STREAMINFO)
511 .value("F_PHONY_NEXT", MPX::PlaybackSource::F_PHONY_NEXT)
512 .value("F_PHONY_PREV", MPX::PlaybackSource::F_PHONY_PREV)
513 .value("F_HANDLE_LASTFM", MPX::PlaybackSource::F_HANDLE_LASTFM)
514 .value("F_HANDLE_LASTFM_ACTIONS", MPX::PlaybackSource::F_HANDLE_LASTFM_ACTIONS)
515 .value("F_USES_REPEAT", MPX::PlaybackSource::F_USES_REPEAT)
516 .value("F_USES_SHUFFLE", MPX::PlaybackSource::F_USES_SHUFFLE)
519 enum_<MPX::PlaybackSource::Caps>("PlaybackSourceCaps")
520 .value("C_NONE", MPX::PlaybackSource::C_NONE)
521 .value("C_CAN_GO_NEXT", MPX::PlaybackSource::C_CAN_GO_NEXT)
522 .value("C_CAN_GO_PREV", MPX::PlaybackSource::C_CAN_GO_PREV)
523 .value("C_CAN_PAUSE", MPX::PlaybackSource::C_CAN_PAUSE)
524 .value("C_CAN_PLAY", MPX::PlaybackSource::C_CAN_PLAY)
525 .value("C_CAN_SEEK", MPX::PlaybackSource::C_CAN_SEEK)
526 .value("C_CAN_RESTORE_CONTEXT", MPX::PlaybackSource::C_CAN_RESTORE_CONTEXT)
527 .value("C_CAN_PROVIDE_METADATA", MPX::PlaybackSource::C_CAN_PROVIDE_METADATA)
528 .value("C_CAN_BOOKMARK", MPX::PlaybackSource::C_CAN_BOOKMARK)
529 .value("C_PROVIDES_TIMING", MPX::PlaybackSource::C_PROVIDES_TIMING)
532 enum_<MPX::MPXPlaystatus>("PlayStatus")
533 .value("NONE", MPX::PLAYSTATUS_NONE)
534 .value("STOPPED", MPX::PLAYSTATUS_STOPPED)
535 .value("PLAYING", MPX::PLAYSTATUS_PLAYING)
536 .value("PAUSED", MPX::PLAYSTATUS_PAUSED)
537 .value("SEEKING", MPX::PLAYSTATUS_SEEKING)
538 .value("WAITING", MPX::PLAYSTATUS_WAITING)
541 /*-------------------------------------------------------------------------------------*/
543 class_<MPX::PlaybackSourcePy, boost::noncopyable>("PlaybackSource", boost::python::no_init)
544 .def("getUri", &MPX::PlaybackSourcePy::get_uri)
545 .def("getType", &MPX::PlaybackSourcePy::get_type)
546 .def("play", &MPX::PlaybackSourcePy::play)
547 .def("goNext", &MPX::PlaybackSourcePy::go_next)
548 .def("goPrev", &MPX::PlaybackSourcePy::go_prev)
549 .def("stop", &MPX::PlaybackSourcePy::stop)
550 .def("playAsync", &MPX::PlaybackSourcePy::play_async)
551 .def("goNextAsync", &MPX::PlaybackSourcePy::go_next_async)
552 .def("goPrevAsync", &MPX::PlaybackSourcePy::go_prev_async)
553 .def("playPost", &MPX::PlaybackSourcePy::play_post)
554 .def("nextPost", &MPX::PlaybackSourcePy::next_post)
555 .def("prevPost", &MPX::PlaybackSourcePy::prev_post)
556 .def("restoreContext", &MPX::PlaybackSourcePy::restore_context)
557 .def("skipped", &MPX::PlaybackSourcePy::skipped)
558 .def("segment", &MPX::PlaybackSourcePy::segment)
559 .def("bufferingDone", &MPX::PlaybackSourcePy::buffering_done)
560 .def("sendCaps", &MPX::PlaybackSourcePy::send_caps)
561 .def("sendFlags", &MPX::PlaybackSourcePy::send_flags)
562 .def("getName", &MPX::PlaybackSourcePy::get_name)
563 .def("getUi", &MPX::PlaybackSourcePy::get_ui, return_internal_reference<>())
564 .def("player", &MPX::PlaybackSourcePy::player, return_internal_reference<>())
567 /*-------------------------------------------------------------------------------------*/
569 class_<Mcs::Mcs, boost::noncopyable>("MCS", boost::python::no_init)
570 .def("domain_register", &Mcs::Mcs::domain_register)
571 .def("key_register", &Mcs::Mcs::key_register)
572 .def("domain_key_exist", &Mcs::Mcs::domain_key_exist)
573 .def("key_set_bool", &Mcs::Mcs::key_set<bool>)
574 .def("key_set_int", &Mcs::Mcs::key_set<int>)
575 .def("key_set_double", &Mcs::Mcs::key_set<double>)
576 .def("key_set_string", &Mcs::Mcs::key_set<std::string>)
577 .def("key_get_bool", &Mcs::Mcs::key_get<bool>)
578 .def("key_get_int", &Mcs::Mcs::key_get<int>)
579 .def("key_get_double", &Mcs::Mcs::key_get<double>)
580 .def("key_get_string", &Mcs::Mcs::key_get<std::string>)
583 /*-------------------------------------------------------------------------------------*/
585 class_<MPX::TagView, boost::noncopyable>("TagView")
586 .def("get_active_tag", &MPX::TagView::get_active_tag, return_internal_reference<>())
587 .def("clear", &MPX::TagView::clear)
588 .def("add_tag", &MPX::TagView::add_tag)
589 .def("get_widget", &mpxpy::tag_view_get_gobject)
592 /*-------------------------------------------------------------------------------------*/
594 /*-------------------------------------------------------------------------------------*/
596 class_<MPX::HAL::Volume>("MPXHalVolume", boost::python::init<>())
597 .def_readwrite("volume_udi", &MPX::HAL::Volume::volume_udi)
598 .def_readwrite("device_udi", &MPX::HAL::Volume::device_udi)
599 .def_readwrite("label", &MPX::HAL::Volume::label)
600 .def_readwrite("size", &MPX::HAL::Volume::size)
601 .def_readwrite("mount_point", &MPX::HAL::Volume::mount_point)
602 .def_readwrite("mount_time", &MPX::HAL::Volume::mount_time)
603 .def_readwrite("device_file", &MPX::HAL::Volume::device_file)
604 .def_readwrite("drive_serial", &MPX::HAL::Volume::drive_serial)
605 .def_readwrite("drive_bus", &MPX::HAL::Volume::drive_bus)
606 .def_readwrite("drive_type", &MPX::HAL::Volume::drive_type)
607 .def_readwrite("drive_size", &MPX::HAL::Volume::drive_size)
608 .def_readwrite("disc", &MPX::HAL::Volume::disc)
611 class_<MPX::HAL>("MPXHal", boost::python::no_init)