From ThisBlueWiki
I'm developing a plugin for RhythmBox that will import metadata (ratings, play count, last play date) and playlists from the iTunes Library.xml file into Rhythmbox.
This code is pre-alpha and not ready for release yet (ie, mostly nonexistent). I'm using this page as a scratchpad for development right now. When I have something ready for people to use, this page will point to a download site until it's shipped with Rhythmbox. Check back from time to time.
Strategy
- Parse the iTunes Library and build a dictionary of lists of songs with the file size as the key. If there is a collision, append subsequent songs to the list for the particular file size.
- For each entry of type 'song' in the Rhythmbox database, get the file size and look up the associated list in the iTunes Library dictionary.
- If the list is nonexistent, move on.
- If the list is of size one, check the filenames for a match and if there is a match, proceed to step 4.
- If the list is of size two or greater, check the paths for the best match. If one can be found, proceed to step 4. Otherwise, log the problem and move on.
- Set the metadata (rating, play count, last played) in the Rhythmbox database using the values in the iTunes file.
- If the rating is unset, set it.
- If the last play date in the iTunes Library is more recent than the Rhythmbox one or the Rhythmbox one is unset, set it.
- Add the play counts in both libraries and set the count in the Rhythmbox library to the result.
Python plugins
rhythmdb
These are bits of the rhythmdb module that look interesting, retrieved with dir().
- PROP_ENTRY_ID
- PROP_LOCATION
- PROP_FILE_SIZE
- PROP_LAST_PLAYED
- PROP_LAST_PLAYED_STR
- PROP_PLAY_COUNT
- PROP_RATING
C docs from doc/reference/html
rhythmdb_entry_foreach ()
void rhythmdb_entry_foreach (RhythmDB *db,
GFunc func,
gpointer data);
Calls the given function for each of the entries in the database.
db : a RhythmDB.
func : the function to call with each entry.
data : user data to pass to the function.
hints and tips
<moch> entry_foreach is a method on the rhythmdb object, not the module
my main questions now would be, how to use this mysterious info() function and how to construct a query that returns all non-streaming tracks in the database
maybe LOCATION LIKE "file:///" or similar?
<moch> you'd probably want to just look at all entries of the 'song' entry type
ahem
upnp_coherence/MediaStore.py: self.db.entry_foreach_by_type (self.db.entry_type_get_by_name('song'), track_cb)
inspect.getmembers() output
('__class__', <class 'itunesimporter.__main__.RhythmDBTree'>),
('__cmp__', <method-wrapper '__cmp__' of __main__.RhythmDBTree object at 0x86567fc>),
('__delattr__', <method-wrapper '__delattr__' of __main__.RhythmDBTree object at 0x86567fc>),
('__getattribute__', <method-wrapper '__getattribute__' of __main__.RhythmDBTree object at 0x86567fc>),
('__gobject_init__', <built-in method __gobject_init__ of __main__.RhythmDBTree object at 0x86567fc>),
('__hash__', <method-wrapper '__hash__' of __main__.RhythmDBTree object at 0x86567fc>),
('__init__', <method-wrapper '__init__' of __main__.RhythmDBTree object at 0x86567fc>),
('__new__', <built-in method __new__ of GObjectMeta object at 0xb5744480>),
('__reduce__', <built-in method __reduce__ of __main__.RhythmDBTree object at 0x86567fc>),
('__reduce_ex__', <built-in method __reduce_ex__ of __main__.RhythmDBTree object at 0x86567fc>)]
('__repr__', <method-wrapper '__repr__' of __main__.RhythmDBTree object at 0x86567fc>),
('__setattr__', <method-wrapper '__setattr__' of __main__.RhythmDBTree object at 0x86567fc>),
('__str__', <method-wrapper '__str__' of __main__.RhythmDBTree object at 0x86567fc>),
('add_uri', <built-in method add_uri of __main__.RhythmDBTree object at 0x86567fc>),
('add_uri_with_type', <built-in method add_uri_with_type of __main__.RhythmDBTree object at 0x86567fc>),
('chain', <built-in method chain of __main__.RhythmDBTree object at 0x86567fc>),
('commit', <built-in method commit of __main__.RhythmDBTree object at 0x86567fc>),
('connect', <built-in method connect of __main__.RhythmDBTree object at 0x86567fc>),
('connect_after', <built-in method connect_after of __main__.RhythmDBTree object at 0x86567fc>),
('connect_object', <built-in method connect_object of __main__.RhythmDBTree object at 0x86567fc>)]
('connect_object_after', <built-in method connect_object_after of __main__.RhythmDBTree object at 0x86567fc>),
('disconnect', <built-in method disconnect of __main__.RhythmDBTree object at 0x86567fc>),
('disconnect_by_func', <built-in method disconnect_by_func of __main__.RhythmDBTree object at 0x86567fc>),
('do_full_query_async_parsed', <built-in method do_full_query_async_parsed of __main__.RhythmDBTree object at 0x86567fc>),
('do_full_query_parsed', <built-in method do_full_query_parsed of __main__.RhythmDBTree object at 0x86567fc>),
('emit', <built-in method emit of __main__.RhythmDBTree object at 0x86567fc>),
('emit_entry_extra_metadata_notify', <built-in method emit_entry_extra_metadata_notify of __main__.RhythmDBTree object at 0x86567fc>),
('emit_stop_by_name', <built-in method emit_stop_by_name of __main__.RhythmDBTree object at 0x86567fc>),
('entry_count', <built-in method entry_count of __main__.RhythmDBTree object at 0x86567fc>),
('entry_count_by_type', <built-in method entry_count_by_type of __m
('entry_delete', <built-in method entry_delete of __main__.RhythmDBTree object at 0x86567fc>),
('entry_delete_by_type', <built-in method entry_delete_by_type of __main__.RhythmDBTree object at 0x86567fc>),
('entry_foreach', <built-in method entry_foreach of __main__.RhythmDBTree object at 0x86567fc>),
('entry_foreach_by_type', <built-in method entry_foreach_by_type of __main__.RhythmDBTree object at 0x86567fc>),
('entry_gather_metadata', <built-in method entry_gather_metadata of __main__.RhythmDBTree object at 0x86567fc>),
('entry_get', <built-in method entry_get of __main__.RhythmDBTree object at 0x86567fc>),
('entry_is_editable', <built-in method entry_is_editable of __main__.RhythmDBTree object at 0x86567fc>),
('entry_keyword_add', <built-in method entry_keyword_add of __main__.RhythmDBTree object at 0x86567fc>),
('entry_keyword_has', <built-in method entry_keyword_has of __main__.RhythmDBTree object at 0x86567fc>),
('entry_keyword_remove', <built-in method entry_keyword_remove of __main__.RhythmDBTree o
('entry_lookup_by_id', <built-in method entry_lookup_by_id of __main__.RhythmDBTree object at 0x86567fc>),
('entry_lookup_by_location', <built-in method entry_lookup_by_location of __main__.RhythmDBTree object at 0x86567fc>),
('entry_move_to_trash', <built-in method entry_move_to_trash of __main__.RhythmDBTree object at 0x86567fc>),
('entry_new', <built-in method entry_new of __main__.RhythmDBTree object at 0x86567fc>),
('entry_register_type', <built-in method entry_register_type of __main__.RhythmDBTree object at 0x86567fc>),
('entry_request_extra_metadata', <built-in method entry_request_extra_metadata of __main__.RhythmDBTree object at 0x86567fc>),
('entry_type_get_by_name', <built-in method entry_type_get_by_name of __main__.RhythmDBTree object at 0x86567fc>),
('evaluate_query', <built-in method evaluate_query of __main__.RhythmDBTree object at 0x86567fc>),
('freeze_notify', <built-in method freeze_notify of __main__.RhythmDBTree object at 0x86567fc>),
('get_data', <built-in method get_data of __main__.
('get_properties', <built-in method get_properties of __main__.RhythmDBTree object at 0x86567fc>),
('get_property', <built-in method get_property of __main__.RhythmDBTree object at 0x86567fc>),
('get_property_type', <built-in method get_property_type of __main__.RhythmDBTree object at 0x86567fc>),
('handler_block', <built-in method handler_block of __main__.RhythmDBTree object at 0x86567fc>),
('handler_block_by_func', <built-in method handler_block_by_func of __main__.RhythmDBTree object at 0x86567fc>),
('handler_disconnect', <built-in method handler_disconnect of __main__.RhythmDBTree object at 0x86567fc>),
('handler_is_connected', <built-in method handler_is_connected of __main__.RhythmDBTree object at 0x86567fc>),
('handler_unblock', <built-in method handler_unblock of __main__.RhythmDBTree object at 0x86567fc>),
('handler_unblock_by_func', <built-in method handler_unblock_by_func of __main__.RhythmDBTree object at 0x86567fc>),
('is_busy', <built-in method is_busy of __main__.RhythmDBTree object at 0x865
('load', <built-in method load of __main__.RhythmDBTree object at 0x86567fc>),
('notify', <built-in method notify of __main__.RhythmDBTree object at 0x86567fc>),
('property_model_new', <built-in method property_model_new of __main__.RhythmDBTree object at 0x86567fc>),
('query_append', <built-in method query_append of __main__.RhythmDBTree object at 0x86567fc>),
('query_model_new', <built-in method query_model_new of __main__.RhythmDBTree object at 0x86567fc>),
('query_model_new_empty', <built-in method query_model_new_empty of __main__.RhythmDBTree object at 0x86567fc>),
('query_new', <built-in method query_new of __main__.RhythmDBTree object at 0x86567fc>),
('query_preprocess', <built-in method query_preprocess of __main__.RhythmDBTree object at 0x86567fc>),
('save', <built-in method save of __main__.RhythmDBTree object at 0x86567fc>),
('save_async', <built-in method save_async of __main__.RhythmDBTree object at 0x86567fc>)]
shell
inspect.getmembers() output:
('__class__', <type 'rb.Shell'>)
('__cmp__', <method-wrapper '__cmp__' of rb.Shell object at 0x8652504>)
('__delattr__', <method-wrapper '__delattr__' of rb.Shell object at 0x8652504>)
('__getattribute__', <method-wrapper '__getattribute__' of rb.Shell object at 0x8652504>)
('__gobject_init__', <built-in method __gobject_init__ of rb.Shell object at 0x8652504>)
('__hash__', <method-wrapper '__hash__' of rb.Shell object at 0x8652504>)
('__init__', <method-wrapper '__init__' of rb.Shell object at 0x8652504>)
('__new__', <built-in method __new__ of GObjectMeta object at 0xb566d480>)
('__reduce__', <built-in method __reduce__ of rb.Shell object at 0x8652504>)
('__reduce_ex__', <built-in method __reduce_ex__ of rb.Shell object at 0x8652504>)
('__repr__', <method-wrapper '__repr__' of rb.Shell object at 0x8652504>)
('__setattr__', <method-wrapper '__setattr__' of rb.Shell object at 0x8652504>)
('__str__', <method-wrapper '__str__' of rb.Shell object at 0x8652504>)
('add_to_queue', <built-in method add_to_queue of rb.Shell object at 0x8652504>)
('add_uri', <built-in method add_uri of rb.Shell object at 0x8652504>)
('add_widget', <built-in method add_widget of rb.Shell object at 0x8652504>)
('append_source', <built-in method append_source of rb.Shell object at 0x8652504>)
('chain', <built-in method chain of rb.Shell object at 0x8652504>)
('connect', <built-in method connect of rb.Shell object at 0x8652504>)
('connect_after', <built-in method connect_after of rb.Shell object at 0x8652504>)
('connect_object', <built-in method connect_object of rb.Shell object at 0x8652504>)
('connect_object_after', <built-in method connect_object_after of rb.Shell object at 0x8652504>)
('disconnect', <built-in method disconnect of rb.Shell object at 0x8652504>)
('disconnect_by_func', <built-in method disconnect_by_func of rb.Shell object at 0x8652504>)
('emit', <built-in method emit of rb.Shell object at 0x8652504>)
('emit_stop_by_name', <built-in method emit_stop_by_name of rb.Shell object at 0x8652504>)
('freeze_notify', <built-in method freeze_notify of rb.Shell object at 0x8652504>)
('get_data', <built-in method get_data of rb.Shell object at 0x8652504>)
('get_party_mode', <built-in method get_party_mode of rb.Shell object at 0x8652504>)
('get_player', <built-in method get_player of rb.Shell object at 0x8652504>)
('get_playlist_manager', <built-in method get_playlist_manager of rb.Shell object at 0x8652504>)
('get_properties', <built-in method get_properties of rb.Shell object at 0x8652504>)
('get_property', <built-in method get_property of rb.Shell object at 0x8652504>)
('get_ui_manager', <built-in method get_ui_manager of rb.Shell object at 0x8652504>)
('guess_source_for_uri', <built-in method guess_source_for_uri of rb.Shell object at 0x8652504>)
('handler_block', <built-in method handler_block of rb.Shell object at 0x8652504>)
('handler_block_by_func', <built-in method handler_block_by_func of rb.Shell object at 0x8652504>)
('handler_disconnect', <built-in method handler_disconnect of rb.Shell object at 0x8652504>)
('handler_is_connected', <built-in method handler_is_connected of rb.Shell object at 0x8652504>)
('handler_unblock', <built-in method handler_unblock of rb.Shell object at 0x8652504>)
('handler_unblock_by_func', <built-in method handler_unblock_by_func of rb.Shell object at 0x8652504>)
('hidden_notify', <built-in method hidden_notify of rb.Shell object at 0x8652504>)
('load_uri', <built-in method load_uri of rb.Shell object at 0x8652504>)
('notebook_set_page', <built-in method notebook_set_page of rb.Shell object at 0x8652504>)
('notify', <built-in method notify of rb.Shell object at 0x8652504>)
('notify_playing_entry', <built-in method notify_playing_entry of rb.Shell object at 0x8652504>)
('present', <built-in method present of rb.Shell object at 0x8652504>)
('register_entry_type_for_source', <built-in method register_entry_type_for_source of rb.Shell object at 0x8652504>)
('remove_from_queue', <built-in method remove_from_queue of rb.Shell object at 0x8652504>)
('remove_widget', <built-in method remove_widget of rb.Shell object at 0x8652504>)