This commit is contained in:
croneter 2018-02-11 12:59:04 +01:00
parent 406c2b9f63
commit ca8ad96a05
19 changed files with 301 additions and 362 deletions

View file

@ -32,7 +32,7 @@ sys_path.append(_base_resource)
###############################################################################
import entrypoint
from utils import window, reset, passwordsXML, language as lang, dialog, \
from utils import window, reset, passwords_xml, language as lang, dialog, \
plex_command
from pickler import unpickle_me, pickl_window
from PKC_listitem import convert_PKC_to_listitem
@ -115,7 +115,7 @@ class Main():
entrypoint.resetAuth()
elif mode == 'passwords':
passwordsXML()
passwords_xml()
elif mode == 'switchuser':
entrypoint.switchPlexUser()

View file

@ -40,8 +40,8 @@ from xbmcvfs import exists
import clientinfo as client
from downloadutils import DownloadUtils as DU
from utils import window, settings, language as lang, tryDecode, tryEncode, \
DateToKodi, exists_dir, slugify, dialog
from utils import window, settings, language as lang, try_decode, try_encode, \
unix_date_to_kodi, exists_dir, slugify, dialog
import PlexFunctions as PF
import plexdb_functions as plexdb
import variables as v
@ -139,7 +139,7 @@ class API():
ans = None
if ans is not None:
try:
ans = tryDecode(unquote(ans))
ans = try_decode(unquote(ans))
except UnicodeDecodeError:
# Sometimes, Plex seems to have encoded in latin1
ans = unquote(ans).decode('latin1')
@ -167,7 +167,7 @@ class API():
self.item[0][0].attrib['key']))
# Attach Plex id to url to let it be picked up by our playqueue agent
# later
return tryEncode('%s&plex_id=%s' % (path, self.getRatingKey()))
return try_encode('%s&plex_id=%s' % (path, self.getRatingKey()))
def getTVShowPath(self):
"""
@ -194,7 +194,7 @@ class API():
"""
res = self.item.attrib.get('addedAt')
if res is not None:
res = DateToKodi(res)
res = unix_date_to_kodi(res)
else:
res = '2000-01-01 10:00:00'
return res
@ -231,7 +231,7 @@ class API():
played = True if playcount else False
try:
lastPlayedDate = DateToKodi(int(item['lastViewedAt']))
lastPlayedDate = unix_date_to_kodi(int(item['lastViewedAt']))
except (KeyError, ValueError):
lastPlayedDate = None
@ -884,7 +884,7 @@ class API():
parameters = {
'api_key': apiKey,
'language': v.KODILANGUAGE,
'query': tryEncode(title)
'query': try_encode(title)
}
data = DU().downloadUrl(url,
authenticate=False,
@ -1196,12 +1196,12 @@ class API():
languages.append(stream.attrib['language'])
languages = ', '.join(languages)
if filename:
option = tryEncode(filename)
option = try_encode(filename)
if languages:
if option:
option = '%s (%s): ' % (option, tryEncode(languages))
option = '%s (%s): ' % (option, try_encode(languages))
else:
option = '%s: ' % tryEncode(languages)
option = '%s: ' % try_encode(languages)
if 'videoResolution' in entry.attrib:
option = '%s%sp ' % (option,
entry.attrib.get('videoResolution'))
@ -1544,7 +1544,7 @@ class API():
# exist() needs a / or \ at the end to work for directories
if folder is False:
# files
check = exists(tryEncode(path))
check = exists(try_encode(path))
else:
# directories
if "\\" in path:
@ -1640,7 +1640,7 @@ class API():
plexitem = "plex_%s" % playurl
window('%s.runtime' % plexitem, value=str(userdata['Runtime']))
window('%s.type' % plexitem, value=itemtype)
state.PLEX_IDS[tryDecode(playurl)] = self.getRatingKey()
state.PLEX_IDS[try_decode(playurl)] = self.getRatingKey()
# window('%s.itemid' % plexitem, value=self.getRatingKey())
window('%s.playcount' % plexitem, value=str(userdata['PlayCount']))

View file

@ -11,7 +11,7 @@ from threading import Thread
from xbmc import sleep
from downloadutils import DownloadUtils as DU
from utils import settings, tryEncode, tryDecode
from utils import settings, try_encode, try_decode
from variables import PLEX_TO_KODI_TIMEFACTOR
import plex_tv
@ -306,11 +306,11 @@ def _plex_gdm():
}
for line in response['data'].split('\n'):
if 'Content-Type:' in line:
pms['product'] = tryDecode(line.split(':')[1].strip())
pms['product'] = try_decode(line.split(':')[1].strip())
elif 'Host:' in line:
pms['baseURL'] = line.split(':')[1].strip()
elif 'Name:' in line:
pms['name'] = tryDecode(line.split(':')[1].strip())
pms['name'] = try_decode(line.split(':')[1].strip())
elif 'Port:' in line:
pms['port'] = line.split(':')[1].strip()
elif 'Resource-Identifier:' in line:
@ -820,7 +820,7 @@ def transcode_image_path(key, AuthToken, path, width, height):
path = 'http://127.0.0.1:32400' + key
else: # internal path, add-on
path = 'http://127.0.0.1:32400' + path + '/' + key
path = tryEncode(path)
path = try_encode(path)
# This is bogus (note the extra path component) but ATV is stupid when it
# comes to caching images, it doesn't use querystrings. Fortunately PMS is
# lenient...

View file

@ -12,8 +12,8 @@ import requests
from xbmc import sleep, translatePath
from xbmcvfs import exists
from utils import window, settings, language as lang, kodiSQL, tryEncode, \
thread_methods, dialog, exists_dir, tryDecode
from utils import window, settings, language as lang, kodi_sql, try_encode, \
thread_methods, dialog, exists_dir, try_decode
import state
# Disable annoying requests warnings
@ -134,13 +134,13 @@ class Artwork():
if dialog('yesno', "Image Texture Cache", lang(39251)):
LOG.info("Resetting all cache data first")
# Remove all existing textures first
path = tryDecode(translatePath("special://thumbnails/"))
path = try_decode(translatePath("special://thumbnails/"))
if exists_dir(path):
rmtree(path, ignore_errors=True)
self.restoreCacheDirectories()
# remove all existing data from texture DB
connection = kodiSQL('texture')
connection = kodi_sql('texture')
cursor = connection.cursor()
query = 'SELECT tbl_name FROM sqlite_master WHERE type=?'
cursor.execute(query, ('table', ))
@ -153,7 +153,7 @@ class Artwork():
connection.close()
# Cache all entries in video DB
connection = kodiSQL('video')
connection = kodi_sql('video')
cursor = connection.cursor()
# dont include actors
query = "SELECT url FROM art WHERE media_type != ?"
@ -166,7 +166,7 @@ class Artwork():
for url in result:
self.cacheTexture(url[0])
# Cache all entries in music DB
connection = kodiSQL('music')
connection = kodi_sql('music')
cursor = connection.cursor()
cursor.execute("SELECT url FROM art")
result = cursor.fetchall()
@ -179,7 +179,7 @@ class Artwork():
def cacheTexture(self, url):
# Cache a single image url to the texture cache
if url and self.enableTextureCache:
self.queue.put(double_urlencode(tryEncode(url)))
self.queue.put(double_urlencode(try_encode(url)))
def addArtwork(self, artwork, kodiId, mediaType, cursor):
# Kodi conversion table
@ -323,7 +323,7 @@ class Artwork():
def deleteCachedArtwork(self, url):
# Only necessary to remove and apply a new backdrop or poster
connection = kodiSQL('texture')
connection = kodi_sql('texture')
cursor = connection.cursor()
try:
cursor.execute("SELECT cachedurl FROM texture WHERE url = ?",
@ -336,7 +336,7 @@ class Artwork():
path = translatePath("special://thumbnails/%s" % cachedurl)
LOG.debug("Deleting cached thumbnail: %s" % path)
if exists(path):
rmtree(tryDecode(path), ignore_errors=True)
rmtree(try_decode(path), ignore_errors=True)
cursor.execute("DELETE FROM texture WHERE url = ?", (url,))
connection.commit()
finally:
@ -347,4 +347,4 @@ class Artwork():
LOG.info("Restoring cache directories...")
paths = ("","0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","Video","plex")
for p in paths:
makedirs(tryDecode(translatePath("special://thumbnails/%s" % p)))
makedirs(try_decode(translatePath("special://thumbnails/%s" % p)))

View file

@ -11,8 +11,8 @@ import xbmcplugin
from xbmc import sleep, executebuiltin, translatePath
from xbmcgui import ListItem
from utils import window, settings, language as lang, dialog, tryEncode, \
CatchExceptions, exists_dir, plex_command, tryDecode
from utils import window, settings, language as lang, dialog, try_encode, \
CatchExceptions, exists_dir, plex_command, try_decode
import downloadutils
from PlexFunctions import GetPlexMetadata, GetPlexSectionResults, \
@ -53,11 +53,11 @@ def chooseServer():
if not __LogOut():
return
from utils import deletePlaylists, deleteNodes
from utils import delete_playlists, delete_nodes
# First remove playlists
deletePlaylists()
delete_playlists()
# Remove video nodes
deleteNodes()
delete_nodes()
# Log in again
__LogIn()
@ -175,10 +175,10 @@ def switchPlexUser():
return
# First remove playlists of old user
from utils import deletePlaylists, deleteNodes
deletePlaylists()
from utils import delete_playlists, delete_nodes
delete_playlists()
# Remove video nodes
deleteNodes()
delete_nodes()
__LogIn()
@ -455,14 +455,14 @@ def getVideoFiles(plexId, params):
if exists_dir(path):
for root, dirs, files in walk(path):
for directory in dirs:
item_path = tryEncode(join(root, directory))
item_path = try_encode(join(root, directory))
li = ListItem(item_path, path=item_path)
xbmcplugin.addDirectoryItem(handle=HANDLE,
url=item_path,
listitem=li,
isFolder=True)
for file in files:
item_path = tryEncode(join(root, file))
item_path = try_encode(join(root, file))
li = ListItem(item_path, path=item_path)
xbmcplugin.addDirectoryItem(handle=HANDLE,
url=file,
@ -490,7 +490,7 @@ def getExtraFanArt(plexid, plexPath):
# We need to store the images locally for this to work
# because of the caching system in xbmc
fanartDir = tryDecode(translatePath(
fanartDir = try_decode(translatePath(
"special://thumbnails/plex/%s/" % plexid))
if not exists_dir(fanartDir):
# Download the images to the cache directory
@ -504,19 +504,19 @@ def getExtraFanArt(plexid, plexPath):
backdrops = api.getAllArtwork()['Backdrop']
for count, backdrop in enumerate(backdrops):
# Same ordering as in artwork
fanartFile = tryEncode(join(fanartDir, "fanart%.3d.jpg" % count))
fanartFile = try_encode(join(fanartDir, "fanart%.3d.jpg" % count))
li = ListItem("%.3d" % count, path=fanartFile)
xbmcplugin.addDirectoryItem(
handle=HANDLE,
url=fanartFile,
listitem=li)
copyfile(backdrop, tryDecode(fanartFile))
copyfile(backdrop, try_decode(fanartFile))
else:
log.info("Found cached backdrop.")
# Use existing cached images
for root, dirs, files in walk(fanartDir):
for file in files:
fanartFile = tryEncode(join(root, file))
fanartFile = try_encode(join(root, file))
li = ListItem(file, path=fanartFile)
xbmcplugin.addDirectoryItem(handle=HANDLE,
url=fanartFile,

View file

@ -6,7 +6,7 @@ import xml.etree.ElementTree as etree
from xbmc import executebuiltin, translatePath
from utils import settings, window, language as lang, tryEncode, tryDecode, \
from utils import settings, window, language as lang, try_encode, try_decode, \
XmlKodiSetting, reboot_kodi, dialog
from migration import check_migration
from downloadutils import DownloadUtils as DU
@ -76,7 +76,7 @@ def reload_pkc():
set_webserver()
# To detect Kodi profile switches
window('plex_kodiProfile',
value=tryDecode(translatePath("special://profile")))
value=try_decode(translatePath("special://profile")))
getDeviceId()
# Initialize the PKC playqueues
PQ.init_playqueues()
@ -355,7 +355,7 @@ class InitialSetup(object):
dialog('ok',
lang(29999),
'%s %s' % (lang(39214),
tryEncode(server['name'])))
try_encode(server['name'])))
return
else:
return
@ -610,8 +610,8 @@ class InitialSetup(object):
line1=lang(39029),
line2=lang(39030)):
LOG.debug("Presenting network credentials dialog.")
from utils import passwordsXML
passwordsXML()
from utils import passwords_xml
passwords_xml()
# Disable Plex music?
if dialog('yesno', heading=lang(29999), line1=lang(39016)):
LOG.debug("User opted to disable Plex music library.")

View file

@ -6,7 +6,7 @@ from ntpath import dirname
from datetime import datetime
from artwork import Artwork
from utils import window, kodiSQL, CatchExceptions
from utils import window, kodi_sql, CatchExceptions
import plexdb_functions as plexdb
import kodidb_functions as kodidb
@ -43,9 +43,9 @@ class Items(object):
"""
Open DB connections and cursors
"""
self.plexconn = kodiSQL('plex')
self.plexconn = kodi_sql('plex')
self.plexcursor = self.plexconn.cursor()
self.kodiconn = kodiSQL('video')
self.kodiconn = kodi_sql('video')
self.kodicursor = self.kodiconn.cursor()
self.plex_db = plexdb.Plex_DB_Functions(self.plexcursor)
self.kodi_db = kodidb.Kodidb_Functions(self.kodicursor)
@ -1273,10 +1273,10 @@ class Music(Items):
OVERWRITE this method, because we need to open another DB.
Open DB connections and cursors
"""
self.plexconn = kodiSQL('plex')
self.plexconn = kodi_sql('plex')
self.plexcursor = self.plexconn.cursor()
# Here it is, not 'video' but 'music'
self.kodiconn = kodiSQL('music')
self.kodiconn = kodi_sql('music')
self.kodicursor = self.kodiconn.cursor()
self.plex_db = plexdb.Plex_DB_Functions(self.plexcursor)
self.kodi_db = kodidb.Kodidb_Functions(self.kodicursor)

View file

@ -5,7 +5,7 @@ from logging import getLogger
from ntpath import dirname
import artwork
from utils import kodiSQL
from utils import kodi_sql
import variables as v
###############################################################################
@ -30,7 +30,7 @@ class GetKodiDB():
self.db_type = db_type
def __enter__(self):
self.kodiconn = kodiSQL(self.db_type)
self.kodiconn = kodi_sql(self.db_type)
kodi_db = Kodidb_Functions(self.kodiconn.cursor())
return kodi_db

View file

@ -8,10 +8,10 @@ from random import shuffle
import xbmc
from xbmcvfs import exists
from utils import window, settings, getUnixTimestamp, \
thread_methods, create_actor_db_index, dialog, LogTime, playlistXSP,\
language as lang, DateToKodi, reset, tryDecode, deletePlaylists, \
deleteNodes, tryEncode, compare_version
from utils import window, settings, unix_timestamp, thread_methods, \
create_actor_db_index, dialog, LogTime, playlist_xsp, language as lang, \
unix_date_to_kodi, reset, try_decode, delete_playlists, delete_nodes, \
try_encode, compare_version
import downloadutils
import itemtypes
import plexdb_functions as plexdb
@ -155,7 +155,7 @@ class LibrarySync(Thread):
log.debug('No timestamp; using 0')
# Set the timer
koditime = getUnixTimestamp()
koditime = unix_timestamp()
# Toggle watched state
scrobble(plexId, 'watched')
# Let the PMS process this first!
@ -329,7 +329,7 @@ class LibrarySync(Thread):
# Create playlist for the video library
if (foldername not in playlists and
mediatype in (v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_SHOW)):
playlistXSP(mediatype, foldername, folderid, viewtype)
playlist_xsp(mediatype, foldername, folderid, viewtype)
playlists.append(foldername)
# Create the video node
if (foldername not in nodes and
@ -371,7 +371,7 @@ class LibrarySync(Thread):
# The tag could be a combined view. Ensure there's
# no other tags with the same name before deleting
# playlist.
playlistXSP(mediatype,
playlist_xsp(mediatype,
current_viewname,
folderid,
current_viewtype,
@ -388,7 +388,7 @@ class LibrarySync(Thread):
# Added new playlist
if (foldername not in playlists and mediatype in
(v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_SHOW)):
playlistXSP(mediatype,
playlist_xsp(mediatype,
foldername,
folderid,
viewtype)
@ -414,7 +414,7 @@ class LibrarySync(Thread):
if mediatype != v.PLEX_TYPE_ARTIST:
if (foldername not in playlists and mediatype in
(v.PLEX_TYPE_MOVIE, v.PLEX_TYPE_SHOW)):
playlistXSP(mediatype,
playlist_xsp(mediatype,
foldername,
folderid,
viewtype)
@ -1102,7 +1102,7 @@ class LibrarySync(Thread):
"""
self.videoLibUpdate = False
self.musicLibUpdate = False
now = getUnixTimestamp()
now = unix_timestamp()
deleteListe = []
for i, item in enumerate(self.itemsToProcess):
if self.thread_stopped() or self.thread_suspended():
@ -1220,7 +1220,7 @@ class LibrarySync(Thread):
'state': status,
'type': typus,
'ratingKey': str(item['itemID']),
'timestamp': getUnixTimestamp(),
'timestamp': unix_timestamp(),
'attempt': 0
})
elif typus in (v.PLEX_TYPE_MOVIE,
@ -1237,7 +1237,7 @@ class LibrarySync(Thread):
'state': status,
'type': typus,
'ratingKey': plex_id,
'timestamp': getUnixTimestamp(),
'timestamp': unix_timestamp(),
'attempt': 0
})
@ -1276,7 +1276,7 @@ class LibrarySync(Thread):
'state': None, # Don't need a state here
'type': kodi_info[5],
'ratingKey': plex_id,
'timestamp': getUnixTimestamp(),
'timestamp': unix_timestamp(),
'attempt': 0
})
@ -1386,7 +1386,7 @@ class LibrarySync(Thread):
resume,
session['duration'],
session['file_id'],
DateToKodi(getUnixTimestamp()))
unix_date_to_kodi(unix_timestamp()))
def fanartSync(self, refresh=False):
"""
@ -1430,9 +1430,9 @@ class LibrarySync(Thread):
window('plex_dbScan', value="true")
state.DB_SCAN = True
# First remove playlists
deletePlaylists()
delete_playlists()
# Remove video nodes
deleteNodes()
delete_nodes()
# Kick off refresh
if self.maintainViews() is True:
# Ran successfully
@ -1549,11 +1549,11 @@ class LibrarySync(Thread):
# Also runs when first installed
# Verify the video database can be found
videoDb = v.DB_VIDEO_PATH
if not exists(tryEncode(videoDb)):
if not exists(try_encode(videoDb)):
# Database does not exists
log.error("The current Kodi version is incompatible "
"to know which Kodi versions are supported.")
log.error('Current Kodi version: %s' % tryDecode(
log.error('Current Kodi version: %s' % try_decode(
xbmc.getInfoLabel('System.BuildVersion')))
# "Current Kodi version is unsupported, cancel lib sync"
dialog('ok', heading='{plex}', line1=lang(39403))
@ -1562,10 +1562,10 @@ class LibrarySync(Thread):
state.DB_SCAN = True
window('plex_dbScan', value="true")
log.info("Db version: %s" % settings('dbCreatedWithVersion'))
lastTimeSync = getUnixTimestamp()
lastTimeSync = unix_timestamp()
# Initialize time offset Kodi - PMS
self.syncPMStime()
lastSync = getUnixTimestamp()
lastSync = unix_timestamp()
if settings('FanartTV') == 'true':
# Start getting additional missing artwork
with plexdb.Get_Plex_DB() as plex_db:
@ -1579,8 +1579,8 @@ class LibrarySync(Thread):
'refresh': True
})
log.info('Refreshing video nodes and playlists now')
deletePlaylists()
deleteNodes()
delete_playlists()
delete_nodes()
log.info("Initial start-up full sync starting")
librarySync = fullSync()
window('plex_dbScan', clear=True)
@ -1604,7 +1604,7 @@ class LibrarySync(Thread):
self.triage_lib_scans()
self.force_dialog = False
continue
now = getUnixTimestamp()
now = unix_timestamp()
# Standard syncs - don't force-show dialogs
self.force_dialog = False
if (now - lastSync > FULL_SYNC_INTERVALL and

View file

@ -12,7 +12,7 @@ LEVELS = {
###############################################################################
def tryEncode(uniString, encoding='utf-8'):
def try_encode(uniString, encoding='utf-8'):
"""
Will try to encode uniString (in unicode) to encoding. This possibly
fails with e.g. Android TV's Python, which does not accept arguments for
@ -43,5 +43,5 @@ class LogHandler(logging.StreamHandler):
try:
xbmc.log(self.format(record), level=LEVELS[record.levelno])
except UnicodeEncodeError:
xbmc.log(tryEncode(self.format(record)),
xbmc.log(try_encode(self.format(record)),
level=LEVELS[record.levelno])

View file

@ -18,7 +18,7 @@ from playutils import PlayUtils
from PKC_listitem import PKC_ListItem
from pickler import pickle_me, Playback_Successful
import json_rpc as js
from utils import settings, dialog, language as lang, tryEncode
from utils import settings, dialog, language as lang, try_encode
from plexbmchelper.subscribers import LOCKER
import variables as v
import state
@ -167,7 +167,7 @@ def _prep_playlist_stack(xml):
path = ('plugin://plugin.video.plexkodiconnect?%s'
% urlencode(params))
listitem = api.CreateListItemFromPlexItem()
listitem.setPath(tryEncode(path))
listitem.setPath(try_encode(path))
else:
# Will add directly via the Kodi DB
path = None
@ -244,7 +244,7 @@ def conclude_playback(playqueue, pos):
playurl = playutils.getPlayUrl()
else:
playurl = item.file
listitem.setPath(tryEncode(playurl))
listitem.setPath(try_encode(playurl))
if item.playmethod in ('DirectStream', 'DirectPlay'):
listitem.setSubtitles(api.externalSubs())
else:
@ -322,14 +322,14 @@ def process_indirect(key, offset, resolve=True):
return
playurl = xml[0].attrib['key']
item.file = playurl
listitem.setPath(tryEncode(playurl))
listitem.setPath(try_encode(playurl))
playqueue.items.append(item)
if resolve is True:
result.listitem = listitem
pickle_me(result)
else:
thread = Thread(target=Player().play,
args={'item': tryEncode(playurl),
args={'item': try_encode(playurl),
'listitem': listitem})
thread.setDaemon(True)
LOG.info('Done initializing PKC playback, starting Kodi player')

View file

@ -8,7 +8,7 @@ from re import compile as re_compile
import plexdb_functions as plexdb
from downloadutils import DownloadUtils as DU
from utils import tryEncode, escape_html
from utils import try_encode, escape_html
from PlexAPI import API
from PlexFunctions import GetPlexMetadata
import json_rpc as js
@ -60,7 +60,7 @@ class PlaylistObjectBaseclase(object):
continue
if isinstance(getattr(self, key), (str, unicode)):
answ += '\'%s\': \'%s\', ' % (key,
tryEncode(getattr(self, key)))
try_encode(getattr(self, key)))
else:
# e.g. int
answ += '\'%s\': %s, ' % (key, str(getattr(self, key)))
@ -168,7 +168,7 @@ class Playlist_Item(object):
continue
if isinstance(getattr(self, key), (str, unicode)):
answ += '\'%s\': \'%s\', ' % (key,
tryEncode(getattr(self, key)))
try_encode(getattr(self, key)))
else:
# e.g. int
answ += '\'%s\': %s, ' % (key, str(getattr(self, key)))

View file

@ -4,7 +4,7 @@
from logging import getLogger
from downloadutils import DownloadUtils as DU
from utils import window, settings, language as lang, dialog, tryEncode
from utils import window, settings, language as lang, dialog, try_encode
import variables as v
###############################################################################
@ -274,7 +274,7 @@ class PlayUtils():
codec,
channellayout)
audio_streams_list.append(index)
audio_streams.append(tryEncode(track))
audio_streams.append(try_encode(track))
audio_numb += 1
# Subtitles
@ -306,7 +306,7 @@ class PlayUtils():
"%s%s" % (window('pms_server'),
stream.attrib['key']))
downloadable_streams.append(index)
download_subs.append(tryEncode(path))
download_subs.append(try_encode(path))
else:
track = "%s (%s)" % (track, lang(39710)) # burn-in
if stream.attrib.get('selected') == '1' and downloadable:
@ -315,7 +315,7 @@ class PlayUtils():
default_sub = index
subtitle_streams_list.append(index)
subtitle_streams.append(tryEncode(track))
subtitle_streams.append(try_encode(track))
sub_num += 1
if audio_numb > 1:

View file

@ -4,7 +4,7 @@ from logging import getLogger
from xbmc import sleep, executebuiltin
from downloadutils import DownloadUtils as DU
from utils import dialog, language as lang, settings, tryEncode
from utils import dialog, language as lang, settings, try_encode
import variables as v
import state
@ -39,7 +39,7 @@ def choose_home_user(token):
username = user['title']
userlist.append(username)
# To take care of non-ASCII usernames
userlist_coded.append(tryEncode(username))
userlist_coded.append(try_encode(username))
usernumber = len(userlist)
username = ''
usertoken = ''

View file

@ -3,7 +3,7 @@
###############################################################################
from logging import getLogger
from utils import kodiSQL
from utils import kodi_sql
import variables as v
###############################################################################
@ -22,7 +22,7 @@ class Get_Plex_DB():
and the db gets closed
"""
def __enter__(self):
self.plexconn = kodiSQL('plex')
self.plexconn = kodi_sql('plex')
return Plex_DB_Functions(self.plexconn.cursor())
def __exit__(self, type, value, traceback):

View file

@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
"""
Various functions and decorators for PKC
"""
###############################################################################
from logging import getLogger
from cProfile import Profile
@ -7,7 +9,7 @@ from pstats import Stats
from sqlite3 import connect, OperationalError
from datetime import datetime, timedelta
from StringIO import StringIO
from time import localtime, strftime, strptime
from time import localtime, strftime
from unicodedata import normalize
import xml.etree.ElementTree as etree
from functools import wraps, partial
@ -21,12 +23,13 @@ import xbmc
import xbmcaddon
import xbmcgui
from xbmcvfs import exists, delete
import variables as v
import state
###############################################################################
log = getLogger("PLEX."+__name__)
LOG = getLogger("PLEX." + __name__)
WINDOW = xbmcgui.Window(10000)
ADDON = xbmcaddon.Addon(id='plugin.video.plexkodiconnect')
@ -46,7 +49,8 @@ def reboot_kodi(message=None):
dialog('ok', heading='{plex}', line1=message)
xbmc.executebuiltin('RestartApp')
def window(property, value=None, clear=False, windowid=10000):
def window(prop, value=None, clear=False, windowid=10000):
"""
Get or set window property - thread safe!
@ -60,11 +64,11 @@ def window(property, value=None, clear=False, windowid=10000):
win = WINDOW
if clear:
win.clearProperty(property)
win.clearProperty(prop)
elif value is not None:
win.setProperty(tryEncode(property), tryEncode(value))
win.setProperty(try_encode(prop), try_encode(value))
else:
return tryDecode(win.getProperty(property))
return try_decode(win.getProperty(prop))
def plex_command(key, value):
@ -90,10 +94,10 @@ def settings(setting, value=None):
addon = xbmcaddon.Addon(id='plugin.video.plexkodiconnect')
if value is not None:
# Takes string or unicode by default!
addon.setSetting(tryEncode(setting), tryEncode(value))
addon.setSetting(try_encode(setting), try_encode(value))
else:
# Should return unicode by default, but just in case
return tryDecode(addon.getSetting(setting))
return try_decode(addon.getSetting(setting))
def exists_dir(path):
@ -104,24 +108,26 @@ def exists_dir(path):
Feed with encoded string or unicode
"""
if v.KODIVERSION >= 17:
answ = exists(tryEncode(path))
answ = exists(try_encode(path))
else:
dummyfile = join(tryDecode(path), 'dummyfile.txt')
dummyfile = join(try_decode(path), 'dummyfile.txt')
try:
with open(dummyfile, 'w') as f:
f.write('text')
with open(dummyfile, 'w') as filer:
filer.write('text')
except IOError:
# folder does not exist yet
answ = 0
else:
# Folder exists. Delete file again.
delete(tryEncode(dummyfile))
delete(try_encode(dummyfile))
answ = 1
return answ
def language(stringid):
# Central string retrieval
"""
Central string retrieval from strings.po
"""
return ADDON.getLocalizedString(stringid)
@ -236,7 +242,7 @@ def kodi_time_to_millis(time):
return ret
def tryEncode(uniString, encoding='utf-8'):
def try_encode(uniString, encoding='utf-8'):
"""
Will try to encode uniString (in unicode) to encoding. This possibly
fails with e.g. Android TV's Python, which does not accept arguments for
@ -252,7 +258,7 @@ def tryEncode(uniString, encoding='utf-8'):
return uniString
def tryDecode(string, encoding='utf-8'):
def try_decode(string, encoding='utf-8'):
"""
Will try to decode string (encoded) using encoding. This possibly
fails with e.g. Android TV's Python, which does not accept arguments for
@ -295,7 +301,7 @@ def escape_html(string):
return string
def DateToKodi(stamp):
def unix_date_to_kodi(stamp):
"""
converts a Unix time stamp (seconds passed sinceJanuary 1 1970) to a
propper, human-readable time stamp used by Kodi
@ -313,49 +319,42 @@ def DateToKodi(stamp):
return localdate
def IntFromStr(string):
"""
Returns an int from string or the int 0 if something happened
"""
try:
result = int(string)
except:
result = 0
return result
def getUnixTimestamp(secondsIntoTheFuture=None):
def unix_timestamp(seconds_into_the_future=None):
"""
Returns a Unix time stamp (seconds passed since January 1 1970) for NOW as
an integer.
Optionally, pass secondsIntoTheFuture: positive int's will result in a
Optionally, pass seconds_into_the_future: positive int's will result in a
future timestamp, negative the past
"""
if secondsIntoTheFuture:
future = datetime.utcnow() + timedelta(seconds=secondsIntoTheFuture)
if seconds_into_the_future:
future = datetime.utcnow() + timedelta(seconds=seconds_into_the_future)
else:
future = datetime.utcnow()
return timegm(future.timetuple())
def kodiSQL(media_type="video"):
def kodi_sql(media_type=None):
"""
Open a connection to the Kodi database.
media_type: 'video' (standard if not passed), 'plex', 'music', 'texture'
"""
if media_type == "plex":
dbPath = v.DB_PLEX_PATH
db_path = v.DB_PLEX_PATH
elif media_type == "music":
dbPath = v.DB_MUSIC_PATH
db_path = v.DB_MUSIC_PATH
elif media_type == "texture":
dbPath = v.DB_TEXTURE_PATH
db_path = v.DB_TEXTURE_PATH
else:
dbPath = v.DB_VIDEO_PATH
return connect(dbPath, timeout=60.0)
db_path = v.DB_VIDEO_PATH
return connect(db_path, timeout=60.0)
def create_actor_db_index():
"""
Index the "actors" because we got a TON - speed up SELECT and WHEN
"""
conn = kodiSQL('video')
conn = kodi_sql('video')
cursor = conn.cursor()
try:
cursor.execute("""
@ -370,6 +369,10 @@ def create_actor_db_index():
def reset():
"""
User navigated to the PKC settings, Advanced, and wants to reset the Kodi
database and possibly PKC entirely
"""
# Are you sure you want to reset your local Kodi database?
if not dialog('yesno',
heading='{plex} %s ' % language(30132),
@ -380,7 +383,7 @@ def reset():
plex_command('STOP_SYNC', 'True')
count = 10
while window('plex_dbScan') == "true":
log.debug("Sync is running, will retry: %s..." % count)
LOG.debug("Sync is running, will retry: %s...", count)
count -= 1
if count == 0:
# Could not stop the database from running. Please try again later.
@ -391,14 +394,14 @@ def reset():
xbmc.sleep(1000)
# Clean up the playlists
deletePlaylists()
delete_playlists()
# Clean up the video nodes
deleteNodes()
delete_nodes()
# Wipe the kodi databases
log.info("Resetting the Kodi video database.")
connection = kodiSQL('video')
LOG.info("Resetting the Kodi video database.")
connection = kodi_sql('video')
cursor = connection.cursor()
cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
rows = cursor.fetchall()
@ -410,8 +413,8 @@ def reset():
cursor.close()
if settings('enableMusic') == "true":
log.info("Resetting the Kodi music database.")
connection = kodiSQL('music')
LOG.info("Resetting the Kodi music database.")
connection = kodi_sql('music')
cursor = connection.cursor()
cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
rows = cursor.fetchall()
@ -423,8 +426,8 @@ def reset():
cursor.close()
# Wipe the Plex database
log.info("Resetting the Plex database.")
connection = kodiSQL('plex')
LOG.info("Resetting the Plex database.")
connection = kodi_sql('plex')
cursor = connection.cursor()
cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
rows = cursor.fetchall()
@ -441,21 +444,21 @@ def reset():
if dialog('yesno',
heading='{plex} %s ' % language(30132),
line1=language(39602)):
log.info("Resetting all cached artwork.")
LOG.info("Resetting all cached artwork.")
# Remove all existing textures first
path = xbmc.translatePath("special://thumbnails/")
if exists(path):
rmtree(tryDecode(path), ignore_errors=True)
rmtree(try_decode(path), ignore_errors=True)
# remove all existing data from texture DB
connection = kodiSQL('texture')
connection = kodi_sql('texture')
cursor = connection.cursor()
query = 'SELECT tbl_name FROM sqlite_master WHERE type=?'
cursor.execute(query, ("table", ))
rows = cursor.fetchall()
for row in rows:
tableName = row[0]
if(tableName != "version"):
cursor.execute("DELETE FROM %s" % tableName)
table_name = row[0]
if table_name != "version":
cursor.execute("DELETE FROM %s" % table_name)
connection.commit()
cursor.close()
@ -469,44 +472,36 @@ def reset():
line1=language(39603)):
# Delete the settings
addon = xbmcaddon.Addon()
addondir = tryDecode(xbmc.translatePath(addon.getAddonInfo('profile')))
dataPath = "%ssettings.xml" % addondir
log.info("Deleting: settings.xml")
remove(dataPath)
addondir = try_decode(xbmc.translatePath(addon.getAddonInfo('profile')))
LOG.info("Deleting: settings.xml")
remove("%ssettings.xml" % addondir)
reboot_kodi()
def profiling(sortby="cumulative"):
# Will print results to Kodi log
"""
Will print results to Kodi log. Must be enabled in the Python source code
"""
def decorator(func):
"""
decorator construct
"""
def wrapper(*args, **kwargs):
pr = Profile()
pr.enable()
"""
wrapper construct
"""
profile = Profile()
profile.enable()
result = func(*args, **kwargs)
pr.disable()
s = StringIO()
ps = Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats()
log.info(s.getvalue())
profile.disable()
string_io = StringIO()
stats = Stats(profile, stream=string_io).sort_stats(sortby)
stats.print_stats()
LOG.info(string_io.getvalue())
return result
return wrapper
return decorator
def convertdate(date):
try:
date = datetime.strptime(date, "%Y-%m-%dT%H:%M:%SZ")
except TypeError:
# TypeError: attribute of type 'NoneType' is not callable
# Known Kodi/python error
date = datetime(*(strptime(date, "%Y-%m-%dT%H:%M:%SZ")[0:6]))
return date
def compare_version(current, minimum):
"""
@ -515,38 +510,36 @@ def compare_version(current, minimum):
Input strings: e.g. "1.2.3"; always with Major, Minor and Patch!
"""
log.info("current DB: %s minimum DB: %s" % (current, minimum))
LOG.info("current DB: %s minimum DB: %s", current, minimum)
try:
currMajor, currMinor, currPatch = current.split(".")
curr_major, curr_minor, curr_patch = current.split(".")
except ValueError:
# there WAS no current DB, e.g. deleted.
return True
minMajor, minMinor, minPatch = minimum.split(".")
currMajor = int(currMajor)
currMinor = int(currMinor)
currPatch = int(currPatch)
minMajor = int(minMajor)
minMinor = int(minMinor)
minPatch = int(minPatch)
min_major, min_minor, min_patch = minimum.split(".")
curr_major = int(curr_major)
curr_minor = int(curr_minor)
curr_patch = int(curr_patch)
min_major = int(min_major)
min_minor = int(min_minor)
min_patch = int(min_patch)
if currMajor > minMajor:
if curr_major > min_major:
return True
elif currMajor < minMajor:
elif curr_major < min_major:
return False
if currMinor > minMinor:
if curr_minor > min_minor:
return True
elif currMinor < minMinor:
return False
if currPatch >= minPatch:
return True
else:
elif curr_minor < min_minor:
return False
return curr_patch >= min_patch
def normalize_nodes(text):
# For video nodes
"""
For video nodes
"""
text = text.replace(":", "")
text = text.replace("/", "-")
text = text.replace("\\", "-")
@ -561,13 +554,15 @@ def normalize_nodes(text):
# Remove dots from the last character as windows can not have directories
# with dots at the end
text = text.rstrip('.')
text = tryEncode(normalize('NFKD', unicode(text, 'utf-8')))
text = try_encode(normalize('NFKD', unicode(text, 'utf-8')))
return text
def normalize_string(text):
# For theme media, do not modify unless
# modified in TV Tunes
"""
For theme media, do not modify unless modified in TV Tunes
"""
text = text.replace(":", "")
text = text.replace("/", "-")
text = text.replace("\\", "-")
@ -580,7 +575,7 @@ def normalize_string(text):
# Remove dots from the last character as windows can not have directories
# with dots at the end
text = text.rstrip('.')
text = tryEncode(normalize('NFKD', unicode(text, 'utf-8')))
text = try_encode(normalize('NFKD', unicode(text, 'utf-8')))
return text
@ -595,8 +590,8 @@ def indent(elem, level=0):
elem.text = i + " "
if not elem.tail or not elem.tail.strip():
elem.tail = i
for elem in elem:
indent(elem, level+1)
for item in elem:
indent(item, level+1)
if not elem.tail or not elem.tail.strip():
elem.tail = i
else:
@ -604,30 +599,6 @@ def indent(elem, level=0):
elem.tail = i
def guisettingsXML():
"""
Returns special://userdata/guisettings.xml as an etree xml root element
"""
path = tryDecode(xbmc.translatePath("special://profile/"))
xmlpath = "%sguisettings.xml" % path
try:
xmlparse = etree.parse(xmlpath)
except IOError:
# Document is blank or missing
root = etree.Element('settings')
except etree.ParseError:
log.error('Error parsing %s' % xmlpath)
# "Kodi cannot parse {0}. PKC will not function correctly. Please visit
# {1} and correct your file!"
dialog('ok', language(29999), language(39716).format(
'guisettings.xml', 'http://kodi.wiki/view/userdata'))
return
else:
root = xmlparse.getroot()
return root
class XmlKodiSetting(object):
"""
Used to load a Kodi XML settings file from special://profile as an etree
@ -670,7 +641,7 @@ class XmlKodiSetting(object):
except IOError:
# Document is blank or missing
if self.force_create is False:
log.debug('%s does not seem to exist; not creating', self.path)
LOG.debug('%s does not seem to exist; not creating', self.path)
# This will abort __enter__
self.__exit__(IOError, None, None)
# Create topmost xml entry
@ -678,7 +649,7 @@ class XmlKodiSetting(object):
element=etree.Element(self.top_element))
self.write_xml = True
except etree.ParseError:
log.error('Error parsing %s', self.path)
LOG.error('Error parsing %s', self.path)
# "Kodi cannot parse {0}. PKC will not function correctly. Please
# visit {1} and correct your file!"
dialog('ok', language(29999), language(39716).format(
@ -775,7 +746,7 @@ class XmlKodiSetting(object):
elif old.attrib != attrib:
already_set = False
if already_set is True:
log.debug('Element has already been found')
LOG.debug('Element has already been found')
return old
# Need to set new setting, indeed
self.write_xml = True
@ -790,34 +761,35 @@ class XmlKodiSetting(object):
return element
def passwordsXML():
# To add network credentials
path = tryDecode(xbmc.translatePath("special://userdata/"))
def passwords_xml():
"""
To add network credentials to Kodi's password xml
"""
path = try_decode(xbmc.translatePath("special://userdata/"))
xmlpath = "%spasswords.xml" % path
dialog = xbmcgui.Dialog()
try:
xmlparse = etree.parse(xmlpath)
except IOError:
# Document is blank or missing
root = etree.Element('passwords')
skipFind = True
skip_find = True
except etree.ParseError:
log.error('Error parsing %s' % xmlpath)
LOG.error('Error parsing %s', xmlpath)
# "Kodi cannot parse {0}. PKC will not function correctly. Please visit
# {1} and correct your file!"
dialog.ok(language(29999), language(39716).format(
dialog('ok', language(29999), language(39716).format(
'passwords.xml', 'http://forum.kodi.tv/'))
return
else:
root = xmlparse.getroot()
skipFind = False
skip_find = False
credentials = settings('networkCreds')
if credentials:
# Present user with options
option = dialog.select(
"Modify/Remove network credentials", ["Modify", "Remove"])
option = dialog('select',
"Modify/Remove network credentials",
["Modify", "Remove"])
if option < 0:
# User cancelled dialog
@ -825,76 +797,86 @@ def passwordsXML():
elif option == 1:
# User selected remove
success = False
for paths in root.getiterator('passwords'):
for path in paths:
if path.find('.//from').text == "smb://%s/" % credentials:
paths.remove(path)
log.info("Successfully removed credentials for: %s"
% credentials)
LOG.info("Successfully removed credentials for: %s",
credentials)
etree.ElementTree(root).write(xmlpath,
encoding="UTF-8")
break
else:
log.error("Failed to find saved server: %s in passwords.xml"
% credentials)
success = True
if not success:
LOG.error("Failed to find saved server: %s in passwords.xml",
credentials)
dialog('notification',
heading='{plex}',
message="%s not found" % credentials,
icon='{warning}',
sound=False)
return
settings('networkCreds', value="")
xbmcgui.Dialog().notification(
heading='PlexKodiConnect',
dialog('notification',
heading='{plex}',
message="%s removed from passwords.xml" % credentials,
icon="special://home/addons/plugin.video.plexkodiconnect/icon.png",
time=1000,
icon='{plex}',
sound=False)
return
elif option == 0:
# User selected to modify
server = dialog.input("Modify the computer name or ip address", credentials)
server = dialog('input',
"Modify the computer name or ip address",
credentials)
if not server:
return
else:
# No credentials added
dialog.ok(
heading="Network credentials",
line1= (
"Input the server name or IP address as indicated in your plex library paths. "
'For example, the server name: \\\\SERVER-PC\\path\\ or smb://SERVER-PC/path is "SERVER-PC".'))
server = dialog.input("Enter the server name or IP address")
dialog('ok',
"Network credentials",
'Input the server name or IP address as indicated in your plex '
'library paths. For example, the server name: '
'\\\\SERVER-PC\\path\\ or smb://SERVER-PC/path is SERVER-PC')
server = dialog('input', "Enter the server name or IP address")
if not server:
return
server = quote_plus(server)
# Network username
user = dialog.input("Enter the network username")
user = dialog('input', "Enter the network username")
if not user:
return
user = quote_plus(user)
# Network password
password = dialog.input("Enter the network password",
password = dialog('input',
"Enter the network password",
'', # Default input
xbmcgui.INPUT_ALPHANUM,
xbmcgui.ALPHANUM_HIDE_INPUT)
type='{alphanum}',
option='{hide}')
# Need to url-encode the password
password = quote_plus(password)
# Add elements. Annoying etree bug where findall hangs forever
if skipFind is False:
skipFind = True
if skip_find is False:
skip_find = True
for path in root.findall('.//path'):
if path.find('.//from').text.lower() == "smb://%s/" % server.lower():
# Found the server, rewrite credentials
path.find('.//to').text = "smb://%s:%s@%s/" % (user, password, server)
skipFind = False
path.find('.//to').text = ("smb://%s:%s@%s/"
% (user, password, server))
skip_find = False
break
if skipFind:
if skip_find:
# Server not found, add it.
path = etree.SubElement(root, 'path')
etree.SubElement(path, 'from', attrib={'pathversion': "1"}).text = "smb://%s/" % server
etree.SubElement(path, 'from', attrib={'pathversion': "1"}).text = \
"smb://%s/" % server
topath = "smb://%s:%s@%s/" % (user, password, server)
etree.SubElement(path, 'to', attrib={'pathversion': "1"}).text = topath
# Add credentials
settings('networkCreds', value="%s" % server)
log.info("Added server: %s to passwords.xml" % server)
LOG.info("Added server: %s to passwords.xml", server)
# Prettify and write to file
try:
indent(root)
@ -902,19 +884,12 @@ def passwordsXML():
pass
etree.ElementTree(root).write(xmlpath, encoding="UTF-8")
# dialog.notification(
# heading="PlexKodiConnect",
# message="Added to passwords.xml",
# icon="special://home/addons/plugin.video.plexkodiconnect/icon.png",
# time=5000,
# sound=False)
def playlistXSP(mediatype, tagname, viewid, viewtype="", delete=False):
def playlist_xsp(mediatype, tagname, viewid, viewtype="", delete=False):
"""
Feed with tagname as unicode
"""
path = tryDecode(xbmc.translatePath("special://profile/playlists/video/"))
path = try_decode(xbmc.translatePath("special://profile/playlists/video/"))
if viewtype == "mixed":
plname = "%s - %s" % (tagname, mediatype)
xsppath = "%sPlex %s - %s.xsp" % (path, viewid, mediatype)
@ -923,16 +898,16 @@ def playlistXSP(mediatype, tagname, viewid, viewtype="", delete=False):
xsppath = "%sPlex %s.xsp" % (path, viewid)
# Create the playlist directory
if not exists(tryEncode(path)):
log.info("Creating directory: %s" % path)
if not exists(try_encode(path)):
LOG.info("Creating directory: %s", path)
makedirs(path)
# Only add the playlist if it doesn't already exists
if exists(tryEncode(xsppath)):
log.info('Path %s does exist' % xsppath)
if exists(try_encode(xsppath)):
LOG.info('Path %s does exist', xsppath)
if delete:
remove(xsppath)
log.info("Successfully removed playlist: %s." % tagname)
LOG.info("Successfully removed playlist: %s.", tagname)
return
# Using write process since there's no guarantee the xml declaration works
@ -942,9 +917,9 @@ def playlistXSP(mediatype, tagname, viewid, viewtype="", delete=False):
'movie': 'movies',
'show': 'tvshows'
}
log.info("Writing playlist file to: %s" % xsppath)
with open(xsppath, 'wb') as f:
f.write(tryEncode(
LOG.info("Writing playlist file to: %s", xsppath)
with open(xsppath, 'wb') as filer:
filer.write(try_encode(
'<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n'
'<smartplaylist type="%s">\n\t'
'<name>Plex %s</name>\n\t'
@ -954,20 +929,24 @@ def playlistXSP(mediatype, tagname, viewid, viewtype="", delete=False):
'</rule>\n'
'</smartplaylist>\n'
% (itemtypes.get(mediatype, mediatype), plname, tagname)))
log.info("Successfully added playlist: %s" % tagname)
LOG.info("Successfully added playlist: %s", tagname)
def deletePlaylists():
# Clean up the playlists
path = tryDecode(xbmc.translatePath("special://profile/playlists/video/"))
def delete_playlists():
"""
Clean up the playlists
"""
path = try_decode(xbmc.translatePath("special://profile/playlists/video/"))
for root, _, files in walk(path):
for file in files:
if file.startswith('Plex'):
remove(join(root, file))
def deleteNodes():
# Clean up video nodes
path = tryDecode(xbmc.translatePath("special://profile/library/video/"))
def delete_nodes():
"""
Clean up video nodes
"""
path = try_decode(xbmc.translatePath("special://profile/library/video/"))
for root, dirs, _ in walk(path):
for directory in dirs:
if directory.startswith('Plex-'):
@ -993,9 +972,9 @@ def CatchExceptions(warnuser=False):
try:
return func(*args, **kwargs)
except Exception as e:
log.error('%s has crashed. Error: %s' % (func.__name__, e))
LOG.error('%s has crashed. Error: %s', func.__name__, e)
import traceback
log.error("Traceback:\n%s" % traceback.format_exc())
LOG.error("Traceback:\n%s", traceback.format_exc())
if warnuser:
window('plex_scancrashed', value='true')
return
@ -1012,8 +991,8 @@ def LogTime(func):
starttotal = datetime.now()
result = func(*args, **kwargs)
elapsedtotal = datetime.now() - starttotal
log.info('It took %s to run the function %s'
% (elapsedtotal, func.__name__))
LOG.info('It took %s to run the function %s',
elapsedtotal, func.__name__)
return result
return wrapper
@ -1117,43 +1096,3 @@ class Lock_Function(object):
result = func(*args, **kwargs)
return result
return wrapper
###############################################################################
# UNUSED METHODS
# def changePlayState(itemType, kodiId, playCount, lastplayed):
# """
# YET UNUSED
# kodiId: int or str
# playCount: int or str
# lastplayed: str or int unix timestamp
# """
# lastplayed = DateToKodi(lastplayed)
# kodiId = int(kodiId)
# playCount = int(playCount)
# method = {
# 'movie': ' VideoLibrary.SetMovieDetails',
# 'episode': 'VideoLibrary.SetEpisodeDetails',
# 'musicvideo': ' VideoLibrary.SetMusicVideoDetails', # TODO
# 'show': 'VideoLibrary.SetTVShowDetails', # TODO
# '': 'AudioLibrary.SetAlbumDetails', # TODO
# '': 'AudioLibrary.SetArtistDetails', # TODO
# 'track': 'AudioLibrary.SetSongDetails'
# }
# params = {
# 'movie': {
# 'movieid': kodiId,
# 'playcount': playCount,
# 'lastplayed': lastplayed
# },
# 'episode': {
# 'episodeid': kodiId,
# 'playcount': playCount,
# 'lastplayed': lastplayed
# }
# }
# result = jsonrpc(method[itemType]).execute(params[itemType])
# log.debug("JSON result was: %s" % result)

View file

@ -6,7 +6,7 @@ from xbmcaddon import Addon
# For any file operations with KODI function, use encoded strings!
def tryDecode(string, encoding='utf-8'):
def try_decode(string, encoding='utf-8'):
"""
Will try to decode string (encoded) using encoding. This possibly
fails with e.g. Android TV's Python, which does not accept arguments for
@ -37,7 +37,7 @@ ADDON_VERSION = _ADDON.getAddonInfo('version')
KODILANGUAGE = xbmc.getLanguage(xbmc.ISO_639_1)
KODIVERSION = int(xbmc.getInfoLabel("System.BuildVersion")[:2])
KODILONGVERSION = xbmc.getInfoLabel('System.BuildVersion')
KODI_PROFILE = tryDecode(xbmc.translatePath("special://profile"))
KODI_PROFILE = try_decode(xbmc.translatePath("special://profile"))
if xbmc.getCondVisibility('system.platform.osx'):
PLATFORM = "MacOSX"
@ -56,7 +56,7 @@ elif xbmc.getCondVisibility('system.platform.android'):
else:
PLATFORM = "Unknown"
DEVICENAME = tryDecode(_ADDON.getSetting('deviceName'))
DEVICENAME = try_decode(_ADDON.getSetting('deviceName'))
DEVICENAME = DEVICENAME.replace(":", "")
DEVICENAME = DEVICENAME.replace("/", "-")
DEVICENAME = DEVICENAME.replace("\\", "-")
@ -86,7 +86,7 @@ _DB_VIDEO_VERSION = {
17: 107, # Krypton
18: 108 # Leia
}
DB_VIDEO_PATH = tryDecode(xbmc.translatePath(
DB_VIDEO_PATH = try_decode(xbmc.translatePath(
"special://database/MyVideos%s.db" % _DB_VIDEO_VERSION[KODIVERSION]))
_DB_MUSIC_VERSION = {
@ -97,7 +97,7 @@ _DB_MUSIC_VERSION = {
17: 60, # Krypton
18: 62 # Leia
}
DB_MUSIC_PATH = tryDecode(xbmc.translatePath(
DB_MUSIC_PATH = try_decode(xbmc.translatePath(
"special://database/MyMusic%s.db" % _DB_MUSIC_VERSION[KODIVERSION]))
_DB_TEXTURE_VERSION = {
@ -108,12 +108,12 @@ _DB_TEXTURE_VERSION = {
17: 13, # Krypton
18: 13 # Leia
}
DB_TEXTURE_PATH = tryDecode(xbmc.translatePath(
DB_TEXTURE_PATH = try_decode(xbmc.translatePath(
"special://database/Textures%s.db" % _DB_TEXTURE_VERSION[KODIVERSION]))
DB_PLEX_PATH = tryDecode(xbmc.translatePath("special://database/plex.db"))
DB_PLEX_PATH = try_decode(xbmc.translatePath("special://database/plex.db"))
EXTERNAL_SUBTITLE_TEMP_PATH = tryDecode(xbmc.translatePath(
EXTERNAL_SUBTITLE_TEMP_PATH = try_decode(xbmc.translatePath(
"special://profile/addon_data/%s/temp/" % ADDON_ID))

View file

@ -8,8 +8,8 @@ from os import makedirs
import xbmc
from xbmcvfs import exists
from utils import window, settings, language as lang, tryEncode, indent, \
normalize_nodes, exists_dir, tryDecode
from utils import window, settings, language as lang, try_encode, indent, \
normalize_nodes, exists_dir, try_decode
import variables as v
###############################################################################
@ -62,9 +62,9 @@ class VideoNodes(object):
dirname = viewid
# Returns strings
path = tryDecode(xbmc.translatePath(
path = try_decode(xbmc.translatePath(
"special://profile/library/video/"))
nodepath = tryDecode(xbmc.translatePath(
nodepath = try_decode(xbmc.translatePath(
"special://profile/library/video/Plex-%s/" % dirname))
if delete:
@ -77,9 +77,9 @@ class VideoNodes(object):
# Verify the video directory
if not exists_dir(path):
copytree(
src=tryDecode(xbmc.translatePath(
src=try_decode(xbmc.translatePath(
"special://xbmc/system/library/video")),
dst=tryDecode(xbmc.translatePath(
dst=try_decode(xbmc.translatePath(
"special://profile/library/video")))
# Create the node directory
@ -292,7 +292,7 @@ class VideoNodes(object):
# To do: add our photos nodes to kodi picture sources somehow
continue
if exists(tryEncode(nodeXML)):
if exists(try_encode(nodeXML)):
# Don't recreate xml if already exists
continue
@ -378,9 +378,9 @@ class VideoNodes(object):
etree.ElementTree(root).write(nodeXML, encoding="UTF-8")
def singleNode(self, indexnumber, tagname, mediatype, itemtype):
tagname = tryEncode(tagname)
cleantagname = tryDecode(normalize_nodes(tagname))
nodepath = tryDecode(xbmc.translatePath(
tagname = try_encode(tagname)
cleantagname = try_decode(normalize_nodes(tagname))
nodepath = try_decode(xbmc.translatePath(
"special://profile/library/video/"))
nodeXML = "%splex_%s.xml" % (nodepath, cleantagname)
path = "library://video/plex_%s.xml" % cleantagname
@ -394,9 +394,9 @@ class VideoNodes(object):
if not exists_dir(nodepath):
# We need to copy over the default items
copytree(
src=tryDecode(xbmc.translatePath(
src=try_decode(xbmc.translatePath(
"special://xbmc/system/library/video")),
dst=tryDecode(xbmc.translatePath(
dst=try_decode(xbmc.translatePath(
"special://profile/library/video")))
labels = {
@ -411,7 +411,7 @@ class VideoNodes(object):
window('%s.content' % embynode, value=path)
window('%s.type' % embynode, value=itemtype)
if exists(tryEncode(nodeXML)):
if exists(try_encode(nodeXML)):
# Don't recreate xml if already exists
return

View file

@ -292,7 +292,7 @@ class ABNF(object):
opcode: operation code. please see OPCODE_XXX.
"""
if opcode == ABNF.OPCODE_TEXT and isinstance(data, unicode):
data = utils.tryEncode(data)
data = utils.try_encode(data)
# mask must be set if send data from client
return ABNF(1, 0, 0, 0, opcode, 1, data)