jellyfin-kodi/resources/lib/Utils.py

285 lines
10 KiB
Python
Raw Normal View History

2015-03-13 21:24:59 +00:00
#################################################################################################
# utils
#################################################################################################
import xbmc
import xbmcgui
import xbmcaddon
import xbmcvfs
import json
import os
import cProfile
import pstats
import time
2015-03-13 21:24:59 +00:00
import inspect
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
from xml.etree import ElementTree
from xml.dom import minidom
import xml.etree.cElementTree as ET
from API import API
from PlayUtils import PlayUtils
from DownloadUtils import DownloadUtils
downloadUtils = DownloadUtils()
2015-03-25 17:37:21 +00:00
addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
language = addonSettings.getLocalizedString
2015-03-13 21:24:59 +00:00
def logMsg(title, msg, level = 1):
logLevel = int(addonSettings.getSetting("logLevel"))
2015-03-13 21:24:59 +00:00
if(logLevel >= level):
if(logLevel == 2): # inspect.stack() is expensive
2015-03-13 21:24:59 +00:00
try:
xbmc.log(title + " -> " + inspect.stack()[1][3] + " : " + str(msg))
except UnicodeEncodeError:
xbmc.log(title + " -> " + inspect.stack()[1][3] + " : " + str(msg.encode('utf-8')))
else:
try:
xbmc.log(title + " -> " + str(msg))
except UnicodeEncodeError:
xbmc.log(title + " -> " + str(msg.encode('utf-8')))
2015-03-16 21:31:32 +00:00
def convertEncoding(data):
#nasty hack to make sure we have a unicode string
try:
return data.decode('utf-8')
except:
return data
2015-03-13 21:24:59 +00:00
def checkKodiSources():
2015-03-25 17:37:21 +00:00
addon = xbmcaddon.Addon(id='plugin.video.emby')
2015-03-13 21:24:59 +00:00
addondir = xbmc.translatePath( addon.getAddonInfo('profile') )
dataPath = os.path.join(addondir,"library")
2015-03-14 18:37:52 +00:00
movieLibrary = os.path.join(dataPath,'movies')
tvLibrary = os.path.join(dataPath,'tvshows')
2015-03-21 13:31:30 +00:00
musicvideoLibrary = os.path.join(dataPath,'musicvideos')
2015-03-13 21:24:59 +00:00
rebootRequired = False
2015-03-14 20:48:09 +00:00
if not xbmcvfs.exists(dataPath + os.sep):
2015-03-13 21:24:59 +00:00
xbmcvfs.mkdir(dataPath)
2015-03-14 20:48:09 +00:00
if not xbmcvfs.exists(movieLibrary + os.sep):
xbmcvfs.mkdir(movieLibrary)
rebootRequired = True
addKodiSource("mediabrowser_movies",movieLibrary,"movies")
2015-03-14 20:48:09 +00:00
if not xbmcvfs.exists(tvLibrary + os.sep):
xbmcvfs.mkdir(tvLibrary)
rebootRequired = True
addKodiSource("mediabrowser_tvshows",tvLibrary,"tvshows")
2015-03-21 13:31:30 +00:00
if not xbmcvfs.exists(musicvideoLibrary + os.sep):
xbmcvfs.mkdir(musicvideoLibrary)
rebootRequired = True
addKodiSource("mediabrowser_musicvideos",musicvideoLibrary,"musicvideos")
rebootRequired = KodiAdvancedSettingsCheck()
2015-03-13 21:24:59 +00:00
if rebootRequired:
ret = xbmcgui.Dialog().yesno(heading="Emby Sync service", line1="A restart of Kodi is needed to apply changes.", line2="Synchronisation will not start before the restart.", line3="Do you want to restart now?")
2015-03-13 21:24:59 +00:00
if ret:
xbmc.executebuiltin("RestartApp")
else:
return False
return True
def KodiSQL():
if xbmc.getinfolabel("System.BuildVersion").startswith("13"):
#gotham
dbVersion = "78"
if xbmc.getinfolabel("System.BuildVersion").startswith("15"):
#isengard
dbVersion = "91"
else:
#helix
dbVersion = "90"
#find out if we should use MySQL
useMySQL = False
settingsFile = xbmc.translatePath( "special://profile/advancedsettings.xml" )
if xbmcvfs.exists(settingsFile):
tree = ET.ElementTree(file=settingsFile)
root = tree.getroot()
video = root.find("videolibrary")
if video != None:
mysql = video.find("type")
if mysql != None:
useMySQL = True
db_port = video.find("port").text
db_host = video.find("host").text
db_user = video.find("user").text
db_pass = video.find("pass").text
if video.find("name") != None:
db_name = video.find("name").text
else:
db_name = "MyVideos"
SubElement(video, "importwatchedstate").text = "true"
if video.find("importresumepoint") == None:
writeNeeded = True
SubElement(video, "importresumepoint").text = "true"
if useMySQL:
import local.mysql.connector as database
connection = database.connect(dbPath)
connection = database.connect(db = db_name, user = db_user, passwd = db_pass, host = db_host, port = db_port)
connection.set_charset('utf8')
connection.set_unicode(True)
else:
import sqlite3 as database
dbPath = xbmc.translatePath("special://userdata/Database/MyVideos" + dbVersion + ".db")
connection = database.connect(dbPath)
return connection
2015-03-13 21:24:59 +00:00
def addKodiSource(name, path, type):
#add new source to database, common way is to add it directly to the Kodi DB. Fallback to adding it to the sources.xml
#return boolean wether a manual reboot is required.
#todo: Do feature request with Kodi team to get support for adding a source by the json API
error = False
if xbmcvfs.exists(dbPath):
try:
connection = KodiSQL()
cursor = connection.cursor( )
cursor.execute("select coalesce(max(idPath),0) as pathId from path")
pathId = cursor.fetchone()[0]
pathId = pathId + 1
pathsql="insert into path(idPath, strPath, strContent, strScraper, strHash, scanRecursive) values(?, ?, ?, ?, ?, ?)"
cursor.execute(pathsql, (pathId,path + os.sep,type,"metadata.local",None,2147483647))
connection.commit()
cursor.close()
except:
error = True
else:
error = True
# add it to sources.xml
sourcesFile = xbmc.translatePath( "special://profile/sources.xml" )
2015-03-21 13:31:30 +00:00
# add an empty sources file to work with
if xbmcvfs.exists(sourcesFile) == False:
sources = Element("sources")
video = SubElement(sources, "video")
ET.ElementTree(sources).write(sourcesFile)
if xbmcvfs.exists(sourcesFile):
tree = ET.ElementTree(file=sourcesFile)
root = tree.getroot()
videosources = root.find("video")
#remove any existing entries for this path
allsources = videosources.findall("source")
if allsources != None:
for source in allsources:
if source.find("name").text == name:
videosources.remove(source)
# add the new source
source = SubElement(videosources,'source')
SubElement(source, "name").text = name
SubElement(source, "path").text = path
tree.write(sourcesFile)
def KodiAdvancedSettingsCheck():
#setting that kodi should import watched state and resume points from the nfo files
settingsFile = xbmc.translatePath( "special://profile/advancedsettings.xml" )
# add an empty sources file to work with
if xbmcvfs.exists(settingsFile) == False:
sources = Element("advancedsettings")
video = SubElement(sources, "videolibrary")
ET.ElementTree(sources).write(settingsFile)
writeNeeded = False
if xbmcvfs.exists(settingsFile):
tree = ET.ElementTree(file=settingsFile)
root = tree.getroot()
video = root.find("videolibrary")
if video == None:
video = SubElement(sources, "videolibrary")
# add the settings
if video.find("importwatchedstate") == None:
writeNeeded = True
SubElement(video, "importwatchedstate").text = "true"
if video.find("importresumepoint") == None:
writeNeeded = True
SubElement(video, "importresumepoint").text = "true"
if writeNeeded:
tree.write(settingsFile)
return True
else:
return False
2015-03-13 21:24:59 +00:00
def checkAuthentication():
#check authentication
if addonSettings.getSetting('username') != "" and addonSettings.getSetting('ipaddress') != "":
try:
downloadUtils.authenticate()
except Exception, e:
logMsg("MB3 Syncer authentication failed",e)
pass
def prettifyXml(elem):
rough_string = etree.tostring(elem, "utf-8")
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent="\t")
def get_params( paramstring ):
xbmc.log("Parameter string: " + paramstring)
param={}
if len(paramstring)>=2:
params=paramstring
if params[0] == "?":
cleanedparams=params[1:]
else:
cleanedparams=params
if (params[len(params)-1]=='/'):
params=params[0:len(params)-2]
pairsofparams=cleanedparams.split('&')
for i in range(len(pairsofparams)):
splitparams={}
splitparams=pairsofparams[i].split('=')
if (len(splitparams))==2:
param[splitparams[0]]=splitparams[1]
elif (len(splitparams))==3:
param[splitparams[0]]=splitparams[1]+"="+splitparams[2]
return param
def startProfiling():
pr = cProfile.Profile()
pr.enable()
return pr
def stopProfiling(pr, profileName):
pr.disable()
ps = pstats.Stats(pr)
2015-03-25 17:37:21 +00:00
addondir = xbmc.translatePath(xbmcaddon.Addon(id='plugin.video.emby').getAddonInfo('profile'))
fileTimeStamp = time.strftime("%Y-%m-%d %H-%M-%S")
tabFileNamepath = os.path.join(addondir, "profiles")
tabFileName = os.path.join(addondir, "profiles" , profileName + "_profile_(" + fileTimeStamp + ").tab")
if not xbmcvfs.exists(tabFileNamepath):
xbmcvfs.mkdir(tabFileNamepath)
f = open(tabFileName, 'wb')
f.write("NumbCalls\tTotalTime\tCumulativeTime\tFunctionName\tFileName\r\n")
for (key, value) in ps.stats.items():
(filename, count, func_name) = key
(ccalls, ncalls, total_time, cumulative_time, callers) = value
try:
f.write(str(ncalls) + "\t" + "{:10.4f}".format(total_time) + "\t" + "{:10.4f}".format(cumulative_time) + "\t" + func_name + "\t" + filename + "\r\n")
except ValueError:
f.write(str(ncalls) + "\t" + "{0}".format(total_time) + "\t" + "{0}".format(cumulative_time) + "\t" + func_name + "\t" + filename + "\r\n")
f.close()
2015-03-17 18:41:26 +00:00
2015-03-13 21:24:59 +00:00