1 from enigma import eMediaDatabase, eServiceReference, StringMap, StringMapVector
2 from Screens.ChoiceBox import ChoiceBox
3 from Screens.InputBox import InputBox
4 from Tools.Log import Log
6 from MediaCore import MediaCore
7 from Playlist import Playlist, PlayListEntry, AudioPlaylistEntry, DefaultCoverArt
9 from os import path as os_path
11 class DatabasePlaylistEntry(PlayListEntry):
13 def get(ref, state, data):
14 artist = data.get(eMediaDatabase.FIELD_ARTIST, "")
15 title = data.get(eMediaDatabase.FIELD_TITLE, "")
16 album = data.get(eMediaDatabase.FIELD_ALBUM, "")
17 seconds = int(data.get(eMediaDatabase.FIELD_DURATION, 0))
20 minutes, seconds = divmod(seconds, 60)
21 duration = "%02d:%02d" % (minutes, seconds)
25 entry = (data, "", title, artist, album, duration, DefaultCoverArt)
26 entry = AudioPlaylistEntry.updateState(entry, state)
30 class DatabasePlaylist(Playlist):
31 FEATURE_LISTABLE = True
33 class PlaylistChoice(ChoiceBox):
34 def __init__(self, session, type=MediaCore.TYPE_AUDIO):
36 playlists = DatabasePlaylist.getPlaylists(type)
37 for playlist in playlists:
38 menu.append( (playlist.name, playlist) )
39 ChoiceBox.__init__(self, session, list=menu)
40 self.setTitle(_("Playlists"))
43 def __init__(self, session, type, callback):
44 self._callback = callback
46 inputbox = session.openWithCallback(self._onInput, InputBox, title="Playlist name")
47 inputbox.setTitle("Create New Playlist")
49 def _onInput(self, name):
52 p = DatabasePlaylist.create(name, type=self._type)
55 def __init__(self, id, name=_("Default"), type=MediaCore.TYPE_AUDIO, enableWrapAround=True, entryHelper=DatabasePlaylistEntry):
56 Playlist.__init__(self, name, type, enableWrapAround=enableWrapAround, entryHelper=entryHelper)
60 def getPlaylists(type=MediaCore.TYPE_AUDIO):
62 res = eMediaDatabase.getInstance().getPlaylists(type)
65 for item in res.data():
67 DatabasePlaylist( int(item[eMediaDatabase.FIELD_ID]), name=item[eMediaDatabase.FIELD_PLAYLIST_NAME], type=int(item[eMediaDatabase.FIELD_TYPE]) )
72 def get(id=-1, name=None, type=MediaCore.TYPE_AUDIO, create=False):
73 # If we'er called with only the name given we'll try to get the id.
74 # If we cannot find a matching playlist, we return None
75 db = eMediaDatabase.getInstance()
77 res = db.getPlaylistByName(name, type)
79 res = db.getPlaylist(id)
80 if res.error() or not res.data(): #Playlist unkown (not yet saved/created!)
81 Log.w("%s / %s" %(res.errorDatabaseText(), res.errorDriverText()))
83 Log.i("creating new playlist")
84 return DatabasePlaylist.create(name, type)
86 Log.w("Unkown Playlist for id=%s, name=%s and type=%s" %(id, name, type))
90 id = int(data[eMediaDatabase.FIELD_ID])
91 name = data[eMediaDatabase.FIELD_NAME]
92 Log.i("Playlist %s found. Id is %s" %(name, id))
93 playlist = DatabasePlaylist(id, name=name, type=type)
98 def create(name, type=MediaCore.TYPE_AUDIO):
99 Log.i("name=%s, type=%s" %(name, type))
100 db = eMediaDatabase.getInstance()
101 res = db.getPlaylistByName(name, type)
102 if not res or res.error() or res.data():
103 Log.w("%s / %s / %s" %(res.data(), res.errorDatabaseText(), res.errorDriverText()))
106 playlist = DatabasePlaylist(-1, name=name, type=type)
110 def add(self, ref, extra=None, isBatch=False):
112 if extra is None or extra.get(eMediaDatabase.FIELD_FILE_ID, 0) <= 0:
113 data = self.getDetailsByRef(ref) or data
115 path, filename = os_path.split(ref.getPath())
116 data = { "file_uri" : ref.getPath(), "title" : filename, }
117 Playlist.add(self, ref, data, isBatch)
119 def getDetailsByRef(self, ref):
121 #if we get only a reference or an entry with "extra data" but no file id yet we ask the database to enrich the data
122 if path.startswith("/"):
123 Log.i("Asking database for details!")
124 db = eMediaDatabase.getInstance()
125 res = db.getFileByPath(path)
126 if res and res.data() and not res.error() :
127 return dict(res.data()[0])
129 Log.i("ERROR: %s :: %s" %(res.errorDatabaseText(), res.errorDriverText()))
131 Log.i("%s is not an absolute local path, skip querying the database" % path)
135 def load(self, id, name):
136 Log.i("Loading playlist with id=%s and name=%s" %(id, name))
143 db = eMediaDatabase.getInstance()
145 if self._id < 0: #no @staticmethod get() used, probably....
148 Log.w("A Playlist with the name/id %s/%s does not exist!" %(self._name, self._id))
151 res = db.getPlaylistItemsById(self._id)
152 if res and not res.error():
153 for data in res.data():
155 file_uri = data.get(eMediaDatabase.FIELD_FILE_URI, None)
157 Log.w("Playlist entry invalid, %s" % data)
159 ref = eServiceReference(4097, 0, file_uri)
160 self.add(ref, data, True)
163 Log.i("Error loading playlist %s:%s\n%s\n%s" % (self._id, self._name, res.errorDatabaseText(), res.errorDriverText()))
169 vector = StringMapVector()
171 for item in self._list:
173 stringMap = StringMap()
174 for k, v in item.iteritems():
175 stringMap[k] = str(v)
176 stringMap[eMediaDatabase.FIELD_POS] = str(pos)
178 vector.append(stringMap)
179 db = eMediaDatabase.getInstance()
180 res = db.savePlaylist(self._id, self._name, self._type, vector)
183 Log.w("Error saving playlist %s\n%s\n%s" % (self._id, res.errorDatabaseText(), res.errorDriverText()))
188 if data and len(data) > 0:
189 self._id = int(res.data()[0].get(eMediaDatabase.FIELD_ID, -1))
192 self._valid = not error
194 Log.i("Playlist '%s (%s)' saved" %(self._name, self._id))
196 Log.w("Error saving playlist!")
201 id = property(_getId)