| 1 | # Deejayd, a media player daemon |
|---|
| 2 | # Copyright (C) 2007-2009 Mickael Royer <mickael.royer@gmail.com> |
|---|
| 3 | # Alexandre Rossi <alexandre.rossi@gmail.com> |
|---|
| 4 | # |
|---|
| 5 | # This program is free software; you can redistribute it and/or modify |
|---|
| 6 | # it under the terms of the GNU General Public License as published by |
|---|
| 7 | # the Free Software Foundation; either version 2 of the License, or |
|---|
| 8 | # (at your option) any later version. |
|---|
| 9 | # |
|---|
| 10 | # This program is distributed in the hope that it will be useful, |
|---|
| 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 13 | # GNU General Public License for more details. |
|---|
| 14 | # |
|---|
| 15 | # You should have received a copy of the GNU General Public License along |
|---|
| 16 | # with this program; if not, write to the Free Software Foundation, Inc., |
|---|
| 17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
|---|
| 18 | |
|---|
| 19 | import deejayd.interfaces |
|---|
| 20 | from deejayd.interfaces import DeejaydError,\ |
|---|
| 21 | DeejaydAnswer,\ |
|---|
| 22 | DeejaydKeyValue, DeejaydList,\ |
|---|
| 23 | DeejaydFileList,\ |
|---|
| 24 | DeejaydMediaList, DeejaydDvdInfo |
|---|
| 25 | from deejayd.ui.config import DeejaydConfig |
|---|
| 26 | from deejayd import mediafilters, player, sources, mediadb, database, plugins |
|---|
| 27 | |
|---|
| 28 | # Exception imports |
|---|
| 29 | import deejayd.sources.webradio |
|---|
| 30 | import deejayd.mediadb.library |
|---|
| 31 | |
|---|
| 32 | |
|---|
| 33 | def require_mode(mode_name): |
|---|
| 34 | def require_mode_instance(func): |
|---|
| 35 | |
|---|
| 36 | def require_mode_func(self, *__args, **__kw): |
|---|
| 37 | if self.sources.is_available(mode_name): |
|---|
| 38 | return func(self, *__args, **__kw) |
|---|
| 39 | else: |
|---|
| 40 | raise DeejaydError(_("mode %s is not activated.") % mode_name) |
|---|
| 41 | |
|---|
| 42 | require_mode_func.__name__ = func.__name__ |
|---|
| 43 | return require_mode_func |
|---|
| 44 | |
|---|
| 45 | return require_mode_instance |
|---|
| 46 | |
|---|
| 47 | # This decorator is used for the core interface to provide : |
|---|
| 48 | # - A simple way of converting python types to deejayd answers as required by |
|---|
| 49 | # the defined network interface. This is to ensure that the core API stays |
|---|
| 50 | # the same as the client library API. This way, code written as a deejayd |
|---|
| 51 | # client can become a full media player for free by swaping |
|---|
| 52 | # deejayd.net.DeejaydClient and deejayd.core.DeejaydCore . |
|---|
| 53 | # - A simple way to make this optionnal using an optionnal objanswer argument. |
|---|
| 54 | # Please don't use objanswer=False if you think that what you write may one |
|---|
| 55 | # day be used as a deejayd network client. This was originally provided for |
|---|
| 56 | # use in the deejayd.net.commandsXML module. |
|---|
| 57 | def returns_deejaydanswer(answer_class): |
|---|
| 58 | def returns_deejaydanswer_instance(func): |
|---|
| 59 | |
|---|
| 60 | def interface_clean_func(*__args, **__kw): |
|---|
| 61 | if __kw.has_key('objanswer'): |
|---|
| 62 | objanswer = __kw['objanswer'] |
|---|
| 63 | del __kw['objanswer'] |
|---|
| 64 | else: |
|---|
| 65 | objanswer = True |
|---|
| 66 | if objanswer: |
|---|
| 67 | ans = answer_class() |
|---|
| 68 | try: |
|---|
| 69 | res = func(*__args, **__kw) |
|---|
| 70 | except DeejaydError, txt: |
|---|
| 71 | ans.set_error(txt) |
|---|
| 72 | else: |
|---|
| 73 | if res == None: |
|---|
| 74 | ans.contents = True |
|---|
| 75 | elif answer_class == DeejaydMediaList: |
|---|
| 76 | if isinstance(res, tuple): |
|---|
| 77 | ans.set_filter(res[1]) |
|---|
| 78 | ans.set_sort(res[2]) |
|---|
| 79 | res = res[0] |
|---|
| 80 | ans.set_medias(res) |
|---|
| 81 | elif answer_class == DeejaydFileList: |
|---|
| 82 | root_dir, dirs, files = res |
|---|
| 83 | if root_dir != None: |
|---|
| 84 | ans.set_rootdir(root_dir) |
|---|
| 85 | ans.set_files(files) |
|---|
| 86 | ans.set_directories(dirs) |
|---|
| 87 | elif answer_class == DeejaydDvdInfo: |
|---|
| 88 | ans.set_dvd_content(res) |
|---|
| 89 | else: |
|---|
| 90 | ans.contents = res |
|---|
| 91 | return ans |
|---|
| 92 | else: |
|---|
| 93 | return func(*__args, **__kw) |
|---|
| 94 | |
|---|
| 95 | interface_clean_func.__name__ = func.__name__ |
|---|
| 96 | return interface_clean_func |
|---|
| 97 | |
|---|
| 98 | return returns_deejaydanswer_instance |
|---|
| 99 | |
|---|
| 100 | |
|---|
| 101 | class DeejaydStaticPlaylist(deejayd.interfaces.DeejaydStaticPlaylist): |
|---|
| 102 | |
|---|
| 103 | def __init__(self, deejaydcore, pl_id, name): |
|---|
| 104 | self.deejaydcore = deejaydcore |
|---|
| 105 | self.db, self.library = deejaydcore.db, deejaydcore.audio_library |
|---|
| 106 | self.name = name |
|---|
| 107 | self.pl_id = pl_id |
|---|
| 108 | |
|---|
| 109 | @returns_deejaydanswer(DeejaydMediaList) |
|---|
| 110 | def get(self, first=0, length=-1): |
|---|
| 111 | songs = self.db.get_static_medialist(self.pl_id,\ |
|---|
| 112 | infos = self.library.media_attr) |
|---|
| 113 | last = length == -1 and len(songs) or int(first) + int(length) |
|---|
| 114 | return songs[int(first):last] |
|---|
| 115 | |
|---|
| 116 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 117 | def add_paths(self, paths): |
|---|
| 118 | ids = [] |
|---|
| 119 | for path in paths: |
|---|
| 120 | try: medias = self.library.get_all_files(path) |
|---|
| 121 | except deejayd.mediadb.library.NotFoundException: |
|---|
| 122 | try: medias = self.library.get_file(path) |
|---|
| 123 | except NotFoundException: |
|---|
| 124 | raise DeejaydError(_('Path %s not found in library') % path) |
|---|
| 125 | for m in medias: ids.append(m["media_id"]) |
|---|
| 126 | self.add_songs(ids) |
|---|
| 127 | |
|---|
| 128 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 129 | def add_songs(self, song_ids): |
|---|
| 130 | self.db.add_to_static_medialist(self.pl_id, song_ids) |
|---|
| 131 | self.db.connection.commit() |
|---|
| 132 | self.deejaydcore._dispatch_signame('playlist.update',\ |
|---|
| 133 | {"pl_id": self.pl_id}) |
|---|
| 134 | |
|---|
| 135 | |
|---|
| 136 | class DeejaydMagicPlaylist(deejayd.interfaces.DeejaydMagicPlaylist): |
|---|
| 137 | """ Magic playlist object """ |
|---|
| 138 | |
|---|
| 139 | def __init__(self, deejaydcore, pl_id, name): |
|---|
| 140 | self.deejaydcore = deejaydcore |
|---|
| 141 | self.db, self.library = deejaydcore.db, deejaydcore.audio_library |
|---|
| 142 | self.name = name |
|---|
| 143 | self.pl_id = pl_id |
|---|
| 144 | |
|---|
| 145 | @returns_deejaydanswer(DeejaydMediaList) |
|---|
| 146 | def get(self, first=0, length=-1): |
|---|
| 147 | properties = dict(self.db.get_magic_medialist_properties(self.pl_id)) |
|---|
| 148 | if properties["use-or-filter"] == "1": |
|---|
| 149 | filter = mediafilters.Or() |
|---|
| 150 | else: |
|---|
| 151 | filter = mediafilters.And() |
|---|
| 152 | if properties["use-limit"] == "1": |
|---|
| 153 | sort = [(properties["limit-sort-value"],\ |
|---|
| 154 | properties["limit-sort-direction"])] |
|---|
| 155 | limit = int(properties["limit-value"]) |
|---|
| 156 | else: |
|---|
| 157 | sort, limit = [], None |
|---|
| 158 | filter.filterlist = self.db.get_magic_medialist_filters(self.pl_id) |
|---|
| 159 | songs = self.library.search(filter, sort, limit) |
|---|
| 160 | last = length == -1 and len(songs) or int(first) + int(length) |
|---|
| 161 | return (songs[int(first):last], filter, None) |
|---|
| 162 | |
|---|
| 163 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 164 | def add_filter(self, filter): |
|---|
| 165 | if filter.type != "basic": |
|---|
| 166 | raise DeejaydError(\ |
|---|
| 167 | _("Only basic filters are allowed for magic playlist")) |
|---|
| 168 | self.db.add_magic_medialist_filters(self.pl_id, [filter]) |
|---|
| 169 | self.deejaydcore._dispatch_signame('playlist.update',\ |
|---|
| 170 | {"pl_id": self.pl_id}) |
|---|
| 171 | |
|---|
| 172 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 173 | def remove_filter(self, filter): |
|---|
| 174 | record_filters = self.db.get_magic_medialist_filters(self.pl_id) |
|---|
| 175 | new_filters = [] |
|---|
| 176 | for record_filter in record_filters: |
|---|
| 177 | if not filter.equals(record_filter): |
|---|
| 178 | new_filters.append(record_filter) |
|---|
| 179 | self.db.set_magic_medialist_filters(self.name, new_filters) |
|---|
| 180 | self.deejaydcore._dispatch_signame('playlist.update',\ |
|---|
| 181 | {"pl_id": self.pl_id}) |
|---|
| 182 | |
|---|
| 183 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 184 | def clear_filters(self): |
|---|
| 185 | self.db.set_magic_medialist_filters(self.name, []) |
|---|
| 186 | self.deejaydcore._dispatch_signame('playlist.update',\ |
|---|
| 187 | {"pl_id": self.pl_id}) |
|---|
| 188 | |
|---|
| 189 | @returns_deejaydanswer(DeejaydKeyValue) |
|---|
| 190 | def get_properties(self): |
|---|
| 191 | return dict(self.db.get_magic_medialist_properties(self.pl_id)) |
|---|
| 192 | |
|---|
| 193 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 194 | def set_property(self, key, value): |
|---|
| 195 | self.db.set_magic_medialist_property(self.pl_id, key, value) |
|---|
| 196 | self.deejaydcore._dispatch_signame('playlist.update',\ |
|---|
| 197 | {"pl_id": self.pl_id}) |
|---|
| 198 | |
|---|
| 199 | |
|---|
| 200 | class DeejaydWebradioList(deejayd.interfaces.DeejaydWebradioList): |
|---|
| 201 | |
|---|
| 202 | def __init__(self, deejaydcore): |
|---|
| 203 | self.deejaydcore = deejaydcore |
|---|
| 204 | self.source = self.deejaydcore.sources.get_source('webradio') |
|---|
| 205 | |
|---|
| 206 | @returns_deejaydanswer(DeejaydMediaList) |
|---|
| 207 | def get(self, first = 0, length = -1): |
|---|
| 208 | wrs = self.source.get_content() |
|---|
| 209 | last = length == -1 and len(wrs) or int(first) + int(length) |
|---|
| 210 | return wrs[int(first):last] |
|---|
| 211 | |
|---|
| 212 | @returns_deejaydanswer(DeejaydKeyValue) |
|---|
| 213 | def get_available_sources(self): |
|---|
| 214 | return dict(self.source.get_available_sources()) |
|---|
| 215 | |
|---|
| 216 | @returns_deejaydanswer(DeejaydList) |
|---|
| 217 | def get_source_categories(self, source_name): |
|---|
| 218 | return self.source.get_source_categories(source_name) |
|---|
| 219 | |
|---|
| 220 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 221 | def set_source(self, source_name): |
|---|
| 222 | self.source.set_source(source_name) |
|---|
| 223 | |
|---|
| 224 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 225 | def set_source_categorie(self, categorie): |
|---|
| 226 | self.source.set_source_categorie(categorie) |
|---|
| 227 | |
|---|
| 228 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 229 | def add_webradio(self, name, urls): |
|---|
| 230 | self.source.add(urls, name) |
|---|
| 231 | |
|---|
| 232 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 233 | def delete_webradios(self, wr_ids): |
|---|
| 234 | ids = map(int, wr_ids) |
|---|
| 235 | self.source.delete(ids) |
|---|
| 236 | |
|---|
| 237 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 238 | def clear(self): |
|---|
| 239 | self.source.clear() |
|---|
| 240 | |
|---|
| 241 | |
|---|
| 242 | class DeejaydQueue(deejayd.interfaces.DeejaydQueue): |
|---|
| 243 | |
|---|
| 244 | def __init__(self, deejaydcore): |
|---|
| 245 | self.deejaydcore = deejaydcore |
|---|
| 246 | self.source = self.deejaydcore.sources.get_source('queue') |
|---|
| 247 | |
|---|
| 248 | @returns_deejaydanswer(DeejaydMediaList) |
|---|
| 249 | def get(self, first = 0, length = -1): |
|---|
| 250 | songs = self.source.get_content() |
|---|
| 251 | last = length == -1 and len(songs) or int(first) + int(length) |
|---|
| 252 | return songs[int(first):last] |
|---|
| 253 | |
|---|
| 254 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 255 | def add_songs(self, song_ids, pos = None): |
|---|
| 256 | p = pos and int(pos) or None |
|---|
| 257 | try: self.source.add_song(song_ids, pos = p) |
|---|
| 258 | except deejayd.sources._base.SourceError, ex: |
|---|
| 259 | raise DeejaydError(str(ex)) |
|---|
| 260 | |
|---|
| 261 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 262 | def add_paths(self, paths, pos = None): |
|---|
| 263 | p = pos and int(pos) or None |
|---|
| 264 | try: self.source.add_path(paths, p) |
|---|
| 265 | except deejayd.sources._base.SourceError, ex: |
|---|
| 266 | raise DeejaydError(str(ex)) |
|---|
| 267 | |
|---|
| 268 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 269 | def load_playlists(self, pl_ids, pos=None): |
|---|
| 270 | pos = pos and int(pos) or None |
|---|
| 271 | try: self.source.load_playlist(pl_ids, pos) |
|---|
| 272 | except deejayd.sources._base.SourceError, ex: |
|---|
| 273 | raise DeejaydError(str(ex)) |
|---|
| 274 | |
|---|
| 275 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 276 | def move(self, ids, new_pos): |
|---|
| 277 | ids = [int(id) for id in ids] |
|---|
| 278 | try: self.source.move(ids, new_pos) |
|---|
| 279 | except deejayd.sources._base.SourceError, ex: |
|---|
| 280 | raise DeejaydError(str(ex)) |
|---|
| 281 | |
|---|
| 282 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 283 | def clear(self): |
|---|
| 284 | self.source.clear() |
|---|
| 285 | |
|---|
| 286 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 287 | def del_songs(self, ids): |
|---|
| 288 | ids = [int(id) for id in ids] |
|---|
| 289 | try: self.source.delete(ids) |
|---|
| 290 | except deejayd.sources._base.SourceError, ex: |
|---|
| 291 | raise DeejaydError(str(ex)) |
|---|
| 292 | |
|---|
| 293 | |
|---|
| 294 | class DeejaydPlaylistMode(deejayd.interfaces.DeejaydPlaylistMode): |
|---|
| 295 | """Audio playlist mode.""" |
|---|
| 296 | |
|---|
| 297 | def __init__(self, deejaydcore): |
|---|
| 298 | self.deejaydcore = deejaydcore |
|---|
| 299 | self.source = self.deejaydcore.sources.get_source("playlist") |
|---|
| 300 | |
|---|
| 301 | @returns_deejaydanswer(DeejaydMediaList) |
|---|
| 302 | def get(self, first=0, length=-1): |
|---|
| 303 | songs = self.source.get_content() |
|---|
| 304 | last = length == -1 and len(songs) or int(first) + int(length) |
|---|
| 305 | return songs[int(first):last] |
|---|
| 306 | |
|---|
| 307 | @returns_deejaydanswer(DeejaydKeyValue) |
|---|
| 308 | def save(self, name): |
|---|
| 309 | if name == "": |
|---|
| 310 | raise DeejaydError(_("Set a playlist name")) |
|---|
| 311 | return self.source.save(name) |
|---|
| 312 | |
|---|
| 313 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 314 | def add_paths(self, paths, pos=None): |
|---|
| 315 | p = pos and int(pos) or None |
|---|
| 316 | try: self.source.add_path(paths, pos = p) |
|---|
| 317 | except deejayd.sources._base.SourceError, ex: |
|---|
| 318 | raise DeejaydError(str(ex)) |
|---|
| 319 | |
|---|
| 320 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 321 | def add_songs(self, song_ids, pos=None): |
|---|
| 322 | p = pos and int(pos) or None |
|---|
| 323 | try: self.source.add_song(song_ids, pos = p) |
|---|
| 324 | except deejayd.sources._base.SourceError, ex: |
|---|
| 325 | raise DeejaydError(str(ex)) |
|---|
| 326 | |
|---|
| 327 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 328 | def loads(self, pl_ids, pos=None): |
|---|
| 329 | pos = pos and int(pos) or None |
|---|
| 330 | try: self.source.load_playlist(pl_ids, pos) |
|---|
| 331 | except deejayd.sources._base.SourceError, ex: |
|---|
| 332 | raise DeejaydError(str(ex)) |
|---|
| 333 | |
|---|
| 334 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 335 | def move(self, ids, new_pos): |
|---|
| 336 | ids = [int(id) for id in ids] |
|---|
| 337 | try: self.source.move(ids, int(new_pos)) |
|---|
| 338 | except deejayd.sources._base.SourceError, ex: |
|---|
| 339 | raise DeejaydError(str(ex)) |
|---|
| 340 | |
|---|
| 341 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 342 | def shuffle(self): |
|---|
| 343 | try: self.source.shuffle() |
|---|
| 344 | except deejayd.sources._base.SourceError, ex: |
|---|
| 345 | raise DeejaydError(str(ex)) |
|---|
| 346 | |
|---|
| 347 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 348 | def clear(self): |
|---|
| 349 | try: self.source.clear() |
|---|
| 350 | except deejayd.sources._base.SourceError, ex: |
|---|
| 351 | raise DeejaydError(str(ex)) |
|---|
| 352 | |
|---|
| 353 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 354 | def del_songs(self, ids): |
|---|
| 355 | ids = [int(id) for id in ids] |
|---|
| 356 | try: self.source.delete(ids) |
|---|
| 357 | except deejayd.sources._base.SourceError, ex: |
|---|
| 358 | raise DeejaydError(str(ex)) |
|---|
| 359 | |
|---|
| 360 | |
|---|
| 361 | class DeejaydPanel(deejayd.interfaces.DeejaydPanel): |
|---|
| 362 | |
|---|
| 363 | def __init__(self, deejaydcore): |
|---|
| 364 | self.deejaydcore = deejaydcore |
|---|
| 365 | self.source = self.deejaydcore.sources.get_source("panel") |
|---|
| 366 | |
|---|
| 367 | @returns_deejaydanswer(DeejaydMediaList) |
|---|
| 368 | def get(self, first=0, length=-1): |
|---|
| 369 | songs, filters, sort = self.source.get_content() |
|---|
| 370 | last = length == -1 and len(songs) or int(first) + int(length) |
|---|
| 371 | return (songs[int(first):last], filters, sort) |
|---|
| 372 | |
|---|
| 373 | @returns_deejaydanswer(DeejaydList) |
|---|
| 374 | def get_panel_tags(self): |
|---|
| 375 | return self.source.get_panel_tags() |
|---|
| 376 | |
|---|
| 377 | @returns_deejaydanswer(DeejaydKeyValue) |
|---|
| 378 | def get_active_list(self): |
|---|
| 379 | return self.source.get_active_list() |
|---|
| 380 | |
|---|
| 381 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 382 | def set_active_list(self, type, pl_id=""): |
|---|
| 383 | try: self.source.set_active_list(type, pl_id) |
|---|
| 384 | except TypeError: |
|---|
| 385 | raise DeejaydError(_("Not supported type")) |
|---|
| 386 | except deejayd.sources._base.SourceError, ex: |
|---|
| 387 | raise DeejaydError(str(ex)) |
|---|
| 388 | |
|---|
| 389 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 390 | def set_panel_filters(self, tag, values): |
|---|
| 391 | try: self.source.set_panel_filters(tag, values) |
|---|
| 392 | except deejayd.sources._base.SourceError, ex: |
|---|
| 393 | raise DeejaydError(str(ex)) |
|---|
| 394 | |
|---|
| 395 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 396 | def remove_panel_filters(self, tag): |
|---|
| 397 | try: self.source.remove_panel_filters(tag) |
|---|
| 398 | except deejayd.sources._base.SourceError, ex: |
|---|
| 399 | raise DeejaydError(str(ex)) |
|---|
| 400 | |
|---|
| 401 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 402 | def clear_panel_filters(self): |
|---|
| 403 | self.source.clear_panel_filters() |
|---|
| 404 | |
|---|
| 405 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 406 | def set_search_filter(self, tag, value): |
|---|
| 407 | try: self.source.set_search_filter(tag, value) |
|---|
| 408 | except deejayd.sources._base.SourceError, ex: |
|---|
| 409 | raise DeejaydError(str(ex)) |
|---|
| 410 | |
|---|
| 411 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 412 | def clear_search_filter(self): |
|---|
| 413 | self.source.clear_search_filter() |
|---|
| 414 | |
|---|
| 415 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 416 | def set_sorts(self, sorts): |
|---|
| 417 | try: self.source.set_sorts(sorts) |
|---|
| 418 | except deejayd.sources._base.SourceError, ex: |
|---|
| 419 | raise DeejaydError(str(ex)) |
|---|
| 420 | |
|---|
| 421 | class DeejaydVideo(deejayd.interfaces.DeejaydVideo): |
|---|
| 422 | """Video mode.""" |
|---|
| 423 | |
|---|
| 424 | def __init__(self, deejaydcore): |
|---|
| 425 | self.deejaydcore = deejaydcore |
|---|
| 426 | self.source = self.deejaydcore.sources.get_source('video') |
|---|
| 427 | |
|---|
| 428 | @returns_deejaydanswer(DeejaydMediaList) |
|---|
| 429 | def get(self, first = 0, length = -1): |
|---|
| 430 | videos, filters, sort = self.source.get_content() |
|---|
| 431 | last = length == -1 and len(videos) or int(first) + int(length) |
|---|
| 432 | return (videos[int(first):last], filters, sort) |
|---|
| 433 | |
|---|
| 434 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 435 | def set(self, value, type = "directory"): |
|---|
| 436 | try: self.source.set(type, value) |
|---|
| 437 | except deejayd.sources._base.SourceError, ex: |
|---|
| 438 | raise DeejaydError(str(ex)) |
|---|
| 439 | |
|---|
| 440 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 441 | def set_sorts(self, sorts): |
|---|
| 442 | try: self.source.set_sorts(sorts) |
|---|
| 443 | except deejayd.sources._base.SourceError, ex: |
|---|
| 444 | raise DeejaydError(str(ex)) |
|---|
| 445 | |
|---|
| 446 | class DeejayDaemonCore(deejayd.interfaces.DeejaydCore): |
|---|
| 447 | |
|---|
| 448 | def __init__(self, config=None): |
|---|
| 449 | deejayd.interfaces.DeejaydCore.__init__(self) |
|---|
| 450 | |
|---|
| 451 | if not config: |
|---|
| 452 | config = DeejaydConfig() |
|---|
| 453 | |
|---|
| 454 | self.db = database.init(config) |
|---|
| 455 | self.plugin_manager = plugins.PluginManager(config) |
|---|
| 456 | |
|---|
| 457 | self.player = player.init(self.db, config) |
|---|
| 458 | self.player.register_dispatcher(self) |
|---|
| 459 | |
|---|
| 460 | self.audio_library,self.video_library, self.watcher = \ |
|---|
| 461 | mediadb.init(self.db, self.player,config) |
|---|
| 462 | self.audio_library.register_dispatcher(self) |
|---|
| 463 | if self.video_library: |
|---|
| 464 | self.video_library.register_dispatcher(self) |
|---|
| 465 | |
|---|
| 466 | self.sources = sources.init(self.player, self.db, self.audio_library, |
|---|
| 467 | self.video_library, self.plugin_manager, |
|---|
| 468 | config) |
|---|
| 469 | self.sources.register_dispatcher(self) |
|---|
| 470 | for source in self.sources.sources_obj.values(): |
|---|
| 471 | source.register_dispatcher(self) |
|---|
| 472 | |
|---|
| 473 | if not self.db.structure_created: |
|---|
| 474 | self.update_audio_library(objanswer=False) |
|---|
| 475 | if self.video_library: |
|---|
| 476 | self.update_video_library(objanswer=False) |
|---|
| 477 | |
|---|
| 478 | # start inotify thread when we are sure that all init stuff are ok |
|---|
| 479 | if self.watcher: |
|---|
| 480 | self.watcher.start() |
|---|
| 481 | |
|---|
| 482 | def close(self): |
|---|
| 483 | for obj in (self.watcher,self.player,self.sources,self.audio_library,\ |
|---|
| 484 | self.video_library,self.db): |
|---|
| 485 | if obj != None: obj.close() |
|---|
| 486 | |
|---|
| 487 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 488 | def play_toggle(self): |
|---|
| 489 | if self.player.get_state() == player._base.PLAYER_PLAY: |
|---|
| 490 | current_media = self.player.get_playing() |
|---|
| 491 | if current_media['type'] == 'webradio': |
|---|
| 492 | # There is no point in pausing radio streams. |
|---|
| 493 | try: self.player.stop() |
|---|
| 494 | except player.PlayerError, err: raise DeejaydError(err) |
|---|
| 495 | else: |
|---|
| 496 | self.player.pause() |
|---|
| 497 | else: |
|---|
| 498 | try: self.player.play() |
|---|
| 499 | except player.PlayerError, err: |
|---|
| 500 | raise DeejaydError(err) |
|---|
| 501 | |
|---|
| 502 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 503 | def stop(self): |
|---|
| 504 | try: self.player.stop() |
|---|
| 505 | except player.PlayerError, err: |
|---|
| 506 | raise DeejaydError(err) |
|---|
| 507 | |
|---|
| 508 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 509 | def previous(self): |
|---|
| 510 | try: self.player.previous() |
|---|
| 511 | except player.PlayerError, err: |
|---|
| 512 | raise DeejaydError(err) |
|---|
| 513 | |
|---|
| 514 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 515 | def next(self): |
|---|
| 516 | try: self.player.next() |
|---|
| 517 | except player.PlayerError, err: |
|---|
| 518 | raise DeejaydError(err) |
|---|
| 519 | |
|---|
| 520 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 521 | def seek(self, pos, relative = False): |
|---|
| 522 | self.player.set_position(int(pos), relative) |
|---|
| 523 | |
|---|
| 524 | @returns_deejaydanswer(DeejaydMediaList) |
|---|
| 525 | def get_current(self): |
|---|
| 526 | medias = [] |
|---|
| 527 | current = self.player.get_playing() |
|---|
| 528 | if current != None: |
|---|
| 529 | medias.append(current) |
|---|
| 530 | return medias |
|---|
| 531 | |
|---|
| 532 | @require_mode("playlist") |
|---|
| 533 | def get_playlist(self): |
|---|
| 534 | return DeejaydPlaylistMode(self) |
|---|
| 535 | |
|---|
| 536 | @require_mode("panel") |
|---|
| 537 | def get_panel(self): |
|---|
| 538 | return DeejaydPanel(self) |
|---|
| 539 | |
|---|
| 540 | @require_mode("webradio") |
|---|
| 541 | def get_webradios(self): |
|---|
| 542 | return DeejaydWebradioList(self) |
|---|
| 543 | |
|---|
| 544 | @require_mode("video") |
|---|
| 545 | def get_video(self): |
|---|
| 546 | return DeejaydVideo(self) |
|---|
| 547 | |
|---|
| 548 | def get_queue(self): |
|---|
| 549 | return DeejaydQueue(self) |
|---|
| 550 | |
|---|
| 551 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 552 | def go_to(self, id, id_type = "id", source = None): |
|---|
| 553 | if id_type not in ("dvd_id","track","chapter","id","pos"): |
|---|
| 554 | raise DeejaydError(_("Bad value for id_type parm")) |
|---|
| 555 | if id_type != "dvd_id": |
|---|
| 556 | try: id = int(id) |
|---|
| 557 | except ValueError: |
|---|
| 558 | raise DeejaydError(_("Bad value for id parm")) |
|---|
| 559 | |
|---|
| 560 | try: self.player.go_to(id, id_type, source) |
|---|
| 561 | except player.PlayerError, err: |
|---|
| 562 | raise DeejaydError(err) |
|---|
| 563 | |
|---|
| 564 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 565 | def set_volume(self, volume_value): |
|---|
| 566 | self.player.set_volume(int(volume_value)) |
|---|
| 567 | |
|---|
| 568 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 569 | def set_option(self, source, option_name, option_value): |
|---|
| 570 | try: self.sources.set_option(source, option_name, option_value) |
|---|
| 571 | except sources.UnknownSourceException: |
|---|
| 572 | raise DeejaydError(_('Mode %s not supported') % source) |
|---|
| 573 | except sources._base.SourceError, ex: |
|---|
| 574 | raise DeejaydError(str(ex)) |
|---|
| 575 | |
|---|
| 576 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 577 | def set_mode(self, mode_name): |
|---|
| 578 | try: self.sources.set_source(mode_name) |
|---|
| 579 | except sources.UnknownSourceException: |
|---|
| 580 | raise DeejaydError(_('Mode %s not supported') % mode_name) |
|---|
| 581 | |
|---|
| 582 | @returns_deejaydanswer(DeejaydKeyValue) |
|---|
| 583 | def get_mode(self): |
|---|
| 584 | av_sources = self.sources.get_available_sources() |
|---|
| 585 | modes = {} |
|---|
| 586 | for s in self.sources.get_all_sources(): |
|---|
| 587 | modes[s] = s in av_sources |
|---|
| 588 | return modes |
|---|
| 589 | |
|---|
| 590 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 591 | def set_player_option(self, name, value): |
|---|
| 592 | if name != "aspect_ratio": |
|---|
| 593 | try: value = int(value) |
|---|
| 594 | except (ValueError,TypeError): |
|---|
| 595 | raise DeejaydError(_("Param value is not an int")) |
|---|
| 596 | |
|---|
| 597 | try: self.player.set_option(name, value) |
|---|
| 598 | except KeyError: |
|---|
| 599 | raise DeejaydError(_("Option %s does not exist") % name) |
|---|
| 600 | except NotImplementedError: |
|---|
| 601 | raise DeejaydError(_("Option %s is not supported for this backend")\ |
|---|
| 602 | % name) |
|---|
| 603 | except player.PlayerError, err: |
|---|
| 604 | raise DeejaydError(err) |
|---|
| 605 | |
|---|
| 606 | @returns_deejaydanswer(DeejaydKeyValue) |
|---|
| 607 | def get_status(self): |
|---|
| 608 | status = self.player.get_status() |
|---|
| 609 | status.extend(self.sources.get_status()) |
|---|
| 610 | status.extend(self.audio_library.get_status()) |
|---|
| 611 | if self.video_library: |
|---|
| 612 | status.extend(self.video_library.get_status()) |
|---|
| 613 | return dict(status) |
|---|
| 614 | |
|---|
| 615 | @returns_deejaydanswer(DeejaydKeyValue) |
|---|
| 616 | def get_stats(self): |
|---|
| 617 | ans = self.db.get_stats() |
|---|
| 618 | return dict(ans) |
|---|
| 619 | |
|---|
| 620 | @returns_deejaydanswer(DeejaydKeyValue) |
|---|
| 621 | def update_audio_library(self, force = False, sync = False): |
|---|
| 622 | return {'audio_updating_db': self.audio_library.update(force, sync)} |
|---|
| 623 | |
|---|
| 624 | @require_mode("video") |
|---|
| 625 | @returns_deejaydanswer(DeejaydKeyValue) |
|---|
| 626 | def update_video_library(self, force = False, sync = False): |
|---|
| 627 | if not self.video_library: |
|---|
| 628 | raise DeejaydError(_("Video mode disabled")) |
|---|
| 629 | return {'video_updating_db': self.video_library.update(force, sync)} |
|---|
| 630 | |
|---|
| 631 | @returns_deejaydanswer(DeejaydKeyValue) |
|---|
| 632 | def create_recorded_playlist(self, name, type): |
|---|
| 633 | if name == "": |
|---|
| 634 | raise DeejaydError(_("Set a playlist name")) |
|---|
| 635 | # first search if this pls already exist |
|---|
| 636 | try: self.db.get_medialist_id(name, type) |
|---|
| 637 | except ValueError: pass |
|---|
| 638 | else: # pls already exists |
|---|
| 639 | raise DeejaydError(_("This playlist already exists")) |
|---|
| 640 | |
|---|
| 641 | if type == "static": |
|---|
| 642 | pl_id = self.db.set_static_medialist(name, []) |
|---|
| 643 | elif type == "magic": |
|---|
| 644 | pl_id = self.db.set_magic_medialist_filters(name, []) |
|---|
| 645 | pl = DeejaydMagicPlaylist(self, pl_id, name) |
|---|
| 646 | # set default properties for this playlist |
|---|
| 647 | default = { |
|---|
| 648 | "use-or-filter": "0", |
|---|
| 649 | "use-limit": "0", |
|---|
| 650 | "limit-value": "50", |
|---|
| 651 | "limit-sort-value": "title", |
|---|
| 652 | "limit-sort-direction": "ascending" |
|---|
| 653 | } |
|---|
| 654 | for (k, v) in default.items(): |
|---|
| 655 | pl.set_property(k, v) |
|---|
| 656 | self._dispatch_signame('playlist.listupdate') |
|---|
| 657 | return {"pl_id": pl_id, "name": name, "type": type} |
|---|
| 658 | |
|---|
| 659 | def get_recorded_playlist(self, id, name = "", type = "static"): |
|---|
| 660 | try: pl_id, name, type = self.db.is_medialist_exists(id) |
|---|
| 661 | except TypeError: |
|---|
| 662 | raise DeejaydError(_("Playlist with id %s not found.") % str(id)) |
|---|
| 663 | if type == "static": |
|---|
| 664 | return DeejaydStaticPlaylist(self, pl_id, name) |
|---|
| 665 | elif type == "magic": |
|---|
| 666 | return DeejaydMagicPlaylist(self, pl_id, name) |
|---|
| 667 | |
|---|
| 668 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 669 | def erase_playlist(self, ids): |
|---|
| 670 | for id in ids: |
|---|
| 671 | self.db.delete_medialist(id) |
|---|
| 672 | self._dispatch_signame('playlist.listupdate') |
|---|
| 673 | |
|---|
| 674 | @returns_deejaydanswer(DeejaydMediaList) |
|---|
| 675 | def get_playlist_list(self): |
|---|
| 676 | return [{"name": pl, "id":id, "type":type}\ |
|---|
| 677 | for (id, pl, type) in self.db.get_medialist_list() if not \ |
|---|
| 678 | pl.startswith("__") or not pl.endswith("__")] |
|---|
| 679 | |
|---|
| 680 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 681 | def set_media_rating(self, media_ids, rating, type = "audio"): |
|---|
| 682 | if int(rating) not in range(0, 5): |
|---|
| 683 | raise DeejaydError(_("Bad rating value")) |
|---|
| 684 | |
|---|
| 685 | try: library = getattr(self, type+"_library") |
|---|
| 686 | except AttributeError: |
|---|
| 687 | raise DeejaydError(_('Type %s is not supported') % (type,)) |
|---|
| 688 | for id in media_ids: |
|---|
| 689 | try: library.set_file_info(int(id), "rating", rating) |
|---|
| 690 | except TypeError: |
|---|
| 691 | raise DeejaydError(_("%s library not activated") % type) |
|---|
| 692 | except deejayd.mediadb.library.NotFoundException: |
|---|
| 693 | raise DeejaydError(_("File with id %s not found") % str(id)) |
|---|
| 694 | |
|---|
| 695 | @returns_deejaydanswer(DeejaydFileList) |
|---|
| 696 | def get_audio_dir(self,dir = None): |
|---|
| 697 | if dir == None: dir = "" |
|---|
| 698 | try: contents = self.audio_library.get_dir_content(dir) |
|---|
| 699 | except deejayd.mediadb.library.NotFoundException: |
|---|
| 700 | raise DeejaydError(_('Directory %s not found in database') % dir) |
|---|
| 701 | |
|---|
| 702 | return dir, contents['dirs'], contents['files'] |
|---|
| 703 | |
|---|
| 704 | @returns_deejaydanswer(DeejaydKeyValue) |
|---|
| 705 | def get_audio_cover(self,media_id): |
|---|
| 706 | try: cover = self.audio_library.get_cover(media_id) |
|---|
| 707 | except deejayd.mediadb.library.NotFoundException: |
|---|
| 708 | raise DeejaydError(_('Cover not found')) |
|---|
| 709 | return cover |
|---|
| 710 | |
|---|
| 711 | @returns_deejaydanswer(DeejaydMediaList) |
|---|
| 712 | def audio_search(self, pattern, type = 'all'): |
|---|
| 713 | if type not in ('all','title','genre','filename','artist','album'): |
|---|
| 714 | raise DeejaydError(_('Type %s is not supported') % (type,)) |
|---|
| 715 | if type == "all": |
|---|
| 716 | filter = mediafilters.Or() |
|---|
| 717 | for tag in ('title','genre','artist','album'): |
|---|
| 718 | filter.combine(mediafilters.Contains(tag, pattern)) |
|---|
| 719 | else: |
|---|
| 720 | filter = mediafilters.Contains(type, pattern) |
|---|
| 721 | songs = self.audio_library.search(filter,\ |
|---|
| 722 | mediafilters.DEFAULT_AUDIO_SORT) |
|---|
| 723 | |
|---|
| 724 | return songs |
|---|
| 725 | |
|---|
| 726 | @require_mode("video") |
|---|
| 727 | @returns_deejaydanswer(DeejaydFileList) |
|---|
| 728 | def get_video_dir(self,dir = None): |
|---|
| 729 | if not self.video_library: |
|---|
| 730 | raise DeejaydError(_("Video mode disabled")) |
|---|
| 731 | |
|---|
| 732 | if dir == None: dir = "" |
|---|
| 733 | try: contents = self.video_library.get_dir_content(dir) |
|---|
| 734 | except deejayd.mediadb.library.NotFoundException: |
|---|
| 735 | raise DeejaydError(_('Directory %s not found in database') % dir) |
|---|
| 736 | |
|---|
| 737 | return dir, contents['dirs'], contents['files'] |
|---|
| 738 | |
|---|
| 739 | @require_mode("dvd") |
|---|
| 740 | @returns_deejaydanswer(DeejaydAnswer) |
|---|
| 741 | def dvd_reload(self): |
|---|
| 742 | try: self.sources.get_source("dvd").load() |
|---|
| 743 | except sources.dvd.DvdError, msg: |
|---|
| 744 | raise DeejaydError('%s' % msg) |
|---|
| 745 | |
|---|
| 746 | @require_mode("dvd") |
|---|
| 747 | @returns_deejaydanswer(DeejaydDvdInfo) |
|---|
| 748 | def get_dvd_content(self): |
|---|
| 749 | return self.sources.get_source("dvd").get_content() |
|---|
| 750 | |
|---|
| 751 | @returns_deejaydanswer(DeejaydList) |
|---|
| 752 | def mediadb_list(self, tag, filter): |
|---|
| 753 | return [x[0] for x in self.db.list_tags(tag, filter)] |
|---|
| 754 | |
|---|
| 755 | |
|---|
| 756 | # vim: ts=4 sw=4 expandtab |
|---|