Created
December 17, 2012 19:35
-
-
Save jbeluch/4321270 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
redditmusic.resources.lib.playlists | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
This module contains an xbmcswift2.Module for handling the playlists | |
interaction for the addon. | |
:copyright: (c) 2012 by Jonathan Beluch | |
:license: GPLv3, see LICENSE.txt for more details. | |
''' | |
import functools | |
import xbmcswift2 | |
#from xbmcswift2 import module, xbmc, xbmcgui, adding_items | |
from xbmcswift2 import module, xbmc, xbmcgui | |
''' Example usage | |
from xbmcswift2 import Plugin | |
import xbcmswift2_playlists | |
plugin = Plugin() | |
lists = xbmcswift2_playlists.Playlists(plugin) | |
@plugin.route('/') | |
def index(): | |
items = [...] | |
items.append(lists.get_show_playlists_item()) | |
''' | |
def _run(plugin, endpoint, **items): | |
'''Returns a RunPlugin string for use in a context menu. | |
#:param endpoint: The endpoint to be used with playlists.url_for(). | |
#:param **items: Any keyword args to be passed to playlists.url_for(). | |
''' | |
return 'XBMC.RunPlugin(%s)' % plugin.url_for(endpoint, **items) | |
class Playlists(object): | |
def __init__(self, plugin, playlists_storage='my_playlists', temp_item_storage='temp_items'): | |
self.plugin = plugin | |
self.playlist_storage = 'my_playlists' | |
self.temp_item_storage = 'temp_items' | |
self._run = functools.partial(_run, self.plugin) | |
self.init_plugin() | |
def init_plugin(self): | |
self.init_routes() | |
# register a callback to process all playable list items | |
callback = functools.partial(self.add_ctx_to_playable_items, self) | |
# TODO: Build signals into xbmcswift2? | |
#adding_items.connect(callback, self.plugin) | |
def add_ctx_to_playable_items(self, sender, items, **extra): | |
my_playlists = self.plugin.get_storage(self.playlists_storage) | |
for item in items: | |
ctx = [] | |
for name in my_playlists.keys(): | |
label = 'Add to %s playlist' % name | |
action = self._run('add_to_playlist', playlist=name, url=item['path']) | |
ctx.append((label, action)) | |
item['context_menu'] = ctx | |
return items | |
def _add(self, url_ptn, meth, name=None): | |
if not name: | |
name = meth.__name__ | |
self.plugin.add_url_rule(url_ptn, meth, name) | |
def init_routes(self): | |
self._add('/playlists/', self.show_playlists) | |
self._add('/playlists/create/', self.create_playlist) | |
self._add('/playlists/delete/<playlist>/', self.remove_playlist) | |
self._add('/playlists/show/<name>/', self.show_playlist) | |
self._add('/playlists/removeitem/<playlist>/<url>/', self.remove_from_playlist) | |
self._add('/playlists/additem/<playlist>/<url>/', self.add_to_playlist) | |
def show_playlists(self): | |
'''Displays the 'Create Playlist' item as well as items for any | |
playlists the user has created. | |
''' | |
my_playlists = self.plugin.get_storage(self.playlist_storage) | |
import random | |
one_time_code = random.int() | |
create = { | |
'label': 'Create Playlist', | |
'path': self.plugin.url_for('create_playlist', code=one_time_code), | |
} | |
items = [{ | |
'label': name, | |
'path': self.plugin.url_for('show_playlist', name=name), | |
'context_menu': [('Delete this playlist', | |
self._run('remove_playlist', playlist=name)), ] | |
} for name in sorted(my_playlists.keys())] | |
return [create] + items | |
def create_playlist(self, code): | |
codes = self.plugin.get_storage('codes') | |
if code not in codes.keys(): | |
xbmc.executebuiltin(_run('create_playlist_ajax')) | |
codes[code] = True | |
return self.plugin.finish(self.show_playlists(), update_listing=True) | |
def create_playlist_ajax(self): | |
'''Creates a new empty user named playlist. User's can add playlist items | |
from the context menu of playable items elsewhere in the addon. | |
''' | |
# Remove when xbmcswift2 adds xbmc.keyboard in CLI mode | |
if xbmcswift2.CLI_MODE: | |
name = raw_input('Enter playlist name') | |
else: | |
name = self.plugin.keyboard(heading='Enter playlist name') | |
my_playlists = self.plugin.get_storage('my_playlists') | |
if name and name not in my_playlists.keys(): | |
my_playlists[name] = [] | |
def remove_playlist(self, playlist): | |
'''Deletes a user specified playlist. If the playlist is not empty, the | |
user will be presented with a yes/no confirmation dialog before deletion. | |
''' | |
my_playlists = self.plugin.get_storage('my_playlists') | |
num_items = len(my_playlists[playlist]) | |
delete = True | |
if num_items > 0: | |
dialog = xbmcgui.Dialog() | |
delete = dialog.yesno(self.plugin.name, 'Are you sure you wish to delete?') | |
if delete: | |
del my_playlists[playlist] | |
my_playlists.sync() | |
xbmc.executebuiltin('Container.Refresh') | |
def show_playlist(self, name): | |
'''Displays a user's custom playlist. The playlist items are persisted via | |
plugin storage. | |
''' | |
my_playlists = self.plugin.get_storage(self.playlist_storage) | |
items = my_playlists[name] | |
# Augment the existing list items with a context menu item to 'Remove from | |
# Playlist'. | |
for item in items: | |
ctx_items = [ | |
('Remove this item from playlist', | |
self._run('remove_from_playlist', playlist=name, url=item['path'])) | |
] | |
item['context_menu'] = ctx_items | |
return items | |
def remove_from_playlist(self, playlist, url): | |
'''Deletes an item from the given playlist whose url matches the provided | |
url. | |
''' | |
# We don't have the full item in temp_items, so have to iterate over items | |
# in the list and match on url | |
my_playlists = self.plugin.get_storage('my_playlists') | |
try: | |
match = (item for item in my_playlists[playlist] | |
if item['path'] == url).next() | |
my_playlists[playlist].remove(match) | |
my_playlists.sync() | |
xbmc.executebuiltin('Container.Refresh') | |
except StopIteration: | |
pass | |
def add_to_playlist(self, playlist, url): | |
'''Adds an item to the given playlist. The list item added will be pulled | |
from temp_items storage and matched on the provided url. | |
''' | |
temp_items = self.plugin.get_storage('temp_items') | |
item = temp_items[url] | |
my_playlists = self.plugin.get_storage('my_playlists') | |
my_playlists[playlist].append(item) | |
my_playlists.sync() | |
def get_show_playlists_item(self): | |
return { | |
'label': 'Show Playlists', | |
'path': self.plugin.url_for('show_playlists'), | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment