beginnings of a maemo ui
authorKristoffer Grönlund <kristoffer.gronlund@purplescout.se>
Tue, 29 Dec 2009 23:08:11 +0000 (00:08 +0100)
committerKristoffer Grönlund <kristoffer.gronlund@purplescout.se>
Sat, 2 Jan 2010 23:37:44 +0000 (00:37 +0100)
data/bg.png [new file with mode: 0644]
data/jam_artists_simple.png [new file with mode: 0644]
data/logo_2600_710.png [new file with mode: 0644]
jamaendo/api.py
jamaui/console.py
jamaui/jam_artists_simple.png [deleted file]
jamaui/logo_2600_710.png [deleted file]
jamaui/player.py
jamaui/ui.py
scripts/jamaendo [new file with mode: 0755]
scripts/query

diff --git a/data/bg.png b/data/bg.png
new file mode 100644 (file)
index 0000000..a6645eb
Binary files /dev/null and b/data/bg.png differ
diff --git a/data/jam_artists_simple.png b/data/jam_artists_simple.png
new file mode 100644 (file)
index 0000000..f31fe50
Binary files /dev/null and b/data/jam_artists_simple.png differ
diff --git a/data/logo_2600_710.png b/data/logo_2600_710.png
new file mode 100644 (file)
index 0000000..cce480b
Binary files /dev/null and b/data/logo_2600_710.png differ
index 5d2bde9..994288d 100644 (file)
@@ -1,4 +1,4 @@
-import urllib, threading, os, gzip, time, json, re
+import urllib, threading, os, gzip, time, simplejson, re
 _DUMP_URL = '''http://img.jamendo.com/data/dbdump_artistalbumtrack.xml.gz'''
 _DUMP = os.path.expanduser('''~/.cache/jamaendo/dbdump.xml.gz''')
 
 _DUMP_URL = '''http://img.jamendo.com/data/dbdump_artistalbumtrack.xml.gz'''
 _DUMP = os.path.expanduser('''~/.cache/jamaendo/dbdump.xml.gz''')
 
@@ -71,53 +71,58 @@ class LocalDB(object):
     def close(self):
         self.fil.close()
 
     def close(self):
         self.fil.close()
 
+    def make_album_brief(self, element):
+        ret = {}
+        for info in element:
+            if info.tag == 'id':
+                ret['id'] = int(info.text)
+            elif info.tag == 'name':
+                ret['name'] = info.text
+        return ret
+
     def make_artist_obj(self, element):
     def make_artist_obj(self, element):
-        if element.text is not None and element.text != "":
-            return element.text
-        else:
-            ret = {}
-            for child in element:
-                if child.tag in ['name', 'id', 'image']:
-                    ret[child.tag] = child.text
-                if child.tag == 'Albums':
-                    albums = []
-                    for album in child:
-                        albie = {}
-                        for albumitem in album:
-                            if albumitem.tag in ['name', 'id']:
-                                albie[albumitem.tag] = albumitem.text
-                        albums.append(albie)
-                    ret['albums'] = albums
-            return ret
+        ret = {}
+        for child in element:
+            if child.tag == 'id':
+                ret['id'] = int(child.text)
+            elif child.tag in ('name', 'image'):
+                ret[child.tag] = child.text
+            elif child.tag == 'Albums':
+                ret['albums'] = [self.make_album_brief(a) for a in child]
+        return ret
+
+    def make_track_obj(self, element):
+        ret = {}
+        for info in element:
+            if info.tag == 'id':
+                _id = int(info.text)
+                ret['id'] = _id
+                ret['mp3'] = Query.track_mp3(_id)
+                ret['ogg'] = Query.track_ogg(_id)
+            elif info.tag in ('name', 'numalbum'):
+                ret[info.tag] = info.text
+        return ret
 
     def make_album_obj(self, element):
 
     def make_album_obj(self, element):
-        if element.text is not None and element.text != "":
-            return element.text
-        else:
-            ret = {}
-            artist = element.getparent().getparent()
-            if artist is not None:
-                for child in artist:
-                    if child.tag == 'name':
-                        ret['artist'] = child.text
-                    elif child.tag == 'id':
-                        ret['artist_id'] = child.text
-            for child in element:
-                if child.tag in ['name', 'id', 'image']:
-                    if child.text:
-                        ret[child.tag] = child.text
-                    else:
-                        ret[child.tag] = ""
-                if child.tag == 'Tracks':
-                    tracks = []
-                    for track in child:
-                        trackd = {}
-                        for trackinfo in track:
-                            if trackinfo.tag in ['name', 'id', 'numalbum']:
-                                trackd[trackinfo.tag] = trackinfo.text
-                        tracks.append(trackd)
-                    ret['tracks'] = tracks
-            return ret
+        ret = {}
+        artist = element.getparent().getparent()
+        if artist is not None:
+            for child in artist:
+                if child.tag == 'name':
+                    ret['artist'] = child.text
+                elif child.tag == 'id':
+                    ret['artist_id'] = int(child.text)
+        for child in element:
+            if child.tag == 'id':
+                ret['id'] = int(child.text)
+            elif child.tag in ('name', 'image'):
+                if child.text:
+                    ret[child.tag] = child.text
+                else:
+                    ret[child.tag] = ""
+            elif child.tag == 'Tracks':
+                ret['tracks'] = [self.make_track_obj(t) for t in child]
+        return ret
 
     def artist_walker(self, name_match):
         for event, element in etree.iterparse(self.fil, tag="artist"):
 
     def artist_walker(self, name_match):
         for event, element in etree.iterparse(self.fil, tag="artist"):
@@ -202,7 +207,7 @@ class Query(object):
         """ratelimited query"""
         self._ratelimit()
         f = urllib.urlopen(self.url)
         """ratelimited query"""
         self._ratelimit()
         f = urllib.urlopen(self.url)
-        ret = json.load(f)
+        ret = simplejson.load(f)
         f.close()
         return ret
 
         f.close()
         return ret
 
index 5c02a0b..88622ea 100644 (file)
@@ -9,6 +9,9 @@ if os.path.isdir(local_module_dir):
 from jamaendo.api import LocalDB, Query, Queries, refresh_dump
 from jamaui.player import Player, Playlist
 import time
 from jamaendo.api import LocalDB, Query, Queries, refresh_dump
 from jamaui.player import Player, Playlist
 import time
+import gobject
+
+gobject.threads_init()
 
 class Refresher(object):
     def __init__(self):
 
 class Refresher(object):
     def __init__(self):
@@ -29,8 +32,8 @@ class Refresher(object):
 
 
 def pprint(x):
 
 
 def pprint(x):
-    import json
-    print json.dumps(x, sort_keys=True, indent=4)
+    import simplejson
+    print simplejson.dumps(x, sort_keys=True, indent=4)
 
 class Console(object):
     def run(self):
 
 class Console(object):
     def run(self):
@@ -74,11 +77,13 @@ class Console(object):
     def query_play_track(self):
         trackid = int(sys.argv[2])
         uri = Query.track_mp3(trackid)
     def query_play_track(self):
         trackid = int(sys.argv[2])
         uri = Query.track_mp3(trackid)
-        items = [uri]
-        playlist = Playlist(items)
+        playlist = Playlist([uri])
         player = Player()
         player.play(playlist)
 
         player = Player()
         player.play(playlist)
 
+        while player.playing():
+            time.sleep(1)
+
     def query_play_album(self):
         albumid = int(sys.argv[2])
         db = LocalDB()
     def query_play_album(self):
         albumid = int(sys.argv[2])
         db = LocalDB()
@@ -90,14 +95,16 @@ class Console(object):
         if not album:
             return
         print "%s - %s" % (album['artist'], album['name'])
         if not album:
             return
         print "%s - %s" % (album['artist'], album['name'])
-        items = [Query.track_mp3(int(track['id'])) for track in album['tracks']]
 
 
-        playlist = Playlist(items)
+        playlist = Playlist(album['tracks'])
         player = Player()
         player.play(playlist)
 
         while player.playing():
         player = Player()
         player.play(playlist)
 
         while player.playing():
-            time.sleep(1)
+            try:
+                time.sleep(1)
+            except KeyboardInterrupt:
+                player.next()
 
 if __name__=="__main__":
     main()
 
 if __name__=="__main__":
     main()
diff --git a/jamaui/jam_artists_simple.png b/jamaui/jam_artists_simple.png
deleted file mode 100644 (file)
index f31fe50..0000000
Binary files a/jamaui/jam_artists_simple.png and /dev/null differ
diff --git a/jamaui/logo_2600_710.png b/jamaui/logo_2600_710.png
deleted file mode 100644 (file)
index cce480b..0000000
Binary files a/jamaui/logo_2600_710.png and /dev/null differ
index 0b27777..8274662 100644 (file)
@@ -69,6 +69,8 @@ class GStreamer(object):
         bus = self.player.get_bus()
         bus.add_signal_watch()
         bus.connect('message', self._on_message)
         bus = self.player.get_bus()
         bus.add_signal_watch()
         bus.connect('message', self._on_message)
+
+        self._set_volume_level( 1 )
         return True
 
     def get_state(self):
         return True
 
     def get_state(self):
@@ -194,12 +196,29 @@ class GStreamer(object):
         self.eos_callback = cb
 
 class Playlist(object):
         self.eos_callback = cb
 
 class Playlist(object):
+    class Entry(object):
+        def __init__(self, data):
+            if isinstance(data, dict):
+                self.id = data['id']
+                self.name = data['name']
+                self.numalbum = int(data['numalbum'])
+                self.url = data['mp3']
+                self.type = 'mp3'
+            elif isinstance(data, basestring): # assume URI
+                self.id = 0
+                self.name = ''
+                self.numalbum = 0
+                self.url = data
+                self.type = 'mp3'
+        def __str__(self):
+            return "{%s}" % (", ".join([str(self.name), str(self.numalbum), str(self.url)]))
+
     def __init__(self, items = []):
     def __init__(self, items = []):
-        self.items = items
+        self.items = [Playlist.Entry(item) for item in items]
         self.current = -1
 
     def add(self, item):
         self.current = -1
 
     def add(self, item):
-        self.items.append(item)
+        self.items.append(Playlist.Entry(item))
 
     def next(self):
         if self.has_next():
 
     def next(self):
         if self.has_next():
@@ -221,7 +240,9 @@ class Player(Playlist):
             self.playlist = playlist
         if self.playlist is not None:
             if self.playlist.has_next():
             self.playlist = playlist
         if self.playlist is not None:
             if self.playlist.has_next():
-                self.gstreamer.setup('mp3', self.playlist.next())
+                entry = self.playlist.next()
+                log.debug("playing %s", entry)
+                self.gstreamer.setup(entry.type, entry.url)
                 self.gstreamer.play()
 
     def pause(self):
                 self.gstreamer.play()
 
     def pause(self):
@@ -235,8 +256,8 @@ class Player(Playlist):
 
     def next(self):
         if self.playlist.has_next():
 
     def next(self):
         if self.playlist.has_next():
-            self.gstreamer.setup('mp3', self.playlist.next())
-            self.gstreamer.play()
+            self.stop()
+            self.play()
         else:
             self.stop()
 
         else:
             self.stop()
 
@@ -244,4 +265,5 @@ class Player(Playlist):
         pass
 
     def _on_eos(self):
         pass
 
     def _on_eos(self):
+        log.debug("EOS!")
         self.next()
         self.next()
index e0bb84b..1c6724f 100644 (file)
@@ -1,6 +1,19 @@
+# debugging hack - add . to path
+import os, sys
+local_module_dir = os.path.join(os.path.dirname(sys.argv[0]), '..')
+if os.path.isdir(local_module_dir):
+    sys.path.append(local_module_dir)
+
 import gtk
 import gobject
 import util
 import gtk
 import gobject
 import util
+import logging
+import gobject
+
+from jamaendo.api import LocalDB, Query, Queries, refresh_dump
+from jamaui.player import Player, Playlist
+
+gobject.threads_init()
 
 log = logging.getLogger(__name__)
 
 
 log = logging.getLogger(__name__)
 
@@ -8,21 +21,31 @@ try:
     import hildon
 except:
     if util.platform == 'maemo':
     import hildon
 except:
     if util.platform == 'maemo':
-        log.critical( 'Using GTK widgets, install "python2.5-hildon" '
-            'for this to work properly.' )
+        log.critical('Using GTK widgets, install "python2.5-hildon" '
+            'for this to work properly.')
+    else:
+        log.critical('This ui only works in maemo')
+        sys.exit(1)
 
 class Jamaui(object):
 
 class Jamaui(object):
+    _DATA = 'data/bg.png' # /opt/jamaendo/data/bg.png
+
     def __init__(self):
     def __init__(self):
-        self.app = None
-        self.window = None
-        if util.platform == 'maemo':
-            self.app = hildon.Program()
-            self.window = hildon.Window()
-            self.app.add_window(window)
-        else:
-            self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+        self.app = hildon.Program()
+        self.window = hildon.Window()
+        self.app.add_window(window)
+
+        self.window.set_title("jamaendo")
+        self.window.connect("destroy", gtk.main_quit, None)
+
+        img = gtk.image_new_from_file(self._DATA)
+        self.window.add(img)
 
     def run(self):
 
     def run(self):
-        self.window.show()
+        self.window.show_all()
         gtk.main()
 
         gtk.main()
 
+if __name__=="__main__":
+    ui = Jamaui()
+    ui.run()
+
diff --git a/scripts/jamaendo b/scripts/jamaendo
new file mode 100755 (executable)
index 0000000..5de2686
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/env python2.5
+
+# debugging hack - add . to path
+import os, sys
+local_module_dir = os.path.join(os.path.dirname(sys.argv[0]), '..')
+if os.path.isdir(local_module_dir):
+    sys.path.append(local_module_dir)
+
+def main():
+    from jamaui.ui import JamaUI
+    player = JamaUI()
+
+    player.run()
+
+if __name__=="__main__":
+    main()
index a8e94cf..e1ef212 100755 (executable)
@@ -29,8 +29,8 @@ class Refresher(object):
 
 
 def pprint(x):
 
 
 def pprint(x):
-    import json
-    print json.dumps(x, sort_keys=True, indent=4)
+    import simplejson
+    print simplejson.dumps(x, sort_keys=True, indent=4)
 
 def main():
     Refresher().run()
 
 def main():
     Refresher().run()