[contrib] add a xbmc plugin that interracts with videoob

This commit is contained in:
Bezleputh 2014-09-02 16:48:17 +02:00
commit d1839bfcd4
23 changed files with 1036 additions and 0 deletions

View file

@ -0,0 +1 @@
# Dummy file to make this directory a package.

View file

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
from abc import ABCMeta, abstractmethod
class BaseAction():
__metaclass__ = ABCMeta
@abstractmethod
def _do(self, param=None):
"""
Overload this method in application type subclass
if you want to associate an action to the menu
"""
pass
actions = {}

View file

@ -0,0 +1,157 @@
# -*- coding: utf-8 -*-
import xbmc
import xbmcgui
import xbmcplugin
import xbmcaddon
import urllib
import sys
from traceback import print_exc
def get_addon():
if hasattr(sys.modules["__main__"], "addon_id"):
_id = sys.modules["__main__"].addon_id
return xbmcaddon.Addon(id=_id)
def get_translation(key):
addon = get_addon()
if addon:
return addon.getLocalizedString(int(key))
def get_settings(key):
addon = get_addon()
if addon:
return addon.getSetting(key)
def get_addon_dir():
addon = get_addon()
if addon:
addonDir = addon.getAddonInfo("path")
else:
addonDir = xbmc.translatePath("special://profile/addon_data/")
return addonDir
def display_error(msg):
xbmc.executebuiltin("XBMC.Notification(%s, %s)" % (get_translation('30200').decode('utf-8'), msg))
print msg
print_exc(msg)
def display_info(msg):
xbmc.executebuiltin("XBMC.Notification(%s, %s, 3000, DefaultFolder.png)" % (get_translation('30300').encode('utf-8'),
msg.encode('utf-8')))
#print msg
print_exc()
def parse_params(param_str):
param_dic = {}
# Parameters are on the 3rd arg passed to the script
param_str = sys.argv[2]
if len(param_str) > 1:
param_str = param_str.replace('?', '')
# Ignore last char if it is a '/'
if param_str[len(param_str) - 1] == '/':
param_str = param_str[0:len(param_str) - 2]
# Processing each parameter splited on '&'
for param in param_str.split('&'):
try:
# Spliting couple key/value
key, value = param.split('=')
except:
key = param
value = ''
key = urllib.unquote_plus(key)
value = urllib.unquote_plus(value)
# Filling dictionnary
param_dic[key] = value
return param_dic
def ask_user(content, title):
keyboard = xbmc.Keyboard(content, title)
keyboard.doModal()
if keyboard.isConfirmed() and keyboard.getText():
return keyboard.getText()
return ""
def create_param_url(param_dic, quote_plus=False):
"""
Create an plugin URL based on the key/value passed in a dictionary
"""
url = sys.argv[0]
sep = '?'
try:
for param in param_dic:
if quote_plus:
url = url + sep + urllib.quote_plus(param) + '=' + urllib.quote_plus(param_dic[param])
else:
url = "%s%s%s=%s" % (url, sep, param, param_dic[param])
sep = '&'
except Exception, msg:
display_error("create_param_url %s" % msg)
url = None
return url
def create_list_item(name, itemInfoType="Video", itemInfoLabels=None, iconimage="DefaultFolder.png",
c_items=None, isPlayable=False):
lstItem = xbmcgui.ListItem(label=name, iconImage=iconimage, thumbnailImage=iconimage)
if c_items:
lstItem.addContextMenuItems(c_items, replaceItems=True)
if itemInfoLabels:
iLabels = itemInfoLabels
else:
iLabels = {"Title": name, }
lstItem.setInfo(type=itemInfoType, infoLabels=iLabels)
if isPlayable:
lstItem.setProperty('IsPlayable', "true")
return lstItem
def add_menu_item(params={}):
url = create_param_url(params)
if params.get('name'):
if params.get('iconimage'):
lstItem = create_list_item(params.get('name'), iconimage=params.get('iconimage'))
else:
lstItem = create_list_item(params.get('name'))
xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=url, listitem=lstItem, isFolder=True)
else:
display_error('add_menu_item : Fail to add item to menu')
def add_menu_link(params={}):
if params.get('name') and params.get('iconimage') and params.get('url') and \
params.get('itemInfoLabels') and params.get('c_items'):
url = params.get('url')
lstItem = create_list_item(params.get('name'), iconimage=params.get('iconimage'),
itemInfoLabels=params.get('itemInfoLabels'), c_items=params.get('c_items'),
isPlayable=True)
xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=url, listitem=lstItem)
else:
display_error('add_menu_link : Fail to add item to menu')
def end_of_directory(update=False):
xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=True, updateListing=update) # , cacheToDisc=True)

View file

@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
import sys
if hasattr(sys.modules["__main__"], "common_xbmc"):
common_xbmc = sys.modules["__main__"].common_xbmc
else:
import common_xbmc
class BaseMenuItem():
def __init__(self, name, action, iconimage="DefaultFolder.png"):
self.params = {}
self.params['name'] = name
self.params['action'] = action
self.params['iconimage'] = iconimage
def get(self, element):
return self.params[element]
def add_to_menu(self):
common_xbmc.add_menu_item(self.params)
class BaseMenuLink(BaseMenuItem):
def __init__(self, name, url, action, iconimage="DefaultFolder.png"):
BaseMenuItem.__init__(self, name, action, iconimage)
self.params["url"] = url
def createVideoContextMenu(self):
return ""
def create_info_labels(self):
return ""
def add_to_menu(self):
self.params["itemInfoLabels"] = self.create_info_labels()
self.params["c_items"] = self.createVideoContextMenu()
common_xbmc.add_menu_link(self.params)

View file

@ -0,0 +1,62 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
import os
import re
import subprocess
import simplejson as json
if hasattr(sys.modules["__main__"], "common_xbmc"):
common_xbmc = sys.modules["__main__"].common_xbmc
else:
import common_xbmc
class Weboobmc():
def __init__(self, count=10):
self.count = count
def update(self):
#weboob-config update
self._call_weboob('weboob-config', 'update')
def _call_weboob(self, application, command, options={}, argument=""):
options['-n'] = self.count
_opt = " ".join(["%s %s " % (k, v) for k, v in options.items()])
_cmd = "%s %s %s %s" % (application, _opt, command, argument)
#print _cmd.encode('utf-8')
return subprocess.check_output(_cmd, shell=True)
def _json_call_weboob(self, application, command, options={}, argument=""):
options['-f'] = 'json'
try:
result = self._call_weboob(application, command, options, argument)
m = re.search(r"(\[{.+\}])", result)
if m:
result = u'%s' % m.group(1)
#print result
return json.loads(result) if result else []
except subprocess.CalledProcessError as e:
common_xbmc.display_error(" Error while calling weboob : %s " % e)
def get_loaded_backends(self, caps):
#weboob-config list ICapVideo -f json
backends = self._json_call_weboob('weboob-config', 'list', argument=caps)
for backend in backends:
if "_enabled=0" not in backend['Configuration']:
yield backend['Name'] # , self.get_backend_icon(backend['Module'])
def get_backend_icon(self, module):
if 'WEBOOB_WORKDIR' in os.environ:
datadir = os.environ.get('WEBOOB_WORKDIR')
else:
datadir = os.path.join(os.environ.get('XDG_DATA_HOME',
os.path.join(os.path.expanduser('~'), '.local', 'share')
), 'weboob')
icons_dir = os.path.join(datadir, 'icons')
return os.path.join(icons_dir, '%s.png' % module)
def is_category(self, obj):
return 'split_path' in obj.keys()

View file

@ -0,0 +1,80 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
from weboob.tools.application.base import BaseApplication
import os
import re
import subprocess
class Weboobmc(BaseApplication):
def __init__(self, count=10):
BaseApplication.__init__(self)
self.count = int(count)
self._is_default_count = False
def update(self):
self.weboob.update()
def get_backend_icon(self, module):
minfo = self.weboob.repositories.get_module_info(module)
return self.weboob.repositories.get_module_icon_path(minfo)
def obj_to_filename(self, obj, dest=None, default=None):
"""
This method can be used to get a filename from an object, using a mask
filled by information of this object.
All patterns are braces-enclosed, and are name of available fields in
the object.
:param obj: object type obj: BaseObject param dest: dest given by user (default None)
type dest: str param default: default file mask (if not given, this is
:'{id}-{title}.{ext}') type default: str rtype: str
"""
if default is None:
default = '{id}-{title}.{ext}'
if dest is None:
dest = '.'
if os.path.isdir(dest):
dest = os.path.join(dest, default)
def repl(m):
field = m.group(1)
if hasattr(obj, field):
return re.sub('[?:/]', '-', '%s' % getattr(obj, field))
else:
return m.group(0)
return re.sub(r'\{(.+?)\}', repl, dest)
def download_obj(self, obj, dest):
def check_exec(executable):
with open('/dev/null', 'w') as devnull:
process = subprocess.Popen(['which', executable], stdout=devnull)
if process.wait() != 0:
print 'Please install "%s"' % executable
return False
return True
dest = self.obj_to_filename(obj, dest)
if obj.url.startswith('rtmp'):
if not check_exec('rtmpdump'):
return 1
args = ('rtmpdump', '-e', '-r', obj.url, '-o', dest)
elif obj.url.startswith('mms'):
if not check_exec('mimms'):
return 1
args = ('mimms', '-r', obj.url, dest)
elif u'm3u8' == obj.ext:
_dest, _ = os.path.splitext(dest)
dest = u'%s.%s' % (_dest, 'mp4')
args = ('wget',) + tuple(line for line in self.read_url(obj.url) if not line.startswith('#')) + ('-O', dest)
else:
if check_exec('wget'):
args = ('wget', '-c', obj.url, '-O', dest)
elif check_exec('curl'):
args = ('curl', '-C', '-', obj.url, '-o', dest)
else:
return 1
os.spawnlp(os.P_WAIT, args[0], *args)