I am an avid supporter of "message based" systems. I took the time to perform a quick "brain dump" of some of my thoughts on the subject.
Follows a simple Python based implementation.
I will very likely make other contributions to my blog along the same lines.
Friday, January 29, 2010
Notes on a Message Passing design
Thursday, January 21, 2010
Message Bus for Gnome Object based Python projects
Whilst developing my latest software project (Rhythmbox plugin Last.fm sync), I have crafted a "Message Bus" based on Gnome GObject. Since I didn't have any experience at all with Gnome GObject previously, it took me sometimes to work out the details of the architecture. For an example usage, please refer to my Git Repository.
""" GObject based "Message Bus" @author: Jean-Lou Dupont """ import gobject #@UnresolvedImport class Signals(gobject.GObject): """ List of the application level signals """ __gsignals__ = { ## NOTE: customization required here ## ================================= ## Announces changes in the user's Last.fm properties "lastfm_username_changed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)) ,'lastfm_password_changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)) ## Used to signal a change in the currently playing track ,"playing_song_changed": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_OBJECT,)) ## Used to report a failure when accessing Last.fm web service ,'lastfm_request_failed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()) ## Used for distributing the results of the query against the Last.fm web service ,"user_track_info": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_OBJECT,)) ## Used to pass around the "shell" global object ,"rb_shell": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_OBJECT,)) } def __init__(self): gobject.GObject.__init__(self) class Bus(object): """ Message Bus Borg Pattern """ _signals=Signals() @classmethod def emit(cls, name, *pa, **kwa): cls._signals.emit(name, *pa, **kwa) @classmethod def add_emission_hook(cls, name, callback): gobject.add_emission_hook(cls._signals, name, callback) mbus=Bus() ## =============================================================== Tests if __name__=="__main__": def callback(signal, data): print "callback: signal=%s, data=%s" % (signal, data) Bus.add_emission_hook("lastfm_username_changed", callback) Bus.emit("lastfm_username_changed", "jldupont")
Relevant Stackoverflow posts
Here are two Stackoverflow posts in relation with my exercise: question 1, question 2.
Rhythmbox plugin - Syncing with Last.fm
In my quest to manage my music collection seamlessly between media players, I've decided to use Last.Fm as my main database. Last.Fm provides ways to store:
- History of played tracks
- Playcount associated with played tracks
- Tags associated with tracks
- Playlists
- etc.
- When a track is played, it downloads the corresponding information from the user's Last.Fm account and updates the following fields of the Rhythmbox database:
- Playcount: if the "last.fm playcount" associated with the track is greater than 0, the local playcount of RB is updated with it
- Rating: if the "last.fm love" field is set for the track, the local "rating" field of the track is set to 5.0 (5 stars)
UPDATE: see here for details on the new release.
Monday, January 11, 2010
Rhythmbox plugin for Last.fm desktop client
I've recently lost my music database to the hands of Banshee (actually, the Sqlite3 database file is still somewhat salvageable). I have longed for an application that would make my life easy in managing my music collection (which is pretty extensive) and do this day haven't found one. The recent event pushed me to the edge: I am embarking on a quest to scratch my itch on this matter.