[Deskbar] Muine song/album search
- From: Eric Lesh <eclesh pacbell net>
- To: deskbar-applet-list gnome org
- Subject: [Deskbar] Muine song/album search
- Date: Sun, 13 Nov 2005 21:17:40 -0800
Hi,
This adds a handler that allows for playing an music in Muine by
searching for an album or song name (two separate handlers). It works
fine, but has a number of caveats:
* Requires muine-shell (I'm using python2.3, so can't compile dbus
bindings yet)
* If you are running both the album and song handlers, you can't
distinguish between songs and albums of the same name. Both display
'Play %(song/album) by %(artist)'. Maybe albums should say 'Play album
%(album) by %(artist)' or something?
* I don't normally use Python, so things are probably ugly.
Specifically, the database parsing algorithm could use work, because it
is using a nasty regex that embarrasses me a little bit.
All these things could obviously be fixed by someone who has some
knowledge of Python and a desire to use this. Hopefully somebody finds
this useful. At the very least, it may inspire someone to hack up the
same thing for Rhythmbox, Banshee, or Quodlibet.
-eric
import os
from os.path import expanduser, exists
from gettext import gettext as _
import gdbm
import re
import gobject
import deskbar.handler
from deskbar.filewatcher import FileWatcher
HANDLERS = {
"MuineAlbumHandler" : {
"name": _("Music search"),
"description": _("Play music albums"),
},
"MuineSongHandler" : {
"name": _("Music search"),
"description": _("Play songs")
},
}
MUINE_SONGS_DB = expanduser("~/.gnome2/muine/songs.db")
class MuineAlbumMatch(deskbar.handler.Match):
def __init__(self, backend, name, artist, path):
deskbar.handler.Match.__init__(self, backend, "stock_music-library")
self._name = name
self._artist = artist
self._path = path
def action(self, text=None):
self._priority = self._priority+1
gobject.spawn_async(["muine-shell", '-f', self._path[0]], flags=gobject.SPAWN_SEARCH_PATH)
del self._path[0]
for song in self._path:
gobject.spawn_async(["muine-shell", '-q', song], flags=gobject.SPAWN_SEARCH_PATH)
def get_verb(self):
return _("Play <b>%(name)s</b> by %(artist)s")
def get_name(self, text=None):
return {
"name": self._name,
"artist": self._artist,
}
class MuineSongMatch(deskbar.handler.Match):
def __init__(self, backend, artist, name, path):
deskbar.handler.Match.__init__(self, backend, "stock_music-library")
self._artist = artist
self._name = name
self._path = path
def action(self, text=None):
self._priority = self._priority+1
gobject.spawn_async(["muine-shell", "-f", self._path], flags=gobject.SPAWN_SEARCH_PATH)
def get_verb(self):
return _("Play <b>%(name)s</b> by %(artist)s")
def get_name(self, text=None):
return {
"name": self._name,
"artist": self._artist,
}
class MuineHandler (deskbar.handler.Handler):
def __init__(self, callback):
deskbar.handler.Handler.__init__(self, "stock_music-library")
self.watch_callback = callback
def initialize(self):
if not hasattr(self, 'watcher'):
self.watcher = FileWatcher()
self.watcher.connect('changed', lambda watcher, f: self.watch_callback())
self.watcher.add(MUINE_SONGS_DB)
def stop(self):
self.watcher.remove(MUINE_SONGS_DB)
class MuineAlbumHandler(MuineHandler):
def __init__(self):
MuineHandler.__init__(self, lambda: self._scan_muine_albums())
self._albums = {}
def initialize(self):
MuineHandler.initialize(self)
self._scan_muine_albums()
def query(self, query, max=5):
result = []
query = query.lower()
for key, (artist, songs) in self._albums.items():
if key.lower().startswith(query):
result.append(MuineAlbumMatch(self, key, artist, songs))
return result[:max]
def _scan_muine_albums(self):
if not exists(MUINE_SONGS_DB):
return
try:
db = gdbm.open(MUINE_SONGS_DB, 'r')
p = re.compile(r'\A\W.*?(\w.*?)\x00.*?\W.*?(\w.*?)\x00.*?\W.*?(\w.*?)\x00.*?\W.*')
key = db.firstkey()
while key != None:
match = p.match(db[key])
if match != None:
if not self._albums.has_key("%s" % match.group(3)):
self._albums["%s" % match.group(3)] = (match.group(2), [key])
else:
(artist, songs) = self._albums["%s" % match.group(3)]
songs.append(key)
self._albums["%s" % match.group(3)] = (artist, songs)
key = db.nextkey(key)
except Exception, msg:
print 'Error:_scan_muine_albums:', msg
class MuineSongHandler(MuineHandler):
def __init__(self):
MuineHandler.__init__(self, lambda: self._scan_muine_songs())
self._songs = []
def initialize(self):
MuineHandler.initialize(self)
self._scan_muine_songs()
def query(self, query, max=5):
result = []
query = query.lower()
for (artist, song, path) in self._songs:
if song.lower().startswith(query):
result.append(MuineSongMatch(self, artist, song, path))
return result[:max]
def _scan_muine_songs(self):
if not exists(MUINE_SONGS_DB):
return
try:
db = gdbm.open(MUINE_SONGS_DB, 'r')
p = re.compile(r'\A\W.*?(\w.*?)\x00.*?\W.*?(\w.*?)\x00.*?\W.*?(\w.*?)\x00.*?\W.*')
key = db.firstkey()
while key != None:
match = p.match(db[key])
if match != None:
self._songs.append((match.group(2), match.group(1), key))
key = db.nextkey(key)
except Exception, msg:
print 'Error:_scan_muine_songs:', msg
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]