Skip to content

Instantly share code, notes, and snippets.

@dbiesecke
Last active October 2, 2019 20:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dbiesecke/764330cc8f94887ead94154ec0f2dcda to your computer and use it in GitHub Desktop.
Save dbiesecke/764330cc8f94887ead94154ec0f2dcda to your computer and use it in GitHub Desktop.
Kodi Server Test
# -*- coding: utf-8 -*-
'''
Created on 9/05/2014
@author: pybquillast
'''
import sys
import os
import imp
import logging
import re
logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())
class KodiScriptImporter:
KODI_STUBS = ''
KODI_HOME = ''
KODI = ''
archive = None
prefix = ''
path_cache = {}
def __init__(self, kodi = '', kodi_home = ''):
self.stack = []
self.toSave = []
self.nullstack = set()
self.path = None
self.pathprefix = pathprefix = 'script.module'
self.setPaths(kodi, kodi_home)
self.addonDir = None
self.initRootPaths()
def setPaths(self, kodi, kodi_home):
baseDirectory = os.path.dirname(__file__)
if os.path.exists(os.path.join(os.path.dirname(baseDirectory), 'xbmcStubs')):
baseDirectory = os.path.join(os.path.dirname(baseDirectory), 'xbmcStubs')
self.KODI_STUBS = baseDirectory
if sys.platform[:3] == 'win':
kodi = kodi or os.path.join(os.path.expandvars("$PROGRAMFILES"), "Kodi", "addons")
#kodi_home = kodi_home or os.path.join(os.path.expandvars("$APPDATA"), "Kodi", "addons")
kodi_home = kodi_home or os.path.join("/home/user", "addons")
self.KODI = "/usr/share/kodi/addons"
self.KODI_HOME = kodi_home
if not all(map(os.path.exists,[self.KODI, self.KODI_HOME])):
msg = "kodi: " + self.KODI + ' or kodi_home: ' + self.KODI_HOME + "doesn't exits"
logger.log(logging.CRITICAL, msg)
raise ImportError(msg)
self.path_cache = {}
stubs = ['xbmc', 'xbmcgui', 'xbmcaddon', 'xbmcplugin', 'xbmcvfs']
for stub in stubs:
stubmod = os.path.join(self.KODI_STUBS, stub)
if os.path.exists(stubmod + '.py'):
self.path_cache[stub] = stubmod
else:
msg = stubmod + '.py' + " doesn't exits"
logger.log(logging.CRITICAL, msg)
raise ImportError(msg)
def setAddonDir(self, addonDir):
if self.addonDir:
self.rootPaths.pop()
keys = [key for key, value in self.path_cache.items() if value.startswith(self.addonDir)]
for akey in keys:
self.path_cache.pop(akey)
try:
sys.modules.pop(akey)
except:
pass
sys.path_importer_cache.clear()
self.addonDir = addonDir
self.rootPaths.append(addonDir)
pass
def initRootPaths(self):
self.rootPaths = [self.KODI_STUBS]
pattern = r'<extension\s+point="xbmc.python.(?P<type>[^"]+)"\s+library="(?P<lib>[^"]+)"\s*/*>'
for apath in [self.KODI, self.KODI_HOME]:
dirs = [adir for adir in os.walk(apath).next()[1] if adir.startswith('script.module')]
for adir in dirs:
with open(os.path.join(apath, adir,'addon.xml'), 'r') as f:
content = f.read()
atype, alib = re.findall(pattern, content)[0]
root = os.path.join(apath, adir, alib)
self.rootPaths.append(root)
def find_module(self, fullname, path = None):
basename, sep, lastname = fullname.rpartition('.') # @UnusedVariable
rootname = fullname.partition('.')[0]
testpath = self.path_cache.get(fullname, '')
if testpath: return self
if not path and fullname == rootname:
for aroot in self.rootPaths:
testpath = os.path.join(aroot, rootname)
if os.path.exists(os.path.join(testpath, '__init__.py')) or os.path.exists(testpath + '.py'):
break
else:
return None
elif path and (path[0].startswith(self.KODI_HOME) or path[0].startswith(self.KODI)):
testpath = os.path.join(path[0], lastname)
else:
return None
if os.path.exists(testpath) or os.path.exists(testpath + '.py'):
logger.log(logging.INFO, 'Importing module ' + fullname)
self.path_cache[fullname] = os.path.normpath(testpath)
msg = 'found:' + fullname + ' at: ' + testpath
logger.log(logging.DEBUG, msg)
return self
msg = 'Not found: ' + fullname
logger.log(logging.DEBUG, msg)
self.nullstack.add(fullname)
return
def get_code(self,fullname):
src = self.get_source(fullname)
code = compile(src, self.get_filename(fullname), 'exec')
return code
def get_data(self, pathname):
try:
u = open(pathname, 'rb')
data = u.read()
return data
except:
raise ImportError("Can't find %s" % pathname)
def get_filename(self, fullname):
scriptPath = self.path_cache[fullname]
if self.is_package(fullname): return os.path.join(scriptPath, '__init__.py')
return scriptPath + '.py'
def get_source(self, fullname):
filename = self.get_filename(fullname)
return self.get_data(filename)
def is_package(self, fullname):
fullpath = self.path_cache[fullname]
return os.path.exists(os.path.join(fullpath, '__init__.py'))
def load_module(self, fullname):
mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
self.stack.append(fullname)
mod.__file__ = self.get_filename(fullname)
mod.__loader__ = self
mod.__package__ = fullname.rpartition('.')[0]
code = self.get_code(fullname)
if self.is_package(fullname):
mod.__package__ = fullname
mod.__path__ = [self.path_cache[fullname]]
try:
exec(code, mod.__dict__)
except:
if self.stack[0] == fullname:
msg = '***' + fullname + '*** An error has ocurred. The following modules that were loaded before the error ocurred, are going to be unloaded: '
logger.log(logging.DEBUG, msg)
while self.stack:
key = self.stack.pop()
if sys.modules.has_key(key):
sys.modules.pop(key)
logger.log(logging.DEBUG, key)
pass
else:
if self.stack[0] == fullname:
logger.log(logging.INFO, 'IMPORT %s successful' % (fullname))
if self.stack[1:]:
msg = 'The following modules were loaded in the process : '
logger.log(logging.INFO, msg)
for key in sorted(self.stack[1:]): logger.log(logging.INFO, key)
for fullname, fullpath in sorted(self.toSave):
self.path_cache[fullname] = os.path.splitext(fullpath)[0]
logger.log(logging.INFO, fullname)
pass
finally:
if self.stack[0] == fullname:
self.stack = []
if self.nullstack:
msg = '******The following dummy modules are going to be unloaded : *****'
logger.log(logging.DEBUG, msg)
toSave = []
while self.nullstack:
key = self.nullstack.pop()
if sys.modules.has_key(key) and not sys.modules[key]:
rootname = key.rpartition('.')[2]
if sys.modules.has_key(rootname) and hasattr(sys.modules[rootname], '__file__'):
filename = sys.modules[rootname].__file__
bFlag = filename.startswith(self.KODI_HOME) or filename.startswith(self.KODI)
bFlag = bFlag and not self.path_cache.has_key(rootname)
if bFlag:
toSave.append((rootname, sys.modules[rootname].__file__))
sys.modules.pop(key)
logger.log(logging.DEBUG, key)
if toSave:
msg = '******The following modules were created outside the KodiScriptImporter : *****'
logger.log(logging.DEBUG, msg)
for fullname, fullpath in sorted(toSave):
logger.log(logging.DEBUG, fullname.ljust(15) + ' ' + fullpath)
self.toSave.append((fullname, fullpath))
pass
return mod
def install(self, meta_path = True):
if meta_path:
sys.meta_path.append(self)
logger.log(logging.INFO, 'Installed as Meta Path')
else:
class trnClass:
def __init__(aninst, path):
if path == self.pathprefix:aninst.path = None
elif path.startswith(self.KODI_HOME) or path.startswith(self.KODI): aninst.path = [path]
else: raise ImportError
def find_module(aninst, fullname, path = None):
return self.find_module(fullname, aninst.path)
def __getattr__(aninst, attr):
return getattr(self, attr)
sys.path_hooks.append(trnClass)
sys.path.insert(0, self.pathprefix)
logger.log(logging.INFO, 'Installed as Path Hook')
import xbmc
logger.log(logging.INFO, 'Mapping "special://xbmc" to %s' % self.KODI)
xbmc.special_xbmc = self.KODI
logger.log(logging.INFO, 'Mapping "special://home" to %s' % os.path.dirname(self.KODI_HOME))
xbmc.special_home = os.path.dirname(self.KODI_HOME)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, format='%(asctime)-15s %(levelname)-6s %(message)s')
meta_path = True
importador = KodiScriptImporter()
importador.install(meta_path)
import xbmc
import metahandler
import urlresolver # @UnresolvedImport
print urlresolver.resolve('https://www.youtube.com/watch?v=EiOglTERPEo')
# -*- coding: utf-8 -*-
'''
Created on 29/03/2015
@author: Alex Montes Barrios
'''
import os
import sys
import urllib
import urlparse
import hashlib
import webbrowser
import logging
import StringIO
import traceback
import KodiScriptImporter
importer = KodiScriptImporter.KodiScriptImporter()
importer.install(True)
import xbmc, xbmcgui, xbmcaddon, xbmcplugin, xbmcvfs # @UnresolvedImport
from wsgiref.simple_server import make_server
class newModules:
def __init__(self, aDict):
self.dict = aDict
self._initKeys = aDict.keys()
def clear(self):
for key in self.dict.keys():
if key in self._initKeys: continue
self.dict.pop(key)
pass
def __getattr__(self, attr):
return getattr(self.dict,attr)
class KodiFrontEnd:
htmlHead = '''<html><head><style>
div.img {margin: 5px; border: 1px solid #ccc; float: left; width: 250px;}
div.img:hover {border: 1px solid #777;}
div.img img {width: 100%; height: 250px;}
div.desc {margin-top: 10px; text-align: center; font-size: 15px; line-height: 1.0; width: 100%; height: 32px;}
.menu {float: right; font-size: 30px;}
</style></head><body>
<div class="header" style="background: lime;">
<a class="menu" href="/file://log">Log File</a>
<h1>KodiServer</h1>
</div>
<div>'''
htmlTail = '''</div></body></html>'''
htmlStr = '\n<div class="img">\n\t<a href="{0}">' \
'\n\t\t<img src="{1}" alt="{2}" width="400" height="300">' \
'\n\t\t<div class="desc">{2}</div>\n\t</a>\n</div>'
mediaPlayer = '''
<!doctype html>
<head>
<link href="http://vjs.zencdn.net/5.7.1/video-js.css" rel="stylesheet">
<!-- If you'd like to support IE8 -->
<script src="http://vjs.zencdn.net/ie8/1.1.2/videojs-ie8.min.js"></script>
<style>
.menu {float: right; font-size: 30px;}
video.my-video {width:100%; height:100%;}
</style>
</head>
<body>
<div class="header" style="background: lime;">
<a class="menu" href="/file://log">Log File</a>
<h1>KodiServer</h1>
</div>
<videotag>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script src="http://vjs.zencdn.net/5.7.1/video.js"></script>
</body>
'''
errorPage = '<html><head><title>Kodi Error</title></head><body bgcolor="white"><br>' \
'<table border="0" align="center" width="720"><tr><td><center><h1>Kodi Error</h1></center>' \
'<table style="border: 1px solid #f2f2f2;" bgcolor="#ffffff" align="center" width="720">' \
'<tr><td border="0"><tr><td><br><center><h2>An error has ocurred, check the <a href="/file://log">log file</a> for more information</h2>' \
'</center><br></td></tr></table><br><center>kodiserver</center></td></tr></table></body></html>'
def __init__(self):
self.kodiDirectory = []
self.addonID = ''
self.htmlPage = ''
self.stEd = StringIO.StringIO()
self.setLogger()
self.ORIGINAL_PYTHONPATH = sys.path
self.redefineXbmcMethods()
def setLogger(self):
self.logger = logging.getLogger(__name__)
self.logger.setLevel(xbmc.LOGDEBUG+1)
ch = logging.StreamHandler(self.stEd)
ch.setLevel(xbmc.LOGDEBUG+1)
formatter = logging.Formatter('%(asctime)s - %(message)s')
ch.setFormatter(formatter)
self.logger.addHandler(ch)
def initGlobals(self):
theGlobals = {}
exec 'import sys' in theGlobals
theGlobals['sys'].argv = [0,0,0]
exec 'import xbmc, xbmcgui, xbmcplugin' in theGlobals
theGlobals["__name__"] = "__main__"
self.theGlobals = theGlobals
def redefineXbmcMethods(self):
sys.modules['xbmc'].log = self.log
sys.modules['xbmcplugin'].setResolvedUrl = self.setResolvedUrl
sys.modules['xbmcplugin'].addDirectoryItem = self.addDirectoryItem
sys.modules['xbmcplugin'].endOfDirectory = self.endOfDirectory
def log(self, msg, level = 2):
logLst = ['DEBUG', 'INFO', 'NOTICE', 'WARNING',
'ERROR', 'SEVERE', 'FATAL', 'NONE']
msg = '{0:>9s}:{1}'.format(logLst[level], msg)
self.logger.log(level+1, msg)
def setResolvedUrl(self, handle, succeeded, listitem):
if not succeeded: return
url = listitem.getProperty('path')
iconImage = listitem.getProperty('thumbnailImage')
videoUrl = url.split('|', 1)[0]
videoFile = videoUrl.split('?', 1)[0]
videoType = videoFile.rpartition('.')[2]
if len(videoType) > 3: videoType = 'mp4'
videoTag = '<video id="my-video" class="video-js" controls preload="auto" poster="{0}" data-setup="{1}">' \
'<source src="{2}" type="video/{3}">'.format(iconImage, '{}', videoUrl, videoType )
self.htmlPage = self.mediaPlayer.replace('<videotag>', videoTag)
pass
def addDirectoryItem(self, handle, url, listitem, isFolder = False, totalItems = 0):
kwargs = {'handle':handle, 'url':url, 'listitem':listitem, 'isFolder':isFolder, 'totalItems':totalItems}
self.kodiDirectory.append(kwargs)
def endOfDirectory(self, handle, succeeded = True, updateListing = False, cacheToDisc = True):
if not succeeded: return
options = list(self.kodiDirectory)
self.kodiDirectory = []
self.fillListBox(options)
def kodiAddons(self):
pathDir = xbmc.translatePath('special://home/addons')
addons = [addon for addon in os.listdir(pathDir) if addon.startswith('plugin.video')]
for addonId in sorted(addons):
kwargs = {'handle':0, 'isFolder':True, 'totalItems':0}
addon = xbmcaddon.Addon(addonId)
if not addon: continue
kwargs['url'] = 'plugin://' + addonId + '/?'
name = addon.getAddonInfo('name')
listitem = xbmcgui.ListItem(label = name , iconImage = addon.getAddonInfo('icon'))
listitem.setProperty('fanart_image', addon.getAddonInfo('fanart'))
kwargs['listitem'] = listitem
self.addDirectoryItem(**kwargs)
self.endOfDirectory(handle = 0)
return self.htmlPage
def runAddon(self, url):
self.initGlobals()
if url == '/': return self.kodiAddons()
urlScheme = urlparse.urlparse(url)
if urlScheme.scheme != 'plugin': return # Plugin diferente
pluginId, urlArgs = urllib.splitquery(url)
self.theGlobals['sys'].argv = [pluginId, self.theGlobals['sys'].argv[1] + 1, '?' + (urlArgs or '')]
self.kodiDirectory = []
actualID = urlScheme.netloc
addonDir = xbmc.translatePath('special://home/addons/' + actualID)
self.addonID = actualID
self.theGlobals['sys'].modules = newModules(self.theGlobals['sys'].modules)
sourceCode = self.getCompiledAddonSource(actualID)
importer.setAddonDir(addonDir)
try:
exec(sourceCode, self.theGlobals)
except:
msg = traceback.format_exc()
self.log(msg)
self.htmlPage = self.errorPage
return self.htmlPage
def getCompiledAddonSource(self, addonId):
addon = xbmcaddon.Addon(addonId)
path = addon.getAddonInfo('path')
addonSourceFile = addon.getAddonInfo('library')
addonFile = os.path.join(path, addonSourceFile)
with open(addonFile, 'r') as f:
addonSource = f.read()
return compile(addonSource, addonFile, 'exec')
def fillListBox(self, vrtFolder, selItem = 0):
basePath = xbmc.translatePath('special://home')
self.options = vrtFolder
htmlPage = self.htmlHead
for pos, item in enumerate(vrtFolder):
itemLabel = item['listitem'].getLabel()
itemUrl = '/' + item['url']
imtags = ['iconImage', 'thumbnailImage']
itemIcon = ''
for imtag in imtags:
image = item['listitem'].getProperty(imtag)
if not image: continue
if not itemIcon or image.startswith('http://') or not os.path.exists(itemIcon):
itemIcon = image
if image.startswith('http://') or os.path.exists(itemIcon):break
if itemIcon.lower() == 'defaultfolder.png': itemIcon = "http://www.graphicsfuel.com/wp-content/uploads/2012/03/folder-icon-512x512.png"
if os.path.exists(itemIcon):
if itemIcon.startswith(basePath):
hashval = hashlib.md5(open(itemIcon, 'rb').read()).hexdigest()
fpath, fname = os.path.split(itemIcon)
fpath = os.path.join('special://home', os.path.relpath(fpath, basePath))
fpath = fpath.replace('\\', '/')
itemIcon = '/' + fpath + '/?' + '&'.join(['fname=' + fname, 'key=' + hashval])
else:
itemIcon = 'file:///' + itemIcon
htmlPage += self.htmlStr.format(itemUrl, itemIcon, itemLabel)
self.htmlPage = htmlPage + self.htmlTail
kodi = KodiFrontEnd()
def getFile(url):
basePath, queryStr = url.split('/?', 1)
query = urlparse.parse_qs(queryStr)
fname, key = query['fname'][0], query['key'][0]
basePath = xbmc.translatePath(basePath)
fname = os.path.join(basePath, fname)
answ = {}
if key == hashlib.md5(open(fname, 'rb').read()).hexdigest():
answ['Content-Type'] = 'image/' + os.path.splitext(fname)[1][1:]
with open(fname, 'rb') as f: answ['body'] = f.read()
else:
answ['body'] = '<html><head><title>403 Forbidden</title></head>' \
'<body bgcolor="white"><br>' \
'<table border="0" align="center" width="720"><tr><td><h1>403 Forbidden</h1>' \
'<table style="border: 1px solid #f2f2f2;" bgcolor="#ffffff" align="center" width="720">' \
'<tr><td border="0"><tr><td><br><center><h2> server refuses to respond to request </h2>' \
'</center><br></td></tr></table><br><center>kodiserver</center></td></tr></table></body></html>'
answ['Content-Type'] = 'text/html'
return answ
def application (environ, start_response):
url = environ.get('PATH_INFO', '')[1:] or '/'
status = '200 OK'
response_headers = []
if environ.get('QUERY_STRING'):
url += '?' + environ['QUERY_STRING']
if url == '/' or url.startswith('plugin://'):
response_headers.append(('Content-type', 'text/html'))
response_body = kodi.runAddon(url)
elif url.startswith('special://'):
response = getFile(url)
response_headers.append(('Content-type', response['Content-Type']))
response_body = response.pop('body')
elif url == 'file://log':
response_headers.append(('Content-type', 'text/plain'))
response_body = kodi.stEd.getvalue() or 'NOT ACTIVITY LOGGED'
else:
status = '404 Not Found'
response_headers.append(('Content-type', 'text/html'))
response_body = '<html><body><h1>Error url not in this server</h1></body></html>'
response_headers.append(('Content-Length', str(len(response_body))))
start_response(status, response_headers)
return [response_body]
if __name__ == '__main__':
server_address = ('localhost', 5000)
httpd = make_server (
server_address[0], # The host name
server_address[1], # A port number where to wait for the request
application # The application object name, in this case a function
)
webbrowser.open('http://{}:{}'.format(*server_address))
httpd.serve_forever()
pass
'''
Created on 9/05/2014
@author: pybquillast
This module has been ported from xbmcstubs:
__author__ = 'Team XBMC <http://xbmc.org>'
__credits__ = 'Team XBMC'
__date__ = 'Thu Apr 17 08:03:38 BST 2014'
__platform__ = 'ALL'
__version__ = '2.14.0'
'''
import sys
import os
import re
import time
import xbmcgui
# variables
special_xbmc = None
special_home = None
xbmcLoglevel = -1
#
# CONSTANTS
#
CAPTURE_FLAG_CONTINUOUS = 1
CAPTURE_FLAG_IMMEDIATELY = 2
CAPTURE_STATE_DONE = 3
CAPTURE_STATE_FAILED = 4
CAPTURE_STATE_WORKING = 0
DRIVE_NOT_READY = 1
ENGLISH_NAME = 2
ISO_639_1 = 0
ISO_639_2 = 1
LOGDEBUG = 0
LOGINFO = 1
LOGNOTICE = 2
LOGWARNING = 3
LOGERROR = 4
LOGSEVERE = 5
LOGFATAL = 6
LOGNONE = 7
PLAYER_CORE_AUTO = 0
PLAYER_CORE_DVDPLAYER = 1
PLAYER_CORE_MPLAYER = 2
PLAYER_CORE_PAPLAYER = 3
PLAYLIST_MUSIC = 0
PLAYLIST_VIDEO = 1
SERVER_AIRPLAYSERVER = 2
SERVER_EVENTSERVER = 6
SERVER_JSONRPCSERVER = 3
SERVER_UPNPRENDERER = 4
SERVER_UPNPSERVER = 5
SERVER_WEBSERVER = 1
SERVER_ZEROCONF = 7
TRAY_CLOSED_MEDIA_PRESENT = 96
TRAY_CLOSED_NO_MEDIA = 64
TRAY_OPEN = 16
abortRequested = False
#
# Class
#
class InfoTagMusic(object):
'''
Kodi's music info tag class.
To get music info tag data of currently played source.
Note
Info tag load is only be possible from present player class.
Example:
1 ...
2 tag = xbmc.Player().getMusicInfoTag()
3
4 title = tag.getTitle()
5 url = tag.getURL()
6 ...
'''
def getAlbum(self):
"""
--returns a string.
"""
pass
def getAlbumArtist(self):
"""
--returns a string.
"""
pass
def getArtist(self):
"""
--returns a string.
"""
pass
def getComment(self):
"""
--returns a string.
"""
pass
def getDisc(self):
"""
--returns a integer.
"""
pass
def getDuration(self):
"""
--returns a integer.
"""
pass
def getGenre(self):
"""
--returns a string.
"""
pass
def getLastPlayed(self):
"""
--returns a string.
"""
pass
def getListeners(self):
"""
--returns a integer.
"""
pass
def getLyrics(self):
"""
--returns a string.
"""
pass
def getPlayCount(self):
"""
--returns a integer.
"""
pass
def getReleaseDate(self):
"""
--returns a string.
"""
pass
def getTitle(self):
"""
--returns a string.
"""
pass
def getTrack(self):
"""
--returns a integer.
"""
pass
def getURL(self):
"""
--returns a string.
"""
pass
class InfoTagVideo(object):
'''
Kodi's video info tag class.
To get video info tag data of currently played source.
Note
Info tag load is only be possible from present player class.
Example:
1 ...
2 tag = xbmc.Player().getVideoInfoTag()
3
4 title = tag.getTitle()
5 file = tag.getFile()
6 ...
'''
def getCast(self):
"""
--returns a string.
"""
pass
def getDirector(self):
"""
--returns a string.
"""
pass
def getFile(self):
"""
--returns a string.
"""
pass
def getFirstAired(self):
"""
--returns a string.
"""
pass
def getGenre(self):
"""
--returns a string.
"""
pass
def getIMDBNumber(self):
"""
--returns a string.
"""
pass
def getLastPlayed(self):
"""
--returns a string.
"""
pass
def getOriginalTitle(self):
"""
--returns a string.
"""
pass
def getPath(self):
"""
--returns a string.
"""
pass
def getPictureURL(self):
"""
--returns a string.
"""
pass
def getPlayCount(self):
"""
--returns a integer.
"""
pass
def getPlot(self):
"""
--returns a string.
"""
pass
def getPlotOutline(self):
"""
--returns a string.
"""
pass
def getPremiered(self):
"""
--returns a string.
"""
pass
def getRating(self):
"""
--returns a float (double where supported).
"""
pass
def getTagLine(self):
"""
--returns a string.
"""
pass
def getTitle(self):
"""
--returns a string.
"""
pass
def getVotes(self):
"""
--returns a string.
"""
pass
def getWritingCredits(self):
"""
--returns a string.
"""
pass
def getYear(self):
"""
--returns a integer.
"""
pass
class Keyboard(object):
def __init__(self, default = '', heading = '', hidden = False):
"""
--Creates a newKeyboard object with default text
heading and hidden input flag if supplied.
default : [opt] string - default text entry.
heading : [opt] string - keyboard heading.
hidden : [opt] boolean - True for hidden text entry.
example:
- kb =xbmc.Keyboard ('default', 'heading', True)
- kb.setDefault('password') # optional
- kb.setHeading('Enter password') # optional
- kb.setHiddenInput(True) # optional
- kb.doModal()
- if (kb.isConfirmed()):
- text = kb.getText()
"""
self._default = default
self._heading = heading
self._hidden = hidden
self._isConfirmed = False
def doModal(self, autoclose = 0):
"""
--Show keyboard and wait for user action.
autoclose : [opt] integer - milliseconds to autoclose dialog. (default=do not autoclose)
example:
- kb.doModal(30000)
"""
dialog = xbmcgui.Dialog()
self._text = dialog.input(self._heading + ': ')
# self._text = raw_input(self._heading + ': ')
self._isConfirmed = True
def getText(self):
"""
--Returns the user input as a string.
Note, This will always return the text entry even if you cancel the keyboard.
Use theisConfirmed() method to check if user cancelled the keyboard.
example:
- text = kb.getText()
"""
return self._text
def isConfirmed(self):
"""
--Returns False if the user cancelled the input.
example:
- if (kb.isConfirmed()):
"""
return self._isConfirmed
def setDefault(self, default):
"""
--Set the default text entry.
default : string - default text entry.
Example:
- kb.setDefault('password')
"""
self._default = default
def setHeading(self, heading):
"""
--Set the keyboard heading.
heading : string - keyboard heading.
example:
- kb.setHeading('Enter password')
"""
self._heading = heading
def setHiddenInput(self, hidden):
"""
--Allows hidden text entry.
hidden : boolean - True for hidden text entry.
example:
- kb.setHiddenInput(True)
"""
self._hidden = hidden
class Monitor(object):
def __init__(self):
"""
--Creates a newMonitor to notify addon about changes.
"""
pass
def onAbortRequested(self):
"""
--onAbortRequested method.
Will be called when XBMC requests Abort
"""
pass
def onDatabaseScanStarted(self, database):
"""
--onDatabaseScanStarted method.
database : video/music as string
Will be called when database update starts and return video or music to indicate which DB is being updated
"""
pass
def onDatabaseUpdated(self, database):
"""
--onDatabaseUpdated method.
database : video/music as string
Will be called when database gets updated and return video or music to indicate which DB has been changed
"""
pass
def onNotification(self, sender, method, data):
"""
--onNotification method.
sender : sender of the notification
method : name of the notification
data : JSON-encoded data of the notification
Will be called when XBMC receives or sends a notification
"""
pass
def onScreensaverActivated(self):
"""
--onScreensaverActivated method.
Will be called when screensaver kicks in
"""
pass
def onScreensaverDeactivated(self):
"""
--onScreensaverDeactivated method.
Will be called when screensaver goes off
"""
pass
def onSettingsChanged(self):
"""
--onSettingsChanged method.
Will be called when addon settings are changed
"""
pass
class PlayList(object):
def __init__(self, playlist):
"""
Retrieve a reference from a valid xbmc playlist
playlist: int - can be one of the next values:
0: xbmc.PLAYLIST_MUSIC
1: xbmc.PLAYLIST_VIDEO
Use PlayList[int position] or __getitem__(int position) to get a PlayListItem.
"""
def __getitem__(self):
"""
x.__getitem__(y) <==> x[y]
"""
pass
def __len__(self):
"""
x.__len__() <==> len(x)
"""
pass
def add(self, url, listitem = None, index = 0):
"""
--Adds a new file to the playlist.
url : string or unicode - filename or url to add.
listitem : [opt] listitem - used with setInfo() to set different infolabels.
index : [opt] integer - position to add playlist item. (default=end)
*Note, You can use the above as keywords for arguments and skip certain optional arguments. Once you use a keyword, all following arguments require the keyword.
example:
- playlist =xbmc.PlayList (xbmc.PLAYLIST_VIDEO)
- video = 'F:\movies\Ironman.mov'
- listitem =xbmcgui.ListItem ('Ironman', thumbnailImage='F:\movies\Ironman.tbn')
- listitem.setInfo('video', {'Title': 'Ironman', 'Genre': 'Science Fiction'})
- playlist.add(url=video, listitem=listitem, index=7)n
"""
pass
def clear(self):
"""
--clear all items in the playlist.
"""
pass
def getPlayListId(self):
"""
--returns an integer.
"""
pass
def getposition(self):
"""
--returns the position of the current song in this playlist.
"""
pass
def load(self, filename):
"""
--Load a playlist.
clear current playlist and copy items from the file to this Playlist filename can be like .pls or .m3u ...
returns False if unable to load playlist
"""
pass
def remove(self, filename):
"""
--remove an item with this filename from the playlist.
"""
pass
def shuffle(self):
"""
--shuffle the playlist.
"""
pass
def size(self):
"""
--returns the total number of PlayListItems in this playlist.
"""
pass
def unshuffle(self):
"""
--unshuffle the playlist.
"""
pass
class Player(object):
def __init__(self):
"""
--Creates a newPlayer class.
"""
pass
def DisableSubtitles(self):
"""
--disable subtitles
"""
def getAvailableAudioStreams(self):
"""
--get Audio stream names
"""
pass
def getAvailableSubtitleStreams(self):
"""
--get Subtitle stream names
"""
pass
def getMusicInfoTag(self):
"""
--returns the MusicInfoTag of the current playing 'Song'.
Throws: Exception, if player is not playing a file or current file is not a music file.
"""
pass
def getPlayingFile(self):
"""
--returns the current playing file as a string.
Throws: Exception, if player is not playing a file.
"""
pass
def getSubtitles(self):
"""
--get subtitle stream name
"""
pass
def getTime(self):
"""
--Returns the current time of the current playing media as fractional seconds.
Throws: Exception, if player is not playing a file.
"""
pass
def getTotalTime(self):
"""
--Returns the total time of the current playing media in seconds. This is only accurate to the full second.
*Throws: Exception, if player is not playing a file.
"""
pass
def getVideoInfoTag(self):
"""
--returns the VideoInfoTag of the current playing Movie.
Throws: Exception, if player is not playing a file or current file is not a movie file.
"""
pass
def isPlaying(self):
"""
--returns True is xbmc is playing a file.
"""
pass
def isPlayingAudio(self):
"""
--returns True is xbmc is playing an audio file.
"""
pass
def isPlayingVideo(self):
"""
--returns True if xbmc is playing a video.
"""
pass
def onPlayBackEnded(self):
"""
--onPlayBackEnded method.
Will be called when xbmc stops playing a file
"""
pass
def onPlayBackPaused(self):
"""
--onPlayBackPaused method.
Will be called when user pauses a playing file
"""
pass
def onPlayBackResumed(self):
"""
--onPlayBackResumed method.
Will be called when user resumes a paused file
"""
pass
def onPlayBackSeek(self, time, seekOffset):
"""
--onPlayBackSeek method.
time : integer - time to seek to.
seekOffset : integer - ?.
Will be called when user seeks to a time
"""
pass
def onPlayBackSeekChapter(self, chapter):
"""
--onPlayBackSeekChapter method.
chapter : integer - chapter to seek to.
Will be called when user performs a chapter seek
"""
pass
def onPlayBackSpeedChanged(self, speed):
"""
--onPlayBackSpeedChanged method.
speed : integer - current speed of player.
*Note, negative speed means player is rewinding, 1 is normal playback speed.
Will be called when players speed changes. (eg. user FF/RW)
"""
pass
def onPlayBackStarted(self):
"""
--onPlayBackStarted method.
Will be called when xbmc starts playing a file
"""
pass
def onPlayBackStopped(self):
"""
--onPlayBackStopped method.
Will be called when user stops xbmc playing a file
"""
pass
def onQueueNextItem(self):
"""
--onQueueNextItem method.
Will be called when user queues the next item
"""
pass
def pause(self):
"""
--Pause playing.
"""
pass
def play(self, item = '', listitem = None, windowed = False, startpos = 0):
"""
--Play this item.
item : [opt] string - filename, url or playlist.
listitem : [opt] listitem - used with setInfo() to set different infolabels.
windowed : [opt] bool - true=play video windowed, false=play users preference.(default)
startpos : [opt] int - starting position when playing a playlist. Default = -1
*Note, If item is not given then thePlayer will try to play the current item
in the current playlist.
You can use the above as keywords for arguments and skip certain optional arguments.
Once you use a keyword, all following arguments require the keyword.
example:
- listitem =xbmcgui.ListItem ('Ironman')
- listitem.setInfo('video', {'Title': 'Ironman', 'Genre': 'Science Fiction'})
- xbmc.Player().play(url, listitem, windowed)
- xbmc.Player().play(playlist, listitem, windowed, startpos)
"""
pass
def playnext(self):
"""
--Play next item in playlist.
"""
pass
def playprevious(self):
"""
--Play previous item in playlist.
"""
pass
def playselected(self):
"""
--Play a certain item from the current playlist.
"""
pass
def seekTime(self):
"""
--Seeks the specified amount of time as fractional seconds. The time specified is relative to the beginning of the currently playing media file.
Throws: Exception, if player is not playing a file.
"""
pass
def setAudioStream(self, stream):
"""
--set Audio Stream.
stream : int
example:
- setAudioStream(1)
"""
pass
def setSubtitleStream(self, stream):
"""
--set Subtitle Stream
stream : int
example:
- setSubtitleStream(1)
"""
pass
def setSubtitles(self):
"""
--set subtitle file and enable subtitlesn
"""
pass
def showSubtitles(self, visible):
"""
--enable/disable subtitles
visible : boolean - True for visible subtitles.
example:
- xbmc.Player().showSubtitles(True)
"""
pass
def stop(self):
"""
--Stop playing.
"""
pass
class RenderCapture(object):
def capture(self, width, height , flags = None):
"""
--issue capture request.
width : Width capture image should be rendered to
height : Height capture image should should be rendered to
flags : Optional. Flags that control the capture processing.
The value for 'flags' could be or'ed from the following constants:
- xbmc.CAPTURE_FLAG_CONTINUOUS : after a capture is done, issue a new capture request immediately
- xbmc.CAPTURE_FLAG_IMMEDIATELY : read out immediately whencapture() is called, this can cause a busy wait
"""
pass
def getAspectRatio(self):
"""
--returns aspect ratio of currently displayed video.
"""
pass
def getCaptureState(self):
"""
--returns processing state of capture request.
The returned value could be compared against the following constants:
- xbmc.CAPTURE_STATE_WORKING : Capture request in progress.
- xbmc.CAPTURE_STATE_DONE : Capture request done. The image could be retrieved withgetImage()
- xbmc.CAPTURE_STATE_FAILED : Capture request failed.
"""
pass
def getHeight(self):
"""
--returns height of captured image.
"""
pass
def getImage(self):
"""
--returns captured image as a bytearray.
The size of the image isgetWidth() *getHeight() * 4
"""
pass
def getImageFormat(self):
"""
--returns format of captured image: 'BGRA' or 'RGBA'.
"""
pass
def getWidth(self):
"""
--returns width of captured image.
"""
pass
def waitForCaptureStateChangeEvent(self, msecs = 0):
"""
--wait for capture state change event.
msecs : Milliseconds to wait. Waits forever if not specified.
The method will return 1 if the Event was triggered. Otherwise it will return 0.
"""
pass
#
# Functions
#
def audioResume():
"""
--Resume Audio engine.
example: xbmc.audioResume()
"""
pass
def audioSuspend():
"""
--Suspend Audio engine.
example:
- xbmc.audioSuspend()
"""
pass
def convertLanguage(language, lang_format):
"""
--Returns the given language converted to the given format as a string.
language: string either as name in English, two letter code (ISO 639-1), or three letter code (ISO 639-2/T(B)
format: format of the returned language string
xbmc.ISO_639_1: two letter code as defined in ISO 639-1
xbmc.ISO_639_2: three letter code as defined in ISO 639-2/T or ISO 639-2/B
xbmc.ENGLISH_NAME: full language name in English (default)
example:
- language = xbmc.convertLanguage(English, xbmc.ISO_639_2)
"""
pass
def enableNavSounds(yesNo):
"""
--Enables/Disables nav sounds
yesNo : integer - enable (True) or disable (False) nav sounds
example:
- xbmc.enableNavSounds(True)
"""
pass
def executeJSONRPC(jsonrpccommand):
"""
--Execute an JSONRPC command.
jsonrpccommand : string - jsonrpc command to execute.
List of commands -
example:
- response = xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "method": "JSONRPC.Introspect", "id": 1 }')
"""
pass
def executebuiltin(function):
"""
--Execute a built in XBMC function.
function : string - builtin function to execute.
List of functions -http://wiki.xbmc.org/?title=List_of_Built_In_Functions
example:
- xbmc.executebuiltin('XBMC.RunXBE(c:\avalaunch.xbe)')
"""
pass
def executehttpapi(httpcommand):
"""
--Not implemented anymore.
"""
pass
def executescript(script):
"""
--Execute a python script.
script : string - script filename to execute.
example:
- xbmc.executescript('special://home/scripts/update.py')
"""
fileName = translatePath(script)
execfile(fileName, globals())
pass
def getCacheThumbName(path):
"""
--Returns a thumb cache filename.
path : string or unicode - path to file
example:
- thumb = xbmc.getCacheThumbName('f:\videos\movie.avi')
"""
pass
def getCleanMovieTitle(path, usefoldername = False):
"""
--Returns a clean movie title and year string if available.
path : string or unicode - String to clean
bool : [opt] bool - use folder names (defaults to false)
example:
- title, year = xbmc.getCleanMovieTitle('/path/to/moviefolder/test.avi', True)
"""
pass
def getCondVisibility(condition):
"""
--Returns True (1) or False (0) as a bool.
condition : string - condition to check.
List of Conditions -http://wiki.xbmc.org/?title=List_of_Boolean_Conditions
*Note, You can combine two (or more) of the above settings by using "+" as an AND operator,
"|" as an OR operator, "!" as a NOT operator, and "[" and "]" to bracket expressions.
example:
- visible = xbmc.getCondVisibility('[Control.IsVisible(41) + !Control.IsVisible(12)]')
"""
pass
def getDVDState():
"""
--Returns the dvd state as an integer.
return values are:
- 1 : xbmc.DRIVE_NOT_READY
- 16 : xbmc.TRAY_OPEN
- 64 : xbmc.TRAY_CLOSED_NO_MEDIA
- 96 : xbmc.TRAY_CLOSED_MEDIA_PRESENT
example:
- dvdstate = xbmc.getDVDState()
"""
pass
def getFreeMem():
"""
--Returns the amount of free memory in MB as an integer.
example:
- freemem = xbmc.getFreeMem()
"""
pass
def getGlobalIdleTime():
"""
--Returns the elapsed idle time in seconds as an integer.
example:
- t = xbmc.getGlobalIdleTime()
"""
pass
def getIPAddress():
"""
--Returns the current ip address as a string.
example:
-
"""
import socket
return socket.gethostbyname(socket.gethostname())
def getInfoImage(infotag):
"""
--Returns a filename including path to the InfoImage's thumbnail as a string.
infotag : string - infotag for value you want returned.
List of InfoTags -http://wiki.xbmc.org/?title=InfoLabels
example:
- filename = xbmc.getInfoImage('Weather.Conditions')
"""
pass
def getRegion(setting_id):
"""
--Returns your regions setting as a string for the specified id.
setting_id : string - id of setting to return
*Note, choices are (dateshort, datelong, time, meridiem, tempunit, speedunit)You can use the above as keywords for arguments.
example:
- date_long_format = xbmc.getRegion('datelong')
"""
pass
def getInfoLabel(infotag):
"""
--Returns an InfoLabel as a string.
infotag : string - infoTag for value you want returned.
List of InfoTags -http://wiki.xbmc.org/?title=InfoLabels
example:
- label = xbmc.getInfoLabel('Weather.Conditions')
"""
return ''
pass
def getLanguage(lang_format = None, region = None):
"""
--Returns the active language as a string.
lang_format: [opt] format of the returned language string
- xbmc.ISO_639_1: two letter code as defined in ISO 639-1
- xbmc.ISO_639_2: three letter code as defined in ISO 639-2/T or ISO 639-2/B
- xbmc.ENGLISH_NAME: full language name in English (default)
region: [opt] append the region delimited by "-" of the language (setting) to the returned language string
example:
- language = xbmc.getLanguage(xbmc.ENGLISH_NAME)
"""
if lang_format == ISO_639_1: return 'en'
elif lang_format == ISO_639_2: return 'eng'
elif lang_format == ENGLISH_NAME: return 'English'
return 'English'
def getLocalizedString(string_id):
"""
--Returns a localized 'unicode string'.
string_id : integer - id# for string you want to localize.
*Note, See strings.xml in }\ for which id
you need for a string.
example:
- locstr = xbmc.getLocalizedString(6)
"""
addonId = sys.argv[0]
langPath = 'special://home/addons/' + addonId
langPath = translatePath(langPath)
langPath = langPath + '\\resources\\language\\English\\strings.xml'
if os.path.exists(langPath):
with open(langPath, 'r') as langFile:
langStr = langFile.read()
strToSearch = '<string id="' + str(string_id) + '">'
limInf = langStr.find(strToSearch)
if limInf == -1: return 'not found'
limInf += len(strToSearch)
limSup = langStr.find('</string>', limInf)
return langStr[limInf:limSup]
return 'archivo lenguaje no existe'
def getSkinDir():
"""
--Returns the active skin directory as a string.
*Note, This is not the full path like 'special://home/addons/MediaCenter', but only 'MediaCenter'.
example:
- skindir = xbmc.getSkinDir()
"""
pass
def getSupportedMedia(media):
"""
--Returns the supported file types for the specific media as a string.
media : string - media type
*Note, media type can be (video, music, picture).The return value is a pipe separated string of filetypes (eg. '.mov|.avi').
You can use the above as keywords for arguments.
example:
- mTypes = xbmc.getSupportedMedia('video')
"""
pass
def log(msg, level = LOGNOTICE):
"""
--Write a string to XBMC's log file and the debug window.
msg : string - text to output.
level : [opt] integer - log level to ouput at. (default=LOGNOTICE)
*Note, You can use the above as keywords for arguments and skip certain optional arguments.
Once you use a keyword, all following arguments require the keyword.
Text is written to the log for the following conditions.
XBMC loglevel == -1 (NONE, nothing at all is logged)
XBMC loglevel == 0 (NORMAL, shows LOGNOTICE, LOGERROR, LOGSEVERE and LOGFATAL) XBMC loglevel == 1 (DEBUG, shows all)
See pydocs for valid values for level.
example:
- xbmc.log(msg='This is a test string.', level=xbmc.LOGDEBUG));
"""
logLst = ['LOGDEBUG', 'LOGINFO', 'LOGNOTICE', 'LOGWARNING',
'LOGERROR', 'LOGSEVERE', 'LOGFATAL', 'LOGNONE']
if xbmcLoglevel < 0 : return
if xbmcLoglevel == 0 and level in [LOGDEBUG, LOGINFO]: return
print >> sys.stderr, logLst[level] + ': ' + msg
def makeLegalFilename(filename, fatX = True):
"""
--Returns a legal filename or path as a string.
filename : string or unicode - filename/path to make legal
fatX : [opt] bool - True=Xbox file system(Default)
*Note, If fatX is true you should pass a full path. If fatX is false only pass the basename of the path.
You can use the above as keywords for arguments and skip
certain optional arguments. Once you use a keyword,
all following arguments require the keyword.
example:
- filename = xbmc.makeLegalFilename('F: Age: The Meltdown.avi')
"""
if fatX: return validatePath(filename)
return filename + '/'
pass
def playSFX(filename, useCached = True):
"""
--Plays a wav file by filename
filename : string - filename of the wav file to play. useCached : [opt] bool - False = Dump any previously cached wav associated with filename
example:
- xbmc.playSFX('special://xbmc/scripts/dingdong.wav')
- xbmc.playSFX('special://xbmc/scripts/dingdong.wav',False)
"""
pass
def restart():
"""
--Restart the htpc. example:
- xbmc.restart()
"""
pass
def Shutdown():
"""
--Shutdown the htpc.
example:
- xbmc.shutdown()
"""
pass
def skinHasImage(image):
"""
--Returns True if the image file exists in the skin.
image : string - image filename
*Note, If the media resides in a subfolder include it. (eg. home-myfiles\home-myfiles2.png)You can use the above as keywords for arguments.
example:
- exists = xbmc.skinHasImage('ButtonFocusedTexture.png')
"""
pass
def sleep(atime):
"""
--Sleeps for 'time' msec.
time : integer - number of msec to sleep.
*Note, This is useful if you have for example aPlayer class that is waiting
for onPlayBackEnded() calls.
Throws: PyExc_TypeError, if time is not an integer.
example:
- xbmc.sleep(2000) # sleeps for 2 seconds
"""
time.sleep(float(atime/1000.0))
pass
def startServer(typ, bStart, bWait):
"""
--start or stop a server.
typ : integer - use SERVER_* constants
bStart : bool - start (True) or stop (False) a server
bWait : [opt] bool - wait on stop before returning (not supported by all servers)
returnValue : bool - True or False
example:
- xbmc.startServer(xbmc.SERVER_AIRPLAYSERVER, False)
"""
pass
def stopSFX():
"""
--Stops wav file
example:
- xbmc.stopSFX()
"""
pass
def translatePath(path):
"""
--Returns the translated path.
path : string or unicode - Path to format
*Note, Only useful if you are coding for both Linux and Windows.
e.g. Converts 'special://masterprofile/script_data' -> '/home/user/XBMC/UserData/script_data' on Linux.
example:
- fpath = xbmc.translatePath('special://masterprofile/script_data')
:type path: string or unicode
"""
specialProtocol = {
'special://temp':'special://home/cache',
'special://masterprofile':'special://home/userdata',
'special://profile':'special://masterprofile',
'special://userdata':'special://masterprofile',
'special://database':'special://masterprofile/Database',
'special://thumbnails':'special://masterprofile/Thumbnails',
'special://musicplaylists':'special://profile/playlists/music',
'special://videoplaylists':'special://profile/playlists/video',
'special://logpath':'special://home',
'special://skin':'special://xbmc/addons/skin.confluence'
}
if sys.platform[:3] == 'win':
specialProtocol['special://xbmc'] = special_xbmc or os.path.join(os.path.expandvars("$PROGRAMFILES"), "Kodi")
specialProtocol['special://home'] = special_home or os.path.join(os.path.expandvars("$APPDATA"), "Kodi")
elif not (special_home or special_xbmc):
raise Exception('You must define the vars xbmc.special_xbmc (special://xbmc) and xbmc.special_home (special://home)')
else:
specialProtocol['special://xbmc'] = special_xbmc
specialProtocol['special://home'] = special_home
pattern = 'special://[^\\\\/]+'
oldPath = ''
while oldPath != path:
oldPath = path
path = re.sub(pattern, lambda x: specialProtocol.get(x.group(), x.group()), oldPath)
root = re.match(pattern, path)
if not root: return validatePath(path)
raise Exception(root.group() + ' is not a special path in KODI')
def validatePath(aPath):
"""
--Returns the validated path.
path : string or unicode - Path to format
*Note, Only useful if you are coding for both Linux and Windows for fixing slash problems.
e.g. Corrects 'Z://something' -> 'Z:'
example:
- fpath = xbmc.validatePath(somepath)
"""
return os.path.normpath(aPath)
'''
Created on 9/05/2014
@author: pybquillast
This module has been ported from xbmcstubs:
__author__ = 'Team XBMC <http://xbmc.org>'
__credits__ = 'Team XBMC'
__date__ = 'Thu Apr 17 08:03:38 BST 2014'
__platform__ = 'ALL'
__version__ = '2.14.0'
'''
import sys
import os
import xbmc
import xml.etree.ElementTree as ET
import xml.dom.minidom as minidom
import re
class Addon(object):
def __new__(cls, *args, **kwargs):
if args:
addonId = args[0]
else:
posIni = len('plugin://')
posFin = sys.argv[0].find('/', posIni)
addonId = sys.argv[0][posIni:posFin]
addonId = kwargs.get('id',addonId)
pathDir = xbmc.translatePath('special://home/addons/' + addonId)
addonXmlFile = os.path.join(pathDir, 'addon.xml')
if not os.path.exists(addonXmlFile): return False
inst = object.__new__(cls, *args, **kwargs)
return inst
def __init__(self, *args, **kwargs):
"""
--Creates a newAddon class.
addonId : [opt] string - id of the addon as specified in addon.xml
*Note, specifying the addon id is not needed.
Important however is that the addon folder has the same name as the addon id provided in addon.xml.
You can optionally specify the addon id from another installed addon to retrieve settings from it.
example:
- self.Addon = xbmcaddon.Addon()
- self.Addon =xbmcaddon.Addon ('script.foo.bar')
"""
if args:
self.addonId = args[0]
else:
posIni = len('plugin://')
posFin = sys.argv[0].find('/', posIni)
addonId = sys.argv[0][posIni:posFin]
self.addonId = kwargs.get('id',None) or addonId
def getAddonInfo(self, infoId):
"""
--Returns the value of an addon property as a string.
infoId : string - id of the property that the module needs to access.
*Note, choices are (author, changelog, description, disclaimer, fanart. icon, id, name, path profile, stars, summary, type, version)
example:
- version = self.Addon.getAddonInfo('version')
"""
infoId = infoId.lower()
pathDir = xbmc.translatePath('special://home/addons/' + self.addonId)
if not os.path.exists(pathDir):
xbmc.log('The path ' + pathDir + 'for addon ' + self.addonId + 'dosen\'t exists', xbmc.LOGFATAL)
return ''
if infoId in ['changelog', 'fanart', 'icon', 'path', 'profile']:
if infoId == 'changelog': return os.path.join(pathDir, 'changelog.txt')
elif infoId == 'fanart': return os.path.join(pathDir, 'fanart.jpg')
elif infoId == 'icon': return os.path.join(pathDir, 'icon.png')
elif infoId == 'path': return pathDir
elif infoId == 'profile': return 'special://profile/addon_data/' + self.addonId + '/'
addonXmlFile = os.path.join(pathDir, 'addon.xml')
if not os.path.exists(addonXmlFile): return None
if infoId == 'author': infoId = 'provider-name'
attributes = ['id', 'version', 'name', 'provider-name']
metadata = ['summary', 'description', 'disclaimer', 'platform',
'supportedcontent', 'language', 'license', 'forum',
'website', 'source', 'email']
with open(addonXmlFile, 'r') as xmlFile:
xmlContent = xmlFile.read()
xmlDom = minidom.parseString(xmlContent)
if infoId in attributes:
heading = xmlDom.getElementsByTagName('addon')
heading = dict(heading[0].attributes.items())
return heading.get(infoId, None)
elif infoId in ['type', 'library']:
if infoId == 'type': infoId = 'point'
heading = xmlDom.getElementsByTagName('extension')
heading = dict(heading[0].attributes.items())
return heading.get(infoId, None)
elif infoId in metadata:
metadataInfo = xmlDom.getElementsByTagName(infoId)
if len(metadataInfo):
return metadataInfo[0].childNodes[0].data
return ''
elif infoId == 'requires':
requiresInfo = xmlDom.getElementsByTagName('import')
modList = []
if requiresInfo:
for modToImport in requiresInfo:
modAttr = dict(modToImport.attributes.items())
modList.append(modAttr['addon'])
return modList
elif infoId == 'stars': return '0'
def getLocalizedString(self, stringId):
"""
--Returns an addon's localized 'unicode string'.
stringId : integer - id# for string you want to localize.
example:
- locstr = self.Addon.getLocalizedString(32000)
"""
if not isinstance(stringId, int): raise Exception('an integer is required')
langPath = 'special://home/addons/' + self.addonId + '/resources/language/English'
langPath = xbmc.translatePath(langPath)
if os.path.exists(os.path.join(langPath, 'strings.xml')):
langPath = os.path.join(langPath, 'strings.xml')
root = ET.parse(langPath).getroot()
srchStr = './/string[@id="' + stringId + '"]'
element = root.find(srchStr)
if element is not None: return element.text
elif os.path.exists(os.path.join(langPath, 'strings.po')):
langPath = os.path.join(langPath, 'strings.po')
with open(langPath, 'r') as langFile:
langStr = langFile.read()
pattern = r'msgctxt "#{}"\nmsgid "(?P<msgid>[^"]*)"\nmsgstr "(?P<msgstr>[^"]*)"'.format(stringId)
match = re.search(pattern, langStr)
if match: return match.group('msgid')
return ''
# raise Exception('There is no string asociated with id=' + str(stringId))
def getSetting(self, stringId):
"""
--Returns the value of a setting as a unicode string.
stringId : string - id of the setting that the module needs to access.
example:
- apikey = self.Addon.getSetting('apikey')
"""
settingFiles = [('value', 'special://profile/addon_data/{0}/{1}'),
('default', 'special://home/addons/{0}/resources/{1}')]
for attrId, settingXmlFile in settingFiles:
settingXmlFile = xbmc.translatePath(settingXmlFile.format(self.addonId, 'settings.xml'))
if not os.path.exists(settingXmlFile): continue
root = ET.parse(settingXmlFile).getroot()
srchStr = './/setting[@id="' + stringId + '"]'
element = root.find(srchStr)
if element is not None: return element.get(attrId)
return ''
def openSettings(self):
"""
--Opens this scripts settings dialog.
example:
- self.Settings.openSettings()
"""
pass
def setSetting(self,settingId, value):
"""
--Sets a script setting.
addonId : string - id of the setting that the module needs to access. value : string or unicode - value of the setting.
*Note, You can use the above as keywords for arguments.
example:
- self.Settings.setSetting(id='username', value='teamxbmc')
"""
settingXmlFile = xbmc.translatePath('special://profile/addon_data/' + self.addonId + '/settings.xml')
tree = ET.parse(settingXmlFile)
root = tree.getroot()
srchStr = './/setting[@id="' + settingId + '"]'
element = root.find(srchStr)
if element is None:
element = ET.Element('setting', attrib={'id':settingId, 'value':''})
root.append(element)
element.set('value', str(value))
elemList = sorted(root.getchildren(), key = lambda x: x.get('id'))
with open(settingXmlFile, 'w') as f:
f.write('<?xml version="1.0" ?>\n<settings>\n')
for elem in elemList:
setStr = ' ' + ET.tostring(elem, 'utf-8').strip() + '\n'
f.write(setStr)
f.write('</settings>\n')
pass
'''
Created on 9/05/2014
@author: pybquillast
This module has been ported from xbmcstubs:
__author__ = 'Team XBMC <http://xbmc.org>'
__credits__ = 'Team XBMC'
__date__ = 'Sun Aug 18 16:43:27 CEST 2013'
__platform__ = 'ALL'
__version__ = '2.0'
'''
import Tkinter as tk
import tkSimpleDialog
import tkMessageBox
import tkFileDialog
import os
import xbmc
OUTPUT_TYPE = 'tkinter' # Set this variable to 'tkinter' para ejecutar bajo tkinter
# OUTPUT_TYPE = 'console' # Set this variable to 'tkinter' para ejecutar bajo tkinter
#
# Variables
#
ALPHANUM_HIDE_INPUT = 2
CONTROL_TEXT_OFFSET_X = 10
CONTROL_TEXT_OFFSET_Y = 2
ICON_OVERLAY_HAS_TRAINER = 4
ICON_OVERLAY_HD = 8
ICON_OVERLAY_LOCKED = 3
ICON_OVERLAY_NONE = 0
ICON_OVERLAY_RAR = 1
ICON_OVERLAY_TRAINED = 5
ICON_OVERLAY_UNWATCHED = 6
ICON_OVERLAY_WATCHED = 7
ICON_OVERLAY_ZIP = 2
INPUT_ALPHANUM = 0
INPUT_DATE = 2
INPUT_IPADDRESS = 4
INPUT_NUMERIC = 1
INPUT_PASSWORD = 5
INPUT_TIME = 3
NOTIFICATION_ERROR = 'error'
NOTIFICATION_INFO = 'info'
NOTIFICATION_WARNING = 'warning'
PASSWORD_VERIFY = 1
#
# Function Documentation
#
def getCurrentWindowDialogId():
"""
getCurrentWindowDialogId()--Returns the id for the current 'active' dialog as an integer.
example:
- wid = xbmcgui.getCurrentWindowDialogId()
"""
pass
def getCurrentWindowId():
"""
getCurrentWindowId()--Returns the id for the current 'active' window as an integer.
example:
- wid = xbmcgui.getCurrentWindowId()
"""
pass
def lock():
"""
lock()--Lock the gui until xbmcgui.unlock() is called.
*Note, This will improve performance when doing a lot of gui manipulation at once.
The main program (xbmc itself) will freeze until xbmcgui.unlock() is called.
example:
- xbmcgui.lock()
"""
pass
def unlock():
"""
unlock()--Unlock the gui from a lock() call.
example:
- xbmcgui.unlock()
"""
pass
#
# CLASSES
#
class ListItem(object):
def __init__(self, label = '', label2 = '', iconImage = None, thumbnailImage = None, path = None):
"""
label: string or unicode - label1 text.
label2: string or unicode - label2 text.
iconImage: string - icon filename.
thumbnailImage: string - thumbnail filename.
path: string or unicode - listitem's path.
Example:
listitem = xbmcgui.ListItem('Casino Royale', '[PG-13]', 'blank-poster.tbn', 'poster.tbn', path='f:\\movies\\casino_royale.mov')
"""
self._properties = {}
self._properties['contextmenu'] = {'tuplelist':[], 'replaceItems':False}
self.setLabel(label)
self.setLabel2(label2)
self.setIconImage(iconImage)
self.setThumbnailImage(thumbnailImage)
self.setPath(path)
self.select(False)
#
# Member Function Documentation
#
def addContextMenuItems(self, tuplelist, replaceItems = False):
"""
Adds item(s) to the context menu for media lists.
items: tuplelist - [(label, action)] A list of tuples consisting of label and action pairs.
label: string or unicode - item's label.
action: string or unicode - any built-in function to perform.
replaceItems: bool - True=only your items will show/False=your items will be added to context menu.
List of functions: http://wiki.xbmc.org/?title=List_of_Built_In_Functions
Example:
listitem.addContextMenuItems([('Theater Showtimes', 'XBMC.RunScript(special://home/scripts/showtimes/default.py,Iron Man)')])
"""
contextmenu = self._properties['contextmenu']
contextmenu['tuplelist'] = tuplelist
contextmenu['replaceItems'] = replaceItems
def addStreamInfo(self, streamtype, values):
"""
addStreamInfo(type, values) -- Add a stream with details.
streamtype : string - type of stream(video/audio/subtitle).
values : dictionary - pairs of { label: value }.
Video Values:
codec : string (h264)
aspect : float (1.78)
width : integer (1280)
height : integer (720)
duration : integer (seconds)
Audio Values:
codec : string (dts)
language : string (en)
channels : integer (2)
Subtitle Values:
language : string (en)
example:
- self.list.getSelectedItem().addStreamInfo('video', { 'Codec': 'h264', 'Width' : 1280 })
"""
self._streamInfo = (streamtype, values)
pass
def getLabel(self):
"""
Returns the listitem label.
"""
label = self.getProperty('label')
if isinstance(label, unicode): label = label.encode('utf-8')
return label
# return self.getProperty('label').encode('latin-1', 'replace')
def getLabel2(self):
"""
Returns the listitem's second label.
"""
return self.getProperty('label2')
def getProperty(self, key):
"""
Returns a listitem property as a string, similar to an infolabel.
key: string - property name.
Note:
Key is NOT case sensitive.
"""
return self._properties.get(key.lower(), None)
def isSelected(self):
"""
Returns the listitem's selected status.
"""
return self.getProperty('select')
def select(self, selected):
"""
Sets the listitem's selected status.
selected: bool - True=selected/False=not selected.
"""
self.setProperty('select',selected)
def setIconImage(self, icon):
"""
Sets the listitem's icon image.
icon: string or unicode - image filename.
"""
self.setProperty('iconImage',icon)
def setInfo(self, type, infoLabels):
"""
Sets the listitem's infoLabels.
type: string - type of media(video/music/pictures).
infoLabels: dictionary - pairs of { label: value }.
Note:
To set pictures exif info, prepend 'exif:' to the label. Exif values must be passed
as strings, separate value pairs with a comma. (eg. {'exif:resolution': '720,480'}
See CPictureInfoTag::TranslateString in PictureInfoTag.cpp for valid strings.
General Values that apply to all types:
count: integer (12) - can be used to store an id for later, or for sorting purposes
size: long (1024) - size in bytes
date: string (%d.%m.%Y / 01.01.2009) - file date
Video Values:
genre: string (Comedy)
year: integer (2009)
episode: integer (4)
season: integer (1)
top250: integer (192)
tracknumber: integer (3)
rating: float (6.4) - range is 0..10
watched: depreciated - use playcount instead
playcount: integer (2) - number of times this item has been played
overlay: integer (2) - range is 0..8. See GUIListItem.h for values
cast: list (Michal C. Hall)
castandrole: list (Michael C. Hall|Dexter)
director: string (Dagur Kari)
mpaa: string (PG-13)
plot: string (Long Description)
plotoutline: string (Short Description)
title: string (Big Fan)
originaltitle: string (Big Fan)
duration: string (3:18)
studio: string (Warner Bros.)
tagline: string (An awesome movie) - short description of movie
writer: string (Robert D. Siegel)
tvshowtitle: string (Heroes)
premiered: string (2005-03-04)
status: string (Continuing) - status of a TVshow
code: string (tt0110293) - IMDb code
aired: string (2008-12-07)
credits: string (Andy Kaufman) - writing credits
lastplayed: string (%Y-%m-%d %h:%m:%s = 2009-04-05 23:16:04)
album: string (The Joshua Tree)
votes: string (12345 votes)
trailer: string (/home/user/trailer.avi)
Music Values:
tracknumber: integer (8)
duration: integer (245
) - duration in seconds
year: integer (1998)
genre: string (Rock)
album: string (Pulse)
artist: string (Muse)
title: string (American Pie)
rating: string (3) - single character between 0 and 5
lyrics: string (On a dark desert highway...)
playcount: integer (2) - number of times this item has been played
lastplayed: string (%Y-%m-%d %h:%m:%s = 2009-04-05 23:16:04)
Picture Values:
title: string (In the last summer-1)
picturepath: string (/home/username/pictures/img001.jpg)
exif*: string (See CPictureInfoTag::TranslateString in PictureInfoTag.cpp for valid strings)
Example:
self.list.getSelectedItem().setInfo('video', { 'Genre': 'Comedy' })
"""
self._ItemInfo = (type, infoLabels)
def setLabel(self, label):
"""
Sets the listitem's label.
label: string or unicode - text string.
"""
self.setProperty('label', label)
def setLabel2(self, label2):
"""
Sets the listitem's second label.
label2: string or unicode - text string.
"""
self.setProperty('label2', label2)
def setPath(self, path):
"""
setPath(path) -- Sets the listitem's path.
path : string or unicode - path, activated when item is clicked.
*Note, You can use the above as keywords for arguments.
example:
- self.list.getSelectedItem().setPath(path='ActivateWindow(Weather)')
"""
self.setProperty('path', path)
def setProperty(self, key, value):
"""
Sets a listitem property, similar to an infolabel.
key: string - property name.
value: string or unicode - value of property.
Note:
Key is NOT case sensitive.
Some of these are treated internally by XBMC, such as the 'StartOffset' property, which is
the offset in seconds at which to start playback of an item. Others may be used in the skin
to add extra information, such as 'WatchedCount' for tvshow items
Example:
self.list.getSelectedItem().setProperty('AspectRatio', '1.85 : 1')
self.list.getSelectedItem().setProperty('StartOffset', '256.4')
"""
self._properties[key.lower()] = value
def setThumbnailImage(self, thumb):
"""
Sets the listitem's thumbnail image.
thumb: string or unicode - image filename.
"""
self.setProperty('thumbnailImage', thumb)
#
# modulos de xbmc stubs
#
class Window(object):
"""Create a new Window to draw on."""
def __init__(self, windowId=-1):
"""
Create a new Window to draw on.
Specify an id to use an existing window.
Raises:
ValueError: If supplied window Id does not exist.
Exception: If more then 200 windows are created.
Deleting this window will activate the old window that was active
and resets (not delete) all controls that are associated with this window.
"""
pass
def show(self):
"""Show this window.
Shows this window by activating it, calling close() after it wil activate the current window again.
Note:
If your script ends this window will be closed to. To show it forever,
make a loop at the end of your script and use doModal() instead.
"""
pass
def close(self):
"""Closes this window.
Closes this window by activating the old window.
The window is not deleted with this method.
"""
pass
def onAction(self, action):
"""onAction method.
This method will recieve all actions that the main program will send to this window.
By default, only the PREVIOUS_MENU action is handled.
Overwrite this method to let your script handle all actions.
Don't forget to capture ACTION_PREVIOUS_MENU, else the user can't close this window.
"""
pass
def onClick(self, control):
"""onClick method.
This method will recieve all click events that the main program will send to this window.
"""
pass
def onDoubleClick(self):
pass
def onControl(self, control):
"""
onControl method.
This method will recieve all control events that the main program will send to this window.
'control' is an instance of a Control object.
"""
pass
def onFocus(self, control):
"""onFocus method.
This method will recieve all focus events that the main program will send to this window.
"""
pass
def onInit(self):
"""onInit method.
This method will be called to initialize the window.
"""
pass
def doModal(self):
"""Display this window until close() is called."""
pass
def addControl(self, control):
"""Add a Control to this window.
Raises:
TypeError: If supplied argument is not a Control type.
ReferenceError: If control is already used in another window.
RuntimeError: Should not happen :-)
The next controls can be added to a window atm:
ControlLabel
ControlFadeLabel
ControlTextBox
ControlButton
ControlCheckMark
ControlList
ControlGroup
ControlImage
ControlRadioButton
ControlProgress
"""
pass
def addControls(self, controls):
"""
addControls(self, List)--Add a list of Controls to this window.
*Throws:
- TypeError, if supplied argument is not ofList type, or a control is not ofControl type
- ReferenceError, if control is already used in another window
- RuntimeError, should not happen :-)
"""
pass
def getControl(self, controlId):
"""Get's the control from this window.
Raises:
Exception: If Control doesn't exist
controlId doesn't have to be a python control, it can be a control id
from a xbmc window too (you can find id's in the xml files).
Note:
Not python controls are not completely usable yet.
You can only use the Control functions.
"""
return object
def setFocus(self, Control):
"""Give the supplied control focus.
Raises:
TypeError: If supplied argument is not a Control type.
SystemError: On Internal error.
RuntimeError: If control is not added to a window.
"""
pass
def setFocusId(self, int):
"""Gives the control with the supplied focus.
Raises:
SystemError: On Internal error.
RuntimeError: If control is not added to a window.
"""
pass
def getFocus(self):
"""Returns the control which is focused.
Raises:
SystemError: On Internal error.
RuntimeError: If no control has focus.
"""
return object
def getFocusId(self):
"""Returns the id of the control which is focused.
Raises:
SystemError: On Internal error.
RuntimeError: If no control has focus.
"""
return long
def removeControl(self, control):
"""Removes the control from this window.
Raises:
TypeError: If supplied argument is not a Control type.
RuntimeError: If control is not added to this window.
This will not delete the control. It is only removed from the window.
"""
pass
def removeControls(self, controls):
pass
def getHeight(self):
"""Returns the height of this screen."""
return long
def getWidth(self):
"""Returns the width of this screen."""
return long
def getResolution(self):
"""Returns the resolution of the screen.
The returned value is one of the following:
0 - 1080i (1920x1080)
1 - 720p (1280x720)
2 - 480p 4:3 (720x480)
3 - 480p 16:9 (720x480)
4 - NTSC 4:3 (720x480)
5 - NTSC 16:9 (720x480)
6 - PAL 4:3 (720x576)
7 - PAL 16:9 (720x576)
8 - PAL60 4:3 (720x480)
9 - PAL60 16:9 (720x480)
Note: this info is outdated. XBMC 12+ returns different vaulues.
"""
return long
def setCoordinateResolution(self, resolution):
"""Sets the resolution that the coordinates of all controls are defined in.
Allows XBMC to scale control positions and width/heights to whatever resolution
XBMC is currently using.
resolution is one of the following:
0 - 1080i (1920x1080)
1 - 720p (1280x720)
2 - 480p 4:3 (720x480)
3 - 480p 16:9 (720x480)
4 - NTSC 4:3 (720x480)
5 - NTSC 16:9 (720x480)
6 - PAL 4:3 (720x576)
7 - PAL 16:9 (720x576)
8 - PAL60 4:3 (720x480)
9 - PAL60 16:9 (720x480)
Note: default is 720p (1280x720)
Note 2: this is not an actual display resulution. This is the resolution of the coordinate grid
all controls are placed on.
"""
pass
def setProperty(self, key, value):
"""Sets a window property, similar to an infolabel.
key: string - property name.
value: string or unicode - value of property.
Note:
key is NOT case sensitive. Setting value to an empty string is equivalent to clearProperty(key).
Example:
win = xbmcgui.Window(xbmcgui.getCurrentWindowId())
win.setProperty('Category', 'Newest')
"""
pass
def getProperty(self, key):
"""Returns a window property as a string, similar to an infolabel.
key: string - property name.
Note:
key is NOT case sensitive.
Example:
win = xbmcgui.Window(xbmcgui.getCurrentWindowId())
category = win.getProperty('Category')
"""
return str
def clearProperty(self, key):
"""Clears the specific window property.
key: string - property name.
Note:
key is NOT case sensitive. Equivalent to setProperty(key,'').
Example:
win = xbmcgui.Window(xbmcgui.getCurrentWindowId())
win.clearProperty('Category')
"""
pass
def clearProperties(self):
"""Clears all window properties.
Example:
win = xbmcgui.Window(xbmcgui.getCurrentWindowId())
win.clearProperties()
"""
pass
#noinspection PyUnusedLocal
class WindowDialog(Window):
"""
Create a new WindowDialog with transparent background, unlike Window.
WindowDialog always stays on top of XBMC UI.
"""
def __init__(self):
pass
#noinspection PyUnusedLocal
class WindowXML(Window):
"""Create a new WindowXML script."""
def __init__(self, xmlFilename, scriptPath, defaultSkin='Default', defaultRes='720p'):
"""
xmlFilename: string - the name of the xml file to look for.
scriptPath: string - path to script. used to fallback to if the xml doesn't exist in the current skin.
(eg os.getcwd())
defaultSkin: string - name of the folder in the skins path to look in for the xml.
defaultRes: string - default skins resolution.
Note:
Skin folder structure is eg(resources/skins/Default/720p).
Example:
ui = GUI('script-Lyrics-main.xml', os.getcwd(), 'LCARS', 'PAL')
ui.doModal()
del ui
"""
pass
def removeItem(self, position):
"""Removes a specified item based on position, from the Window List.
position: integer - position of item to remove.
"""
pass
def addItem(self, item, position=32767):
"""Add a new item to this Window List.
item: string, unicode or ListItem - item to add.
position: integer - position of item to add. (NO Int = Adds to bottom,0 adds to top, 1 adds to one below from top,-1 adds to one above from bottom etc etc)
If integer positions are greater than list size, negative positions will add to top of list, positive positions will add to bottom of list.
Example:
self.addItem('Reboot XBMC', 0)
"""
pass
def clearList(self):
"""Clear the Window List."""
pass
def setCurrentListPosition(self, position):
"""Set the current position in the Window List.
position: integer - position of item to set.
"""
pass
def getCurrentListPosition(self):
"""Gets the current position in the Window List."""
return long
def getListItem(self, position):
"""Returns a given ListItem in this Window List.
position: integer - position of item to return.
"""
return ListItem
def getListSize(self):
"""Returns the number of items in this Window List."""
return long
def setProperty(self, key, value):
"""Sets a container property, similar to an infolabel.
key: string - property name.
value: string or unicode - value of property.
Note:
Key is NOT case sensitive.
Example:
self.setProperty('Category', 'Newest')
"""
pass
#noinspection PyUnusedLocal
class WindowXMLDialog(WindowXML):
"""Create a new WindowXMLDialog script."""
def __init__(self, xmlFilename, scriptPath, defaultSkin="Default", defaultRes="720p"):
"""
xmlFilename: string - the name of the xml file to look for.
scriptPath: string - path to script. used to fallback to if the xml doesn't exist in the current skin. (eg os.getcwd())
defaultSkin: string - name of the folder in the skins path to look in for the xml.
defaultRes: string - default skins resolution.
Note:
Skin folder structure is eg(resources/skins/Default/720p).
Example:
ui = GUI('script-Lyrics-main.xml', os.getcwd(), 'LCARS', 'PAL')
ui.doModal()
del ui
"""
pass
#noinspection PyUnusedLocal
class Control(object):
"""
Parent for control classes. The problem here is that Python uses references to this class in a dynamic typing way.
For example, you will find this type of python code frequently:
window.getControl( 100 ).setLabel( "Stupid Dynamic Type")
Notice that the 'getControl' call returns a 'Control ' object.
In a dynamically typed language, the subsequent call to setLabel works if the specific type of control has the method.
The script writer is often in a position to know more than the code about the specificControl type
(in the example, that control id 100 is a 'ControlLabel ') where the C++ code is not.
SWIG doesn't support this type of dynamic typing. The 'Control ' wrapper that's returned will wrap aControlLabel
but will not have the 'setLabel' method on it. The only way to handle this is to add all possible subclass methods
to the parent class. This is ugly but the alternative is nearly as ugly.
It's particularly ugly here because the majority of the methods are unique to the particular subclass.
If anyone thinks they have a solution then let me know. The alternative would be to have a set of 'getContol'
methods, each one coresponding to a type so that the downcast can be done in the native code.
IOW rather than a simple 'getControl' there would be a 'getControlLabel', 'getControlRadioButton',
'getControlButton', etc.
TODO:This later solution should be implemented for future scripting languages
while the former will remain as deprecated functionality for Python.
"""
def addItem(self):
pass
def addItems(self):
pass
def canAcceptMessages(self):
pass
def controlDown(self, control=None):
"""
controlDown(control)--Set's the controls down navigation.
control : control object - control to navigate to on down.
*Note, You can also usesetNavigation() . Set to self to disable navigation.
Throws:
- TypeError, if one of the supplied arguments is not a control type.
- ReferenceError, if one of the controls is not added to a window.
example:
- self.button.controlDown(self.button1)
"""
pass
def controlLeft(self, control=None):
"""
controlLeft(control)--Set's the controls left navigation.
control : control object - control to navigate to on left.
*Note, You can also usesetNavigation() . Set to self to disable navigation.
Throws:
- TypeError, if one of the supplied arguments is not a control type.
- ReferenceError, if one of the controls is not added to a window.
example:
- self.button.controlLeft(self.button1)
"""
pass
def controlRight(self, control=None):
"""
controlRight(control)--Set's the controls right navigation.
control : control object - control to navigate to on right.
*Note, You can also usesetNavigation() . Set to self to disable navigation.
Throws:
- TypeError, if one of the supplied arguments is not a control type.
- ReferenceError, if one of the controls is not added to a window.
example:
- self.button.controlRight(self.button1)
"""
pass
def controlUp(self, control=None):
"""
controlUp(control)--Set's the controls up navigation.
control : control object - control to navigate to on up.
*Note, You can also usesetNavigation() . Set to self to disable navigation.
Throws:
- TypeError, if one of the supplied arguments is not a control type.
- ReferenceError, if one of the controls is not added to a window.
example:
- self.button.controlUp(self.button1)
"""
pass
def getHeight(self):
"""
getHeight() --Returns the control's current height as an integer.
example:
- height = self.button.getHeight()
"""
return int
def getId(self):
"""
getId() --Returns the control's current id as an integer.
example:
- id = self.button.getId()
"""
return int
def getPosition(self):
"""
getPosition() --Returns the control's current position as a x,y integer tuple.
example:
- pos = self.button.getPosition()
"""
return (int, int)
def getWidth(self):
"""
getWidth() --Returns the control's current width as an integer.
example:
- width = self.button.getWidth()
"""
return int
def getX(self):
"""
Get X coordinate of a control as an integer.
"""
return int
def getY(self):
"""
Get Y coordinate of a control as an integer.
"""
return int
def setAnimations(self, event_attr=[()]):
"""
setAnimations([(event, attr,)*])--Set's the control's animations.
[(event,attr,)*] : list - A list of tuples consisting of event and attributes pairs.
- event : string - The event to animate.
- attr : string - The whole attribute string separated by spaces.
Animating your skin -http://wiki.xbmc.org/?title=Animating_Your_Skin
example:
- self.button.setAnimations([('focus', 'effect=zoom end=90,247,220,56 time=0',)])
"""
pass
def setEnableCondition(self, enable):
"""
setEnableCondition(enable)--Set's the control's enabled condition.
Allows XBMC to control the enabled status of the control.
enable : string - Enable condition.
List of Conditions -http://wiki.xbmc.org/index.php?title=List_of_Boolean_Conditions
example:
- self.button.setEnableCondition('System.InternetState')
"""
pass
def setEnabled(self, enabled=True):
"""
setEnabled(enabled)--Set's the control's enabled/disabled state.
enabled : bool - True=enabled / False=disabled.
example:
- self.button.setEnabled(False)
"""
pass
def setHeight(self, height):
"""
setHeight(height)--Set's the controls height.
height : integer - height of control.
example:
- self.image.setHeight(100)
"""
pass
def setNavigation(self, up=None, down=None, left=None, right=None):
"""
setNavigation(up, down, left, right)--Set's the controls navigation.
up : control object - control to navigate to on up.
down : control object - control to navigate to on down.
left : control object - control to navigate to on left.
right : control object - control to navigate to on right.
*Note, Same ascontrolUp() ,controlDown() ,controlLeft() ,controlRight() . Set to self to disable navigation for that direction.
Throws:
- TypeError, if one of the supplied arguments is not a control type.
- ReferenceError, if one of the controls is not added to a window.
example:
- self.button.setNavigation(self.button1, self.button2, self.button3, self.button4)
"""
pass
def setPosition(self, x, y):
"""
setPosition(x, y)--Set's the controls position.
x : integer - x coordinate of control.
y : integer - y coordinate of control.
*Note, You may use negative integers. (e.g sliding a control into view)
example:
- self.button.setPosition(100, 250)
"""
pass
def setVisible(self, visible):
"""
setVisible(visible)--Set's the control's visible/hidden state.
visible : bool - True=visible / False=hidden.
example:
- self.button.setVisible(False)
"""
pass
def setVisibleCondition(self, condition, allowHiddenFocus=False):
"""
setVisibleCondition(visible[,allowHiddenFocus])--Set's the control's visible condition.
Allows XBMC to control the visible status of the control.
visible : string - Visible condition.
allowHiddenFocus : bool - True=gains focus even if hidden.
List of Conditions -http://wiki.xbmc.org/index.php?title=List_of_Boolean_Conditions
example:
- self.button.setVisibleCondition('[Control.IsVisible(41) + !Control.IsVisible(12)]', True)
"""
pass
def setWidth(self, width):
"""
setWidth(width)--Set's the controls width.
width : integer - width of control.
example:
- self.image.setWidth(100)
"""
pass
#noinspection PyUnusedLocal
#noinspection PyUnusedLocal
class ControlLabel(Control):
"""
ControlLabel class.
Creates a text label.
"""
def __init__(self, x, y, width, height, label, font=None, textColor=None, disabledColor=None, alignment=None,
hasPath=None, angle=None):
"""
x: integer - x coordinate of control.
y: integer - y coordinate of control.
width: integer - width of control.
height: integer - height of control.
label: string or unicode - text string.
font: string - font used for label text. (e.g. 'font13')
textColor: hexstring - color of enabled label's label. (e.g. '0xFFFFFFFF')
disabledColor: hexstring - color of disabled label's label. (e.g. '0xFFFF3300')
alignment: integer - alignment of label - *Note, see xbfont.h
hasPath: bool - True=stores a path / False=no path.
angle: integer - angle of control. (+ rotates CCW, - rotates CW)"
Note:
After you create the control, you need to add it to the window with addControl().
Example:
self.label = xbmcgui.ControlLabel(100, 250, 125, 75, 'Status', angle=45)
"""
pass
def setLabel(self, label):
"""Set's text for this label.
label: string or unicode - text string.
"""
pass
def getLabel(self):
"""Returns the text value for this label."""
return str
#noinspection PyUnusedLocal
class ControlFadeLabel(Control):
"""Control which scrolls long label text."""
def __init__(self, x, y, width, height, font=None, textColor=None, _alignment=None):
"""
x: integer - x coordinate of control.
y: integer - y coordinate of control.
width: integer - width of control.
height: integer - height of control.
font: string - font used for label text. (e.g. 'font13')
textColor: hexstring - color of fadelabel's labels. (e.g. '0xFFFFFFFF')
_alignment: integer - alignment of label - *Note, see xbfont.h
Note:
After you create the control, you need to add it to the window with addControl().
Example:
self.fadelabel = xbmcgui.ControlFadeLabel(100, 250, 200, 50, textColor='0xFFFFFFFF')
"""
pass
def addLabel(self, label):
"""Add a label to this control for scrolling.
label: string or unicode - text string.
"""
pass
def reset(self):
"""Clears this fadelabel."""
pass
#noinspection PyUnusedLocal
class ControlTextBox(Control):
"""
ControlTextBox class.
Creates a box for multi-line text.
"""
def __init__(self, x, y, width, height, font=None, textColor=None):
"""
x: integer - x coordinate of control.
y: integer - y coordinate of control.
width: integer - width of control.
height: integer - height of control.
font: string - font used for text. (e.g. 'font13')
textColor: hexstring - color of textbox's text. (e.g. '0xFFFFFFFF')
Note:
After you create the control, you need to add it to the window with addControl().
Example:
self.textbox = xbmcgui.ControlTextBox(100, 250, 300, 300, textColor='0xFFFFFFFF')
"""
pass
def setText(self, text):
"""Set's the text for this textbox.
text: string or unicode - text string.
"""
pass
def scroll(self, position):
"""Scrolls to the given position.
id: integer - position to scroll to.
"""
pass
def reset(self):
"""Clear's this textbox."""
pass
#noinspection PyUnusedLocal
class ControlButton(Control):
"""
ControlButton class.
Creates a clickable button.
"""
def __init__(self, x, y, width, height, label, focusTexture=None, noFocusTexture=None, textOffsetX=None,
textOffsetY=None, alignment=None, font=None, textColor=None, disabledColor=None, angle=None,
shadowColor=None, focusedColor=None):
"""
x: integer - x coordinate of control.
y: integer - y coordinate of control.
width: integer - width of control.
height: integer - height of control.
label: string or unicode - text string.
focusTexture: string - filename for focus texture.
noFocusTexture: string - filename for no focus texture.
textOffsetX: integer - x offset of label.
textOffsetY: integer - y offset of label.
alignment: integer - alignment of label - *Note, see xbfont.h
font: string - font used for label text. (e.g. 'font13')
textColor: hexstring - color of enabled button's label. (e.g. '0xFFFFFFFF')
disabledColor: hexstring - color of disabled button's label. (e.g. '0xFFFF3300')
angle: integer - angle of control. (+ rotates CCW, - rotates CW)
shadowColor: hexstring - color of button's label's shadow. (e.g. '0xFF000000')
focusedColor: hexstring - color of focused button's label. (e.g. '0xFF00FFFF')
Note:
After you create the control, you need to add it to the window with addControl().
Example:
self.button = xbmcgui.ControlButton(100, 250, 200, 50, 'Status', font='font14')
"""
pass
def setDisabledColor(self, disabledColor):
"""Set's this buttons disabled color.
disabledColor: hexstring - color of disabled button's label. (e.g. '0xFFFF3300')
"""
pass
def setLabel(self, label=None, font=None, textColor=None, disabledColor=None, shadowColor=None, focusedColor=None):
"""Set's this buttons text attributes.
label: string or unicode - text string.
font: string - font used for label text. (e.g. 'font13')
textColor: hexstring - color of enabled button's label. (e.g. '0xFFFFFFFF')
disabledColor: hexstring - color of disabled button's label. (e.g. '0xFFFF3300')
shadowColor: hexstring - color of button's label's shadow. (e.g. '0xFF000000')
focusedColor: hexstring - color of focused button's label. (e.g. '0xFFFFFF00')
label2: string or unicode - text string.
Example:
self.button.setLabel('Status', 'font14', '0xFFFFFFFF', '0xFFFF3300', '0xFF000000')
"""
pass
def getLabel(self):
"""Returns the buttons label as a unicode string."""
return unicode
def getLabel2(self):
"""Returns the buttons label2 as a unicode string."""
return unicode
#noinspection PyUnusedLocal
class ControlCheckMark(Control):
"""
ControlCheckMark class.
Creates a checkmark with 2 states.
"""
def __init__(self, x, y, width, height, label, focusTexture=None, noFocusTexture=None, checkWidth=None,
checkHeight=None, _alignment=None, font=None, textColor=None, disabledColor=None):
"""
x: integer - x coordinate of control.
y: integer - y coordinate of control.
width: integer - width of control.
height: integer - height of control.
label: string or unicode - text string.
focusTexture: string - filename for focus texture.
noFocusTexture: string - filename for no focus texture.
checkWidth: integer - width of checkmark.
checkHeight: integer - height of checkmark.
_alignment: integer - alignment of label - *Note, see xbfont.h
font: string - font used for label text. (e.g. 'font13')
textColor: hexstring - color of enabled checkmark's label. (e.g. '0xFFFFFFFF')
disabledColor: hexstring - color of disabled checkmark's label. (e.g. '0xFFFF3300')
Note:
After you create the control, you need to add it to the window with addControl().
Example:
self.checkmark = xbmcgui.ControlCheckMark(100, 250, 200, 50, 'Status', font='font14')
"""
pass
def setDisabledColor(self, disabledColor):
"""Set's this controls disabled color.
disabledColor: hexstring - color of disabled checkmark's label. (e.g. '0xFFFF3300')
"""
pass
def setLabel(self, label, font=None, textColor=None, disabledColor=None):
"""Set's this controls text attributes.
label: string or unicode - text string.
font: string - font used for label text. (e.g. 'font13')
textColor: hexstring - color of enabled checkmark's label. (e.g. '0xFFFFFFFF')
disabledColor: hexstring - color of disabled checkmark's label. (e.g. '0xFFFF3300')
Example:
self.checkmark.setLabel('Status', 'font14', '0xFFFFFFFF', '0xFFFF3300')
"""
pass
def getSelected(self):
"""Returns the selected status for this checkmark as a bool."""
return bool
def setSelected(self, isOn):
"""Sets this checkmark status to on or off.
isOn: bool - True=selected (on) / False=not selected (off)
"""
pass
#noinspection PyUnusedLocal
class ControlList(Control):
"""
ControlList class.
Creates a list of items.
"""
def __init__(self, x, y, width, height, font=None, textColor=None, buttonTexture=None, buttonFocusTexture=None,
selectedColor=None, _imageWidth=None, _imageHeight=None, _itemTextXOffset=None, _itemTextYOffset=None,
_itemHeight=None, _space=None, _alignmentY=None):
"""
x: integer - x coordinate of control.
y: integer - y coordinate of control.
width: integer - width of control.
height: integer - height of control.
font: string - font used for items label. (e.g. 'font13')
textColor: hexstring - color of items label. (e.g. '0xFFFFFFFF')
buttonTexture: string - filename for no focus texture.
buttonFocusTexture: string - filename for focus texture.
selectedColor: integer - x offset of label.
_imageWidth: integer - width of items icon or thumbnail.
_imageHeight: integer - height of items icon or thumbnail.
_itemTextXOffset: integer - x offset of items label.
_itemTextYOffset: integer - y offset of items label.
_itemHeight: integer - height of items.
_space: integer - space between items.
_alignmentY: integer - Y-axis alignment of items label - *Note, see xbfont.h
Note:
After you create the control, you need to add it to the window with addControl().
Example:
self.cList = xbmcgui.ControlList(100, 250, 200, 250, 'font14', space=5)
"""
pass
def addItem(self, item):
"""Add a new item to this list control.
item: string, unicode or ListItem - item to add.
"""
pass
def addItems(self, items):
"""Adds a list of listitems or strings to this list control.
items: List - list of strings, unicode objects or ListItems to add.
"""
pass
def selectItem(self, item):
"""Select an item by index number.
item: integer - index number of the item to select.
"""
pass
def reset(self):
"""Clear all ListItems in this control list."""
pass
def getSpinControl(self):
"""Returns the associated ControlSpin object.
Note:
Not working completely yet -
After adding this control list to a window it is not possible to change
the settings of this spin control.
"""
return object
def setImageDimensions(self, imageWidth=None, imageHeight=None):
"""Sets the width/height of items icon or thumbnail.
imageWidth: integer - width of items icon or thumbnail.
imageHeight: integer - height of items icon or thumbnail.
"""
pass
def setItemHeight(self, itemHeight):
"""Sets the height of items.
itemHeight: integer - height of items.
"""
pass
def setPageControlVisible(self, visible):
"""Sets the spin control's visible/hidden state.
visible: boolean - True=visible / False=hidden.
"""
pass
def setSpace(self, space=None):
"""Set's the space between items.
space: integer - space between items.
"""
pass
def getSelectedPosition(self):
"""Returns the position of the selected item as an integer.
Note:
Returns -1 for empty lists.
"""
return int
def getSelectedItem(self):
"""Returns the selected item as a ListItem object.
Note:
Same as getSelectedPosition(), but instead of an integer a ListItem object is returned. Returns None for empty lists.
See windowexample.py on how to use this.
"""
return ListItem
def size(self):
"""Returns the total number of items in this list control as an integer."""
return long
def getListItem(self, index):
"""Returns a given ListItem in this List.
index: integer - index number of item to return.
Raises:
ValueError: If index is out of range.
"""
return ListItem
def getItemHeight(self):
"""Returns the control's current item height as an integer."""
return long
def getSpace(self):
"""Returns the control's space between items as an integer."""
return long
def setStaticContent(self, items):
"""Fills a static list with a list of listitems.
items: List - list of listitems to add.
"""
pass
def removeItem(self, index):
"""
Remove an item by index number.
index : integer - index number of the item to remove.
example:
my_list.removeItem(12)
"""
pass
#noinspection PyUnusedLocal
class ControlImage(Control):
"""
ControlImage class.
Displays an image from a file.
"""
def __init__(self, x, y, width, height, filename, colorKey=None, aspectRatio=None, colorDiffuse=None):
"""
x: integer - x coordinate of control.
y: integer - y coordinate of control.
width: integer - width of control.
height: integer - height of control.
filename: string - image filename.
colorKey: hexString - (example, '0xFFFF3300')
aspectRatio: integer - (values 0 = stretch (default), 1 = scale up (crops), 2 = scale down (black bars)
colorDiffuse: hexString - (example, '0xC0FF0000' (red tint)).
Note:
After you create the control, you need to add it to the window with addControl().
Example:
self.image = xbmcgui.ControlImage(100, 250, 125, 75, aspectRatio=2)
"""
pass
def setImage(self, filename):
"""Changes the image.
filename: string - image filename.
"""
pass
def setColorDiffuse(self, colorDiffuse):
"""Changes the images color.
colorDiffuse: hexString - (example, '0xC0FF0000' (red tint)).
"""
pass
#noinspection PyUnusedLocal
class ControlProgress(Control):
"""
ControlProgress class.
"""
def __init__(self, x, y, width, height, texturebg=None, textureleft=None, texturemid=None, textureright=None,
textureoverlay=None):
"""
x: integer - x coordinate of control.
y: integer - y coordinate of control.
width: integer - width of control.
height: integer - height of control.
texturebg: string - image filename.
textureleft: string - image filename.
texturemid: string - image filename.
textureright: string - image filename.
textureoverlay: string - image filename.
Note:
After you create the control, you need to add it to the window with addControl().
Example:
self.progress = xbmcgui.ControlProgress(100, 250, 125, 75)
"""
pass
def setPercent(self, percent):
"""Sets the percentage of the progressbar to show.
percent: float - percentage of the bar to show.
Note:
Valid range for percent is 0-100.
"""
pass
def getPercent(self):
"""Returns a float of the percent of the progress."""
return float
#noinspection PyUnusedLocal
class ControlSlider(Control):
"""
ControlSlider class.
Creates a slider.
"""
def __init__(self, x, y, width, height, textureback=None, texture=None, texturefocus=None):
"""
x: integer - x coordinate of control.
y: integer - y coordinate of control.
width: integer - width of control.
height: integer - height of control.
textureback: string - image filename.
texture: string - image filename.
texturefocus: string - image filename.
Note:
After you create the control, you need to add it to the window with addControl().
Example:
self.slider = xbmcgui.ControlSlider(100, 250, 350, 40)
"""
pass
def getPercent(self):
"""Returns a float of the percent of the slider."""
return float
def setPercent(self, percent):
"""Sets the percent of the slider."""
pass
#noinspection PyUnusedLocal
class ControlGroup(Control):
"""ControlGroup class."""
def __init__(self, x, y, width, height):
"""
x: integer - x coordinate of control.
y: integer - y coordinate of control.
width: integer - width of control.
height: integer - height of control.
Example:
self.group = xbmcgui.ControlGroup(100, 250, 125, 75)
"""
pass
#noinspection PyUnusedLocal
class ControlEdit(Control):
"""
ControlEdit class.
ControlEdit(x, y, width, height, label[, font, textColor,
disabledColor, alignment, focusTexture, noFocusTexture])
"""
def __init__(self, x, y, width, height, label, font=None, textColor=None, disabledColor=None, alignment=None,
focusTexture=None, noFocusTexture=None):
"""
x : integer - x coordinate of control.
y : integer - y coordinate of control.
width : integer - width of control.
height : integer - height of control.
label : string or unicode - text string.
font : [opt] string - font used for label text. (e.g. 'font13')
textColor : [opt] hexstring - color of enabled label's label. (e.g. '0xFFFFFFFF')
disabledColor : [opt] hexstring - color of disabled label's label. (e.g. '0xFFFF3300')
_alignment : [opt] integer - alignment of label - *Note, see xbfont.h
focusTexture : [opt] string - filename for focus texture.
noFocusTexture : [opt] string - filename for no focus texture.
isPassword : [opt] bool - if true, mask text value.
*Note, You can use the above as keywords for arguments and skip certain optional arguments.
Once you use a keyword, all following arguments require the keyword.
After you create the control, you need to add it to the window with addControl().
example:
- self.edit = xbmcgui.ControlEdit(100, 250, 125, 75, 'Status')
"""
pass
def getLabel(self):
"""
getLabel() -- Returns the text heading for this edit control.
example:
- label = self.edit.getLabel()
"""
return unicode
def getText(self):
"""
getText() -- Returns the text value for this edit control.
example:
- value = self.edit.getText()
"""
return unicode
def setLabel(self, label):
"""
setLabel(label) -- Set's text heading for this edit control.
label : string or unicode - text string.
example:
- self.edit.setLabel('Status')
"""
pass
def setText(self, value):
"""
setText(value) -- Set's text value for this edit control.
value : string or unicode - text string.
example:
- self.edit.setText('online')
"""
pass
#noinspection PyUnusedLocal
class ControlRadioButton(Control):
"""
ControlRadioButton class.
Creates a radio-button with 2 states.
"""
def __init__(self, x, y, width, height, label, focusTexture=None, noFocusTexture=None, textOffsetX=None,
textOffsetY=None, _alignment=None, font=None, textColor=None, disabledColor=None, angle=None,
shadowColor=None, focusedColor=None, focusOnTexture=None, noFocusOnTexture=None,
focusOffTexture=None, noFocusOffTexture=None):
"""
x: integer - x coordinate of control.
y: integer - y coordinate of control.
width: integer - width of control.
height: integer - height of control.
label: string or unicode - text string.
focusTexture: string - filename for focus texture.
noFocusTexture: string - filename for no focus texture.
textOffsetX: integer - x offset of label.
textOffsetY: integer - y offset of label.
_alignment: integer - alignment of label - *Note, see xbfont.h
font: string - font used for label text. (e.g. 'font13')
textColor: hexstring - color of enabled radio button's label. (e.g. '0xFFFFFFFF')
disabledColor: hexstring - color of disabled radio button's label. (e.g. '0xFFFF3300')
angle: integer - angle of control. (+ rotates CCW, - rotates CW)
shadowColor: hexstring - color of radio button's label's shadow. (e.g. '0xFF000000')
focusedColor: hexstring - color of focused radio button's label. (e.g. '0xFF00FFFF')
focusOnTexture: string - filename for radio focused/checked texture.
noFocusOnTexture: string - filename for radio not focused/checked texture.
focusOffTexture: string - filename for radio focused/unchecked texture.
noFocusOffTexture: string - filename for radio not focused/unchecked texture.
Note: To customize RadioButton all 4 abovementioned textures need to be provided.
focus and noFocus textures can be the same.
Note:
After you create the control, you need to add it to the window with addControl().
Example:
self.radiobutton = xbmcgui.ControlRadioButton(100, 250, 200, 50, 'Status', font='font14')
"""
pass
def setSelected(self, selected):
"""Sets the radio buttons's selected status.
selected: bool - True=selected (on) / False=not selected (off)
"""
pass
def isSelected(self):
"""Returns the radio buttons's selected status."""
return bool
def setLabel(self, label, font=None, textColor=None, disabledColor=None, shadowColor=None, focusedColor=None):
"""Set's the radio buttons text attributes.
label: string or unicode - text string.
font: string - font used for label text. (e.g. 'font13')
textColor: hexstring - color of enabled radio button's label. (e.g. '0xFFFFFFFF')
disabledColor: hexstring - color of disabled radio button's label. (e.g. '0xFFFF3300')
shadowColor: hexstring - color of radio button's label's shadow. (e.g. '0xFF000000')
focusedColor: hexstring - color of focused radio button's label. (e.g. '0xFFFFFF00')
Example:
self.radiobutton.setLabel('Status', 'font14', '0xFFFFFFFF', '0xFFFF3300', '0xFF000000')
"""
pass
def setRadioDimension(self, x, y, width, height):
"""Sets the radio buttons's radio texture's position and size.
x: integer - x coordinate of radio texture.
y: integer - y coordinate of radio texture.
width: integer - width of radio texture.
height: integer - height of radio texture.
Example:
self.radiobutton.setRadioDimension(x=100, y=5, width=20, height=20)
"""
pass
class Dialog(object):
def __init__(self):
object.__init__(self)
self.root = root = tk.Tk()
root.focus_set()
root.lift()
root.withdraw()
def browse(self, type, heading, s_shares, mask=None, useThumbs=False, treatAsFolder=False, default=None,
enableMultiple=False):
"""Show a 'Browse' dialog.
type: integer - the type of browse dialog.
heading: string or unicode - dialog heading.
s_shares: string or unicode - from sources.xml. (i.e. 'myprograms')
mask: string or unicode - '|' separated file mask. (i.e. '.jpg|.png')
useThumbs: boolean - if True autoswitch to Thumb view if files exist.
treatAsFolder: boolean - if True playlists and archives act as folders.
default: string - default path or file.
enableMultiple: boolean - if True multiple file selection is enabled.
Types:
0: ShowAndGetDirectory
1: ShowAndGetFile
2: ShowAndGetImage
3: ShowAndGetWriteableDirectory
Note:
If enableMultiple is False (default): returns filename and/or path as a string
to the location of the highlighted item, if user pressed 'Ok' or a masked item
was selected. Returns the default value if dialog was canceled.
If enableMultiple is True: returns tuple of marked filenames as a string,
if user pressed 'Ok' or a masked item was selected. Returns empty tuple if dialog was canceled.
If type is 0 or 3 the enableMultiple parameter is ignored.
Example:
dialog = xbmcgui.Dialog()
fn = dialog.browse(3, 'XBMC', 'files', '', False, False, False, 'special://masterprofile/script_data/XBMC Lyrics')
"""
root = self.root
default = xbmc.translatePath(default)
initDir, initFile = os.path.split(default)
if type in [0, 3]: # ShowAndGetDirectory, ShowAndGetWriteableDirectory
answ = tkFileDialog.askdirectory(title=heading, initialdir= initDir, mustexist=True)
pass
elif type == 1: # ShowAndGetFile
answ = tkFileDialog.askopenfilename(defaultextension = '', filetypes=[('req files', mask or '.txt')], initialdir=initDir, initialfile=initFile, multiple=enableMultiple, title=heading)
pass
elif type == 2: # ShowAndGetImage
mask = '.png|.jpg|.jpeg|.bmp|.gif|.ico|.tif|.tiff|.tga|.pcx|.cbz|.zip|.cbr|.rar|.dng|.nef|.cr2|.crw|.orf|.arw|.erf|.3fr|.dcr|.x3f|.mef|.raf|.mrw|.pef|.sr2|.rss'
answ = tkFileDialog.askopenfilename(defaultextension = '.png', filetypes=[('image files', mask), ('all files', '.txt')], initialdir=initDir, initialfile=initFile, multiple=enableMultiple, title=heading)
pass
return answ
def browseMultiple(self, type, heading, shares, mask=None, useThumbs=None, treatAsFolder=None, default=None):
"""
browse(type, heading, shares[, mask, useThumbs, treatAsFolder, default])--Show a 'Browse' dialog.
type : integer - the type of browse dialog.
heading : string or unicode - dialog heading.
shares : string or unicode - from sources.xml. (i.e. 'myprograms')
mask : [opt] string or unicode - '|' separated file mask. (i.e. '.jpg|.png')
useThumbs : [opt] boolean - if True autoswitch to Thumb view if files exist (default=false).
treatAsFolder : [opt] boolean - if True playlists and archives act as folders (default=false).
default : [opt] string - default path or file.
Types:
- 1 : ShowAndGetFile
- 2 : ShowAndGetImage
*Note,
returns tuple of marked filenames as a string,"
if user pressed 'Ok' or a masked item was selected. Returns empty tuple if dialog was canceled.
example:
- dialog = xbmcgui.Dialog()
- fn = dialog.browseMultiple(2, 'XBMC', 'files', '', False, False, 'special://masterprofile/script_data/XBMC Lyrics')
"""
return self.browse(self, type, heading, shares, mask=None, useThumbs=False, treatAsFolder=False, default=None,
enableMultiple=True)
def browseSingle(self, type, heading, shares, mask=None, useThumbs=None, treatAsFolder=None, default=None):
"""
browse(type, heading, shares[, mask, useThumbs, treatAsFolder, default])--Show a 'Browse' dialog.
type : integer - the type of browse dialog.
heading : string or unicode - dialog heading.
shares : string or unicode - from sources.xml. (i.e. 'myprograms')
mask : [opt] string or unicode - '|' separated file mask. (i.e. '.jpg|.png')
useThumbs : [opt] boolean - if True autoswitch to Thumb view if files exist (default=false).
treatAsFolder : [opt] boolean - if True playlists and archives act as folders (default=false).
default : [opt] string - default path or file.
Types:
- 0 : ShowAndGetDirectory
- 1 : ShowAndGetFile
- 2 : ShowAndGetImage
- 3 : ShowAndGetWriteableDirectory
*Note, Returns filename and/or path as a string to the location of the highlighted item,
if user pressed 'Ok' or a masked item was selected.
Returns the default value if dialog was canceled.
example:
- dialog = xbmcgui.Dialog()
- fn = dialog.browse(3, 'XBMC', 'files', '', False, False, 'special://masterprofile/script_data/XBMC Lyrics')
"""
return self.browse(self, type, heading, s_shares, mask=None, useThumbs=False, treatAsFolder=False, default=None,
enableMultiple=False)
def input(self, heading, default=None, type=0, option=None, autoclose=None):
"""
input(heading[, default, type, option, autoclose])--Show an Input dialog.
heading : string - dialog heading.
default : [opt] string - default value. (default=empty string)
type : [opt] integer - the type of keyboard dialog. (default=xbmcgui.INPUT_ALPHANUM)
option : [opt] integer - option for the dialog. (see Options below)
autoclose : [opt] integer - milliseconds to autoclose dialog. (default=do not autoclose)
Types:
- xbmcgui.INPUT_ALPHANUM (standard keyboard)
- xbmcgui.INPUT_NUMERIC (format: #)
- xbmcgui.INPUT_DATE (format: DD/MM/YYYY)
- xbmcgui.INPUT_TIME (format: HH:MM)
- xbmcgui.INPUT_IPADDRESS (format: #.#.#.#)
- xbmcgui.INPUT_PASSWORD (return md5 hash of input, input is masked)
Options PasswordDialog :
- xbmcgui.PASSWORD_VERIFY (verifies an existing (default) md5 hashed password)
Options AlphanumDialog :
- xbmcgui.ALPHANUM_HIDE_INPUT (masks input)
*Note, Returns the entered data as a string.
Returns an empty string if dialog was canceled.
Note:
available since Gotham
Example:
- dialog = xbmcgui.Dialog()
- d = dialog.input('Enter secret code', type=xbmcgui.INPUT_ALPHANUM, option=xbmcgui.ALPHANUM_HIDE_INPUT)
"""
root = self.root
formatStr = ["a-zA-z0-9", "#", "DD/MM/YYYY", "HH:MM", "#.#.#.#"]
return tkSimpleDialog.askstring('Input Dialog', "Input format " + formatStr[type] + ":", parent=root)
def numeric(self, type, heading, default=None):
"""Show a 'Numeric' dialog.
type: integer - the type of numeric dialog.
heading: string or unicode - dialog heading.
default: string - default value.
Types:
0: ShowAndGetNumber (default format: #)
1: ShowAndGetDate (default format: DD/MM/YYYY)
2: ShowAndGetTime (default format: HH:MM)
3: ShowAndGetIPAddress (default format: #.#.#.#)
Note:
Returns the entered data as a string.
Returns the default value if dialog was canceled.
Example:
dialog = xbmcgui.Dialog()
d = dialog.numeric(1, 'Enter date of birth')
"""
root=self.root
formatStr = ["#", "DD/MM/YYYY", "HH:MM", "#.#.#.#"]
return tkSimpleDialog.askstring('Numeric Dialog', "Input format " + formatStr[type] + ":", parent=root)
def notification(self, heading, message, icon=None, time=None, sound=None):
"""
notification(heading, message[, icon, time, sound])--Show a Notification alert.
heading : string - dialog heading.
message : string - dialog message.
icon : [opt] string - icon to use. (default xbmcgui.NOTIFICATION_INFO)
time : [opt] integer - time in milliseconds (default 5000)
sound : [opt] bool - play notification sound (default True)
Builtin Icons:
- xbmcgui.NOTIFICATION_INFO
- xbmcgui.NOTIFICATION_WARNING
- xbmcgui.NOTIFICATION_ERROR
example:
- dialog = xbmcgui.Dialog()
- dialog.notification('Movie Trailers', 'Finding Nemo download finished.', xbmcgui.NOTIFICATION_INFO, 5000)
"""
root = self.root
tkMessageBox.showinfo('Notification', message, parent=root)
root.destroy()
def yesno(self, heading, line1, line2=None, line3=None, nolabel=None, yeslabel=None):
"""Show a dialog 'YES/NO'.
heading: string or unicode - dialog heading.
line1: string or unicode - line #1 text.
line2: string or unicode - line #2 text.
line3: string or unicode - line #3 text.
nolabel: label to put on the no button.
yeslabel: label to put on the yes button.
Note:
Returns True if 'Yes' was pressed, else False.
Example:
dialog = xbmcgui.Dialog()
ret = dialog.yesno('XBMC', 'Do you want to exit this script?')
"""
root = self.root
prompt = [elem for elem in [line1, line2, line3] if elem]
message = '\n'.join(prompt)
ans = tkMessageBox.askyesno(heading, message, parent=root)
root.destroy()
return ans[0]
def ok(self, heading, line1, line2=None, line3=None):
"""Show a dialog 'OK'.
heading: string or unicode - dialog heading.
line1: string or unicode - line #1 text.
line2: string or unicode - line #2 text.
line3: string or unicode - line #3 text.
Note:
Returns True if 'Ok' was pressed, else False.
Example:
dialog = xbmcgui.Dialog()
ok = dialog.ok('XBMC', 'There was an error.')
"""
root = self.root
prompt = [elem for elem in [line1, line2, line3] if elem]
message = '\n'.join(prompt)
tkMessageBox.showinfo(heading, message, parent=root)
root.destroy()
return True
def select(self, heading, mlist, autoclose=0):
"""Show a select dialog.
heading: string or unicode - dialog heading.
mlist: string list - list of items.
autoclose: integer - milliseconds to autoclose dialog.
Note:
autoclose = 0 - This disables autoclose.
Returns the position of the highlighted item as an integer.
Example:
dialog = xbmcgui.Dialog()
ret = dialog.select('Choose a playlist', ['Playlist #1', 'Playlist #2, 'Playlist #3'])
"""
class kodiSelectClass(tk.Toplevel):
def __init__(self, memList, title = None, master = None, dheight = 300, dwidth = 200):
# if master:
# tk.Toplevel.__init__(self, master)
# self.transient(master)
# self.parent = master
# self.geometry("+%d+%d"%(master.winfo_rootx()+50, master.winfo_rooty()+50))
# else:
if master:
tk.Toplevel.__init__(self, master, height = dheight, width = dwidth)
else:
tk.Toplevel.__init__(self, height = dheight, width = dwidth)
x = (self.winfo_screenwidth() - dwidth)/2
y = (self.winfo_screenheight() -dheight)/2
self.geometry('{}x{}+{}+{}'.format(dwidth, dheight, x, y))
self.resizable(False, False)
if title: self.title(title)
body = tk.Frame(self)
body.pack(padx=5, pady=5, side = tk.TOP, fill = tk.BOTH, expand = tk.YES)
# body.pack_propagate(0)
self.flag = 0
self.setGUI(body)
for pos, item in enumerate(memList): # add to listbox
self.listbox.insert(pos, item) # or insert(END,label)
self.initial_focus = None
self.grab_set()
if not self.initial_focus: self.initial_focus = self.listbox
self.protocol('WM_DELETE_WINDOW', self.Close)
self.initial_focus.focus_set()
self.select(0)
self.wait_window(self)
def Close(self):
self.destroy()
def setGUI(self, frame):
sbar = tk.Scrollbar(frame)
listBox = tk.Listbox(frame, selectmode = 'SINGLE', width = 50, relief=tk.SUNKEN)
sbar.config(command=listBox.yview) # xlink sbar and list
listBox.config(yscrollcommand=sbar.set) # move one moves other
sbar.pack(side=tk.RIGHT, fill=tk.Y) # pack first=clip last
listBox.pack(side=tk.LEFT, fill=tk.BOTH, expand = tk.YES) # list clipped first
listBox.event_add('<<Execute Option>>','<Return>','<Double-Button-1>')
listBox.bind('<<Execute Option>>', self.handleList)
listBox.bind('<Key-Up>', self.up_event)
listBox.bind('<Key-Down>', self.down_event)
self.listbox = listBox
def up_event(self, event):
selItem = self.listbox.index("active")
lsize = self.listbox.size()
self.select((selItem + lsize -1) % lsize)
return "break"
def down_event(self, event):
selItem = self.listbox.index("active")
lsize = self.listbox.size()
self.select((selItem + lsize + 1) % lsize)
return "break"
def handleList(self, event = None):
self.index = self.listbox.curselection()[0] # on list double-click
self.Close()
def select(self, index):
self.index = index
self.listbox.focus_set()
self.listbox.activate(index)
self.listbox.selection_clear(0, "end")
self.listbox.selection_set(index)
self.listbox.see(index)
root = self.root
lOptions = kodiSelectClass(mlist, title = heading, master=root)
return lOptions.index
#noinspection PyUnusedLocal
class DialogProgress(object):
# Create Progress Bar
def create(self, heading, line1='', line2='', line3='' ):
"""Create and show a progress dialog.
heading: string or unicode - dialog heading.
line1: string or unicode - line #1 text.
line2: string or unicode - line #2 text.
line3: string or unicode - line #3 text.
Note:
Use update() to update lines and progressbar.
Example:
pDialog = xbmcgui.DialogProgress()
ret = pDialog.create('XBMC', 'Initializing script...')
"""
width, height = 500, 300
self.cancel = False
self.__root = tk.Tk() #updated by Petr
self.heading = heading
self.line1 = tk.StringVar(self.__root)
self.line2 = tk.StringVar(self.__root)
self.line3 = tk.StringVar(self.__root)
self.__root.resizable(False, False)
self.__root.title(self.heading)
lb = tk.Frame(self.__root)
lb.pack()
tk.Label(lb, textvariable=self.line1).pack(side=tk.TOP, fill = tk.X, expand = 1)
tk.Label(lb, textvariable=self.line2).pack(side=tk.TOP, fill = tk.X, expand = 1)
tk.Label(lb, textvariable=self.line3).pack(side=tk.TOP, fill = tk.X, expand = 1)
pb = tk.Frame(self.__root)
pb.pack(side=tk.TOP)
self.__canvas = tk.Canvas(pb, width=width, height=30)
self.__canvas.grid()
tk.Button(self.__root, text='Cancel', width=40, command=self.doCancel).pack()
self.__width = width
self.__height = 100
self.update(0, line1, line2, line3)
def doCancel(self):
self.cancel = True
def settitle(self, title):
self.__root.title(title)
# Update Progress Bar
def update(self, ratio, line1='', line2='', line3=''):
"""Update's the progress dialog.
percent: integer - percent complete. (0:100)
line1: string or unicode - line #1 text.
line2: string or unicode - line #2 text.
line3: string or unicode - line #3 text.
Note:
If percent == 0, the progressbar will be hidden.
Example:
pDialog.update(25, 'Importing modules...')
"""
ratio = ratio/100.0
input = (line1, line2, line3)
for k, line in enumerate([self.line1, self.line2, self.line3]):
if not input[k]: continue
line.set(input[k])
self.__root.update_idletasks()
self.__canvas.delete(tk.ALL)
self.__canvas.create_rectangle(0, 0, self.__width * ratio, \
self.__height, fill='blue')
self.__root.update_idletasks()
self.__root.update()
self.__root.focus_set()
self.__root.lift()
def iscanceled(self):
"""Returns True if the user pressed cancel."""
return self.cancel
# Close Progress Bar
def close(self):
"""Close the progress dialog."""
self.__root.withdraw()
return True
class DialogProgressBG(object):
"""
DialogProgressBG class
Displays a small progress dialog in the corner of the screen.
"""
def create(self, heading, message=''):
"""
create(heading[, message])--Create and show a background progress dialog.n
heading : string or unicode - dialog headingn
message : [opt] string or unicode - message textn
*Note, 'heading' is used for the dialog's id. Use a unique heading.n
Useupdate() to update heading, message and progressbar.n
example:
- pDialog = xbmcgui.DialogProgressBG()
- pDialog.create('Movie Trailers', 'Downloading Monsters Inc. ...')
"""
width, height = 500, 70
self.cancel = False
self.__root = tk.Tk() #updated by Petr
self.heading = tk.StringVar(self.__root)
self.message = tk.StringVar(self.__root)
self.__root.resizable(False, False)
self.__root.overrideredirect(True)
x = self.__root.winfo_screenwidth() - width - 50
y = self.__root.winfo_screenheight() - height - 70
self.__root.geometry('{}x{}+{}+{}'.format(width, height, x, y))
mframe = tk.Frame(self.__root, relief=tk.SUNKEN, takefocus=True)
mframe.pack()
lb = tk.Frame(mframe)
lb.pack()
tk.Label(lb, textvariable=self.heading).pack(side=tk.TOP, fill = tk.X, expand = 1)
tk.Label(lb, textvariable=self.message).pack(side=tk.TOP, fill = tk.X, expand = 1)
pb = tk.Frame(mframe)
pb.pack(side=tk.TOP)
self.__canvas = tk.Canvas(pb, width=width, height=30)
self.__canvas.grid()
self.__width = width
self.__height = 100
self.update(0, heading, message)
def close(self):
"""
close() --Close the background progress dialog
example:
- pDialog.close()
"""
self.__root.withdraw()
return True
def isFinished(self):
"""
isFinished() --Returns True if the background dialog is active.
example:
- if (pDialog.isFinished()): break
"""
return self.__root.state() == "withdrawn"
def update(self, percent, heading=None, message=None):
"""
update([percent, heading, message])--Updates the background progress dialog.
percent : [opt] integer - percent complete. (0:100)
heading : [opt] string or unicode - dialog heading
message : [opt] string or unicode - message text
*Note, To clear heading or message, you must pass a blank character.
example:
- pDialog.update(25, message='Downloading Finding Nemo ...')
"""
ratio = percent/100.0
input = (heading, message)
for k, line in enumerate([self.heading, self.message]):
if not input[k]: continue
line.set(input[k])
self.__root.update_idletasks()
self.__canvas.delete(tk.ALL)
self.__canvas.create_rectangle(0, 0, self.__width * ratio, \
self.__height, fill='blue')
self.__root.update_idletasks()
self.__root.update()
self.__root.focus_set()
self.__root.lift()
if ratio == 1: self.close()
#noinspection PyUnusedLocal
class Action(object):
"""Action class.
For backwards compatibility reasons the == operator is extended so that it
can compare an action with other actions and action.GetID() with numbers.
Example:
(action == ACTION_MOVE_LEFT)
"""
def getId(self):
"""Returns the action's current id as a long or 0 if no action is mapped in the xml's."""
return long
def getButtonCode(self):
"""Returns the button code for this action."""
return long
def getAmount1(self):
"""Returns the first amount of force applied to the thumbstick."""
return float
def getAmount2(self):
"""Returns the second amount of force applied to the thumbstick."""
return float
'''
Created on 9/05/2014
@author: pybquillast
This module has been ported from xbmcstubs:
__author__ = 'Team XBMC <http://xbmc.org>'
__credits__ = 'Team XBMC'
'''
import sys
import xbmcaddon
_menuSel = 0
_selParameters = None
#
# Variable Documentation
#
SORT_METHOD_ALBUM = 13
SORT_METHOD_ALBUM_IGNORE_THE = 14
SORT_METHOD_ARTIST = 11
SORT_METHOD_ARTIST_IGNORE_THE = 12
SORT_METHOD_BITRATE = 39
SORT_METHOD_CHANNEL = 38
SORT_METHOD_COUNTRY = 16
SORT_METHOD_DATE = 3
SORT_METHOD_DATE_TAKEN = 40
SORT_METHOD_DATEADDED = 19
SORT_METHOD_DRIVE_TYPE = 6
SORT_METHOD_DURATION = 8
SORT_METHOD_EPISODE = 22
SORT_METHOD_FILE = 5
SORT_METHOD_FULLPATH = 32
SORT_METHOD_GENRE = 15
SORT_METHOD_LABEL = 1
SORT_METHOD_LABEL_IGNORE_FOLDERS = 33
SORT_METHOD_LABEL_IGNORE_THE = 2
SORT_METHOD_LASTPLAYED = 34
SORT_METHOD_LISTENERS = 36
SORT_METHOD_MPAA_RATING = 28
SORT_METHOD_NONE = 0
SORT_METHOD_PLAYCOUNT = 35
SORT_METHOD_PLAYLIST_ORDER = 21
SORT_METHOD_PRODUCTIONCODE = 26
SORT_METHOD_PROGRAM_COUNT = 20
SORT_METHOD_SIZE = 4
SORT_METHOD_SONG_RATING = 27
SORT_METHOD_STUDIO = 30
SORT_METHOD_STUDIO_IGNORE_THE = 31
SORT_METHOD_TITLE = 9
SORT_METHOD_TITLE_IGNORE_THE = 10
SORT_METHOD_TRACKNUM = 7
SORT_METHOD_UNSORTED = 37
SORT_METHOD_VIDEO_RATING = 18
SORT_METHOD_VIDEO_RUNTIME = 29
SORT_METHOD_VIDEO_SORT_TITLE = 24
SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE = 25
SORT_METHOD_VIDEO_TITLE = 23
SORT_METHOD_VIDEO_YEAR = 17
#
# FUNCTIONS
#
def addDirectoryItem(handle, url, listitem, isFolder = False, totalItems = 0):
"""
def xbmcplugin.addDirectoryItem (handle,
url,
listitem,
isFolder = False,
totalItems = 0
)
Callback function to pass directory contents back to XBMC.
Returns a bool for successful completion.
handle: integer - handle the plugin was started with.
url: string - url of the entry. would be plugin:// for another virtual directory.
listitem: ListItem - item to add.
isFolder: bool - True=folder / False=not a folder.
totalItems: integer - total number of items that will be passed. (used for progressbar)
Example:
if not xbmcplugin.addDirectoryItem(int(sys.argv[1]), 'F:\\Trailers\\300.mov', listitem, totalItems=50):
break
"""
# global histObj
menuObj = sys.modules['__main__'].menuObj
menuObj.appendToNextMenu(url, listitem, isFolder)
def addDirectoryItems(handle, items, totalItems = 0):
"""
Callback function to pass directory contents back to XBMC as a list.
Returns a bool for successful completion.
handle: integer - handle the plugin was started with.
items: List - list of (url, listitem[, isFolder]) as a tuple to add.
totalItems: integer - total number of items that will be passed. (used for progressbar)
Note:
Large lists benefit over using the standard addDirectoryItem().
You may call this more than once to add items in chunks.
Example:
if not xbmcplugin.addDirectoryItems(int(sys.argv[1]), [(url, listitem, False,)]:
raise
"""
menuObj = sys.modules['__main__'].menuObj
menuObj.extendNextMenu(items)
def addSortMethod(handle, sortMethod, label2 = "%D"):
"""
Adds a sorting method for the media list.
handle: integer - handle the plugin was started with.
sortMethod: integer - number for sortmethod see FileItem.h.
label2Mask: string - the label mask to use for the second label. Defaults to '%D'
applies to: SORT_METHOD_NONE, SORT_METHOD_UNSORTED, SORT_METHOD_VIDEO_TITLE,
SORT_METHOD_TRACKNUM, SORT_METHOD_FILE, SORT_METHOD_TITLE
SORT_METHOD_TITLE_IGNORE_THE, SORT_METHOD_LABEL
SORT_METHOD_LABEL_IGNORE_THE
Example:
xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_TITLE)
"""
pass
def endOfDirectory(handle, succeeded = True, updateListing = False, cacheToDisc = True):
"""
Callback function to tell XBMC that the end of the directory listing in a
virtualPythonFolder module is reached.
handle: integer - handle the plugin was started with.
succeeded: bool - True=script completed successfully/False=Script did not.
updateListing: bool - True=this folder should update the current listing/False=Folder
is a subfolder.
cacheToDisc: bool - True=Folder will cache if extended time/False=this folder will
never cache to disc.
Example:
xbmcplugin.endOfDirectory(int(sys.argv[1]), cacheToDisc=False)
"""
global _menuSel, _selParameters #, histObj
menuObj = sys.modules['__main__'].menuObj
menuObj.displayMenu()
def getSetting(handle, settingID):
"""
Returns the value of a setting as a string.
handle: integer - handle the plugin was started with.
settingID: string - id of the setting that the module needs to access.
Example:
apikey = xbmcplugin.getSetting(int(sys.argv[1]), 'apikey')
"""
pluginId = sys.argv[0]
return xbmcaddon.Addon(pluginId).getSetting(settingID)
pass
def setContent(handle, content):
"""
Sets the plugins content.
handle: integer - handle the plugin was started with.
content: string - content type (eg. movies).
Note:
Possible values for content: files, songs, artists, albums, movies, tvshows, episodes, musicvideos
Example:
xbmcplugin.setContent(int(sys.argv[1]), 'movies')
"""
pass
def setPluginCategory(handle, category):
"""
Sets the plugins name for skins to display.
handle: integer - handle the plugin was started with.
category: string or unicode - plugins sub category.
Example:
xbmcplugin.setPluginCategory(int(sys.argv[1]), 'Comedy')
"""
pass
def setPluginFanart(handle, image = None, color1 = None, color2 = None, color3 = None):
"""
Sets the plugins fanart and color for skins to display.
handle: integer - handle the plugin was started with.\n"
image: string - path to fanart image.
color1: hexstring - color1. (e.g. '0xFFFFFFFF')
color2: hexstring - color2. (e.g. '0xFFFF3300')
color3: hexstring - color3. (e.g. '0xFF000000')
Example:
xbmcplugin.setPluginFanart(int(sys.argv[1]),
'special://home/addons/plugins/video/Apple movie trailers II/fanart.png',
color2='0xFFFF3300')
"""
pass
def setProperty(handle, key, value):
"""
Sets a container property for this plugin.
handle: integer - handle the plugin was started with.
key: string - property name.
value: string or unicode - value of property.
Note:
Key is NOT case sensitive.
Example:
xbmcplugin.setProperty(int(sys.argv[1]), 'Emulator', 'M.A.M.E.')
"""
pass
def setResolvedUrl(handle, succeeded, listitem):
"""
Callback function to tell XBMC that the file plugin has been resolved to a url
handle: integer - handle the plugin was started with.
succeeded: bool - True=script completed successfully/False=Script did not.
listitem: ListItem - item the file plugin resolved to for playback.
Example:
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
"""
menuObj = sys.modules['__main__'].menuObj
print('URL a Ejecutar', listitem.getProperty('path'))
menuObj.setSelectionData(0, (listitem.getProperty('path'), 0))
def setSetting(handle, settingID, value):
"""
Sets a plugin setting for the current running plugin.
handle: integer - handle the plugin was started with.
settingID: string - id of the setting that the module needs to access.
value: string or unicode - value of the setting.
Example:
xbmcplugin.setSetting(int(sys.argv[1]), id='username', value='teamxbmc')
"""
pluginId = sys.argv[0]
return xbmcaddon.Addon(pluginId).setSetting(settingID, value)
pass
'''
Created on 9/05/2014
@author: pybquillast
This module has been ported from xbmcstubs:
__author__ = 'Team XBMC <http://xbmc.org>'
__credits__ = 'Team XBMC'
'''
"""
xbmcvfs Namespace Reference
Classes and functions to work with files and folders.
Classes
class File
class Stat
Functions
def copy
def delete
def rename
def mkdir
def mkdirs
def rmdir
def exists
def listdir
"""
import os
import shutil
#
# Detailed Description
#
# Classes and functions to work with files and folders.
#
#
# Function Documentation
#
def copy(source, destination):
"""
Copy file to destination, returns true/false.
source: string - file to copy.
destination: string - destination file
Example:
success = xbmcvfs.copy(source, destination)
"""
try:
shutil.copy(source, destination)
return True
except:
return False
def delete(fileName):
"""
Deletes a file.
fileName: string - file to delete
Example:
xbmcvfs.delete(file)
"""
try:
os.remove(fileName)
return True
except:
return False
def exists(path):
"""
Checks for a file or folder existance, mimics Pythons os.path.exists()
path: string - file or folder
Example:
success = xbmcvfs.exists(path)
"""
return os.path.exists(path)
def listdir(path):
"""
listdir(path) -- lists content of a folder.
path : folder
example:
- dirs, files = xbmcvfs.listdir(path)
"""
return os.walk(path).next()[1:]
def mkdir(path):
"""
Create a folder.
path: folder
Example:
success = xbmcfvs.mkdir(path)
"""
os.mkdir(path)
return os.path.exists(path)
def mkdirs(path):
"""
mkdirs(path)--Create folder(s) - it will create all folders in the path.
path : folder
example:
- success = xbmcvfs.mkdirs(path)
Create folder(s) - it will create all folders in the path.
path: folder
Example:
success = xbmcfvs.mkdirs(path)
"""
os.makedirs(path)
return os.path.exists(path)
def rename(fileName, newFileName):
"""
Renames a file, returns true/false.
fileName: string - file to rename
newFileName: string - new filename, including the full path
Example:
success = xbmcvfs.rename(file,newFileName)
"""
try:
os.rename(fileName, newFileName)
return True
except:
return False
def rmdir(path):
"""
Remove a folder.
path: folder
Example:
success = xbmcfvs.rmdir(path)
"""
try:
os.rmdir(path)
return True
except:
return False
#
# CLASSES
#
class File(object):
"""
xbmcvfs.File Class Reference
Public Member Functions
def __init__
def close
def read
def readBytes
def seek
def size
def write
"""
# Constructor & Destructor Documentation
def __init__(self, filename, optype = None):
"""
'w' - opt open for write
example:
f = xbmcvfs.File(file, ['w'])
"""
self._file = open(filename, *optype)
pass
# Member Function Documentation
def close(self):
"""
example:
f = xbmcvfs.File(file)
f.close()
"""
self._file.close()
pass
def read(self, bytesToRead = None):
"""
bytes : how many bytes to read [opt]- if not set it will read the whole file
example:
f = xbmcvfs.File(file)
b = f.read()
f.close()
"""
return self._file.read(bytesToRead)
def readBytes(self, numbytes):
"""
readBytes(numbytes)
numbytes : how many bytes to read [opt]- if not set it will read the whole file
returns: bytearray
example:
f = xbmcvfs.File(file)
b = f.read()
f.close()
"""
return self._file.read(numbytes)
def seek(self, offset, whence):
"""
FilePosition : position in the file
Whence : where in a file to seek from[0 begining, 1 current , 2 end possition]
example:
f = xbmcvfs.File(file)
result = f.seek(8129, 0)
f.close()
"""
return self._file.seek(offset, whence)
def size(self):
"""
example:
f = xbmcvfs.File(file)
s = f.size()
f.close()
"""
return self._file.__sizeof__()
pass
def write(self, bufferToWrite):
"""
buffer : buffer to write to file
example:
f = xbmcvfs.File(file, 'w', True)
result = f.write(buffer)
f.close()
"""
return self._file.write(bufferToWrite)
pass
class Stat(object):
def __init__(self, path):
"""
Stat(path) -- get file or file system status.
path : file or folder
example:
- print xbmcvfs.Stat(path).st_mtime()
"""
self._stat = os.stat(path)
pass
#
# Member Function Documentation
#
def st_atime(self): return self._stat.st_atime
def st_ctime(self): return self._stat.st_ctime
def st_gid(self): return self._stat.st_gid
def st_ino(self): return self._stat.st_ino
def st_mode(self): return self._stat.st_mode
def st_mtime(self): return self._stat.st_mtime
def st_nlink(self): return self._stat.st_nlink
def st_size(self): return self._stat.st_size
def st_uid(self): return self._stat.st_uid
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment