2016-11-04 01:36:05 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
#################################################################################################
|
|
|
|
|
2016-11-04 04:45:37 +00:00
|
|
|
import logging
|
2016-11-04 01:36:05 +00:00
|
|
|
import sqlite3
|
2016-11-05 00:15:28 +00:00
|
|
|
import sys
|
2016-11-05 02:19:57 +00:00
|
|
|
import traceback
|
2016-11-04 01:36:05 +00:00
|
|
|
|
|
|
|
import xbmc
|
2016-11-05 00:15:28 +00:00
|
|
|
import xbmcgui
|
|
|
|
import xbmcplugin
|
|
|
|
import xbmcvfs
|
2016-11-04 01:36:05 +00:00
|
|
|
|
2016-11-05 21:39:01 +00:00
|
|
|
from views import Playlist, VideoNodes
|
|
|
|
from utils import window, should_stop, settings, language
|
2016-11-04 17:13:07 +00:00
|
|
|
|
2016-11-04 01:36:05 +00:00
|
|
|
#################################################################################################
|
|
|
|
|
2016-11-04 04:45:37 +00:00
|
|
|
log = logging.getLogger("EMBY."+__name__)
|
2016-11-04 01:36:05 +00:00
|
|
|
KODI = xbmc.getInfoLabel('System.BuildVersion')[:2]
|
|
|
|
|
|
|
|
#################################################################################################
|
|
|
|
|
|
|
|
def video_database():
|
|
|
|
db_version = {
|
|
|
|
|
|
|
|
'13': 78, # Gotham
|
|
|
|
'14': 90, # Helix
|
|
|
|
'15': 93, # Isengard
|
|
|
|
'16': 99, # Jarvis
|
2016-11-04 01:38:01 +00:00
|
|
|
'17': 107 # Krypton
|
2016-11-04 01:36:05 +00:00
|
|
|
}
|
2016-11-07 14:36:32 +00:00
|
|
|
return xbmc.translatePath("special://database/MyVideos%s.db"
|
|
|
|
% db_version.get(KODI, "")).decode('utf-8')
|
2016-11-04 01:36:05 +00:00
|
|
|
|
|
|
|
def music_database():
|
|
|
|
db_version = {
|
|
|
|
|
|
|
|
'13': 46, # Gotham
|
|
|
|
'14': 48, # Helix
|
|
|
|
'15': 52, # Isengard
|
|
|
|
'16': 56, # Jarvis
|
|
|
|
'17': 60 # Krypton
|
|
|
|
}
|
2016-11-07 14:36:32 +00:00
|
|
|
return xbmc.translatePath("special://database/MyMusic%s.db"
|
|
|
|
% db_version.get(KODI, "")).decode('utf-8')
|
2016-11-04 01:36:05 +00:00
|
|
|
|
2016-11-04 17:13:07 +00:00
|
|
|
def texture_database():
|
|
|
|
return xbmc.translatePath("special://database/Textures13.db").decode('utf-8')
|
|
|
|
|
|
|
|
def emby_database():
|
|
|
|
return xbmc.translatePath("special://database/emby.db").decode('utf-8')
|
|
|
|
|
|
|
|
def kodi_commit():
|
|
|
|
# verification for the Kodi video scan
|
|
|
|
kodi_scan = window('emby_kodiScan') == "true"
|
|
|
|
count = 0
|
|
|
|
|
|
|
|
while kodi_scan:
|
|
|
|
log.info("kodi scan is running, waiting...")
|
|
|
|
|
|
|
|
if count == 10:
|
|
|
|
log.info("flag still active, but will try to commit")
|
|
|
|
window('emby_kodiScan', clear=True)
|
|
|
|
|
|
|
|
elif should_stop() or xbmc.Monitor().waitForAbort(1):
|
|
|
|
log.info("commit unsuccessful. sync terminating")
|
|
|
|
return False
|
|
|
|
|
|
|
|
kodi_scan = window('emby_kodiScan') == "true"
|
|
|
|
count += 1
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
2016-11-04 01:36:05 +00:00
|
|
|
|
|
|
|
class DatabaseConn(object):
|
2016-11-04 11:39:49 +00:00
|
|
|
# To be called as context manager - i.e. with DatabaseConn() as conn: #dostuff
|
2016-11-04 01:36:05 +00:00
|
|
|
|
2016-11-04 22:19:28 +00:00
|
|
|
def __init__(self, database_file="video", commit_on_close=True, timeout=120):
|
2016-11-04 01:36:05 +00:00
|
|
|
"""
|
2016-11-04 06:28:02 +00:00
|
|
|
database_file can be custom: emby, texture, music, video, :memory: or path to the file
|
2016-11-04 01:36:05 +00:00
|
|
|
commit_mode set to None to autocommit (isolation_level). See python documentation.
|
|
|
|
"""
|
|
|
|
self.db_file = database_file
|
2016-11-04 22:19:28 +00:00
|
|
|
self.commit_on_close = commit_on_close
|
2016-11-04 06:28:02 +00:00
|
|
|
self.timeout = timeout
|
2016-11-04 01:36:05 +00:00
|
|
|
|
|
|
|
def __enter__(self):
|
|
|
|
# Open the connection
|
|
|
|
self.path = self._SQL(self.db_file)
|
2016-11-05 02:19:57 +00:00
|
|
|
#traceback.print_stack()
|
2016-11-04 22:19:28 +00:00
|
|
|
|
|
|
|
if settings('dblock') == "true":
|
|
|
|
self.conn = sqlite3.connect(self.path, isolation_level=None, timeout=self.timeout)
|
|
|
|
else:
|
|
|
|
self.conn = sqlite3.connect(self.path, timeout=self.timeout)
|
2016-11-06 09:34:27 +00:00
|
|
|
|
|
|
|
log.info("opened: %s - %s", self.path, id(self.conn))
|
2016-11-07 23:32:40 +00:00
|
|
|
self.cursor = self.conn.cursor()
|
2016-11-12 23:39:14 +00:00
|
|
|
|
|
|
|
if self.db_file == "emby":
|
|
|
|
verify_emby_database(self.cursor)
|
|
|
|
self.conn.commit()
|
|
|
|
|
2016-11-08 13:10:21 +00:00
|
|
|
return self.cursor
|
2016-11-04 01:36:05 +00:00
|
|
|
|
|
|
|
def _SQL(self, media_type):
|
|
|
|
|
2016-11-04 17:13:07 +00:00
|
|
|
databases = {
|
|
|
|
'emby': emby_database,
|
|
|
|
'texture': texture_database,
|
|
|
|
'music': music_database,
|
|
|
|
'video': video_database
|
|
|
|
}
|
|
|
|
return databases[media_type]() if media_type in databases else self.db_file
|
2016-11-04 01:36:05 +00:00
|
|
|
|
|
|
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
|
|
# Close the connection
|
2016-11-04 11:39:49 +00:00
|
|
|
changes = self.conn.total_changes
|
|
|
|
|
2016-11-04 01:36:05 +00:00
|
|
|
if exc_type is not None:
|
|
|
|
# Errors were raised in the with statement
|
2016-11-04 17:13:07 +00:00
|
|
|
log.error("Type: %s Value: %s", exc_type, exc_val)
|
2016-11-04 01:36:05 +00:00
|
|
|
|
2016-11-04 22:19:28 +00:00
|
|
|
if self.commit_on_close == True and changes:
|
2016-11-04 11:39:49 +00:00
|
|
|
log.info("number of rows updated: %s", changes)
|
2016-11-05 00:15:28 +00:00
|
|
|
if self.db_file == "video":
|
|
|
|
kodi_commit()
|
2016-11-04 22:19:28 +00:00
|
|
|
self.conn.commit()
|
2016-11-05 00:31:40 +00:00
|
|
|
log.info("commit: %s", self.path)
|
2016-11-04 01:36:05 +00:00
|
|
|
|
2016-11-06 09:34:27 +00:00
|
|
|
log.info("closing: %s - %s", self.path, id(self.conn))
|
2016-11-07 23:32:40 +00:00
|
|
|
self.cursor.close()
|
2016-11-04 01:36:05 +00:00
|
|
|
self.conn.close()
|
2016-11-05 00:15:28 +00:00
|
|
|
|
2016-11-12 23:39:14 +00:00
|
|
|
|
|
|
|
def verify_emby_database(cursor):
|
|
|
|
# Create the tables for the emby database
|
|
|
|
# emby, view, version
|
|
|
|
|
|
|
|
if window('emby_db_checked') != "true":
|
|
|
|
log.info("Verifying emby DB")
|
|
|
|
cursor.execute(
|
|
|
|
"""CREATE TABLE IF NOT EXISTS emby(
|
|
|
|
emby_id TEXT UNIQUE, media_folder TEXT, emby_type TEXT, media_type TEXT,
|
|
|
|
kodi_id INTEGER, kodi_fileid INTEGER, kodi_pathid INTEGER, parent_id INTEGER,
|
|
|
|
checksum INTEGER)""")
|
|
|
|
cursor.execute(
|
|
|
|
"""CREATE TABLE IF NOT EXISTS view(
|
|
|
|
view_id TEXT UNIQUE, view_name TEXT, media_type TEXT, kodi_tagid INTEGER)""")
|
|
|
|
cursor.execute("CREATE TABLE IF NOT EXISTS version(idVersion TEXT)")
|
|
|
|
window('emby_db_checked', value="true")
|
|
|
|
|
2016-11-05 00:15:28 +00:00
|
|
|
def db_reset():
|
|
|
|
|
|
|
|
dialog = xbmcgui.Dialog()
|
|
|
|
|
|
|
|
if not dialog.yesno(language(29999), language(33074)):
|
|
|
|
return
|
|
|
|
|
|
|
|
# first stop any db sync
|
|
|
|
window('emby_online', value="reset")
|
|
|
|
window('emby_shouldStop', value="true")
|
|
|
|
count = 10
|
|
|
|
while window('emby_dbScan') == "true":
|
|
|
|
log.info("Sync is running, will retry: %s..." % count)
|
|
|
|
count -= 1
|
|
|
|
if count == 0:
|
|
|
|
dialog.ok(language(29999), language(33085))
|
|
|
|
return
|
|
|
|
xbmc.sleep(1000)
|
|
|
|
|
|
|
|
# Clean up the playlists
|
2016-11-05 21:39:01 +00:00
|
|
|
Playlist().delete_playlists()
|
2016-11-05 00:15:28 +00:00
|
|
|
|
|
|
|
# Clean up the video nodes
|
2016-11-05 21:39:01 +00:00
|
|
|
VideoNodes().deleteNodes()
|
2016-11-05 00:15:28 +00:00
|
|
|
|
|
|
|
# Wipe the kodi databases
|
|
|
|
log.warn("Resetting the Kodi video database.")
|
2016-11-07 23:32:40 +00:00
|
|
|
with DatabaseConn('video') as cursor:
|
|
|
|
cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
|
|
|
|
rows = cursor.fetchall()
|
|
|
|
for row in rows:
|
|
|
|
tablename = row[0]
|
|
|
|
if tablename != "version":
|
|
|
|
cursor.execute("DELETE FROM " + tablename)
|
2016-11-05 00:15:28 +00:00
|
|
|
|
|
|
|
if settings('enableMusic') == "true":
|
|
|
|
log.warn("Resetting the Kodi music database.")
|
2016-11-07 23:32:40 +00:00
|
|
|
with DatabaseConn('music') as cursor:
|
2016-11-05 00:15:28 +00:00
|
|
|
cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
|
|
|
|
rows = cursor.fetchall()
|
|
|
|
for row in rows:
|
|
|
|
tablename = row[0]
|
|
|
|
if tablename != "version":
|
|
|
|
cursor.execute("DELETE FROM " + tablename)
|
2016-11-07 23:32:40 +00:00
|
|
|
|
|
|
|
# Wipe the emby database
|
|
|
|
log.warn("Resetting the Emby database.")
|
|
|
|
with DatabaseConn('emby') as cursor:
|
|
|
|
cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
|
|
|
|
rows = cursor.fetchall()
|
|
|
|
for row in rows:
|
|
|
|
tablename = row[0]
|
|
|
|
if tablename != "version":
|
|
|
|
cursor.execute("DELETE FROM " + tablename)
|
|
|
|
cursor.execute('DROP table IF EXISTS emby')
|
|
|
|
cursor.execute('DROP table IF EXISTS view')
|
|
|
|
cursor.execute("DROP table IF EXISTS version")
|
2016-11-05 00:15:28 +00:00
|
|
|
|
|
|
|
# Offer to wipe cached thumbnails
|
|
|
|
if dialog.yesno(language(29999), language(33086)):
|
|
|
|
log.warn("Resetting all cached artwork")
|
|
|
|
# Remove all existing textures first
|
|
|
|
import artwork
|
|
|
|
artwork.Artwork().delete_cache()
|
|
|
|
|
|
|
|
# reset the install run flag
|
|
|
|
settings('SyncInstallRunDone', value="false")
|
|
|
|
|
|
|
|
# Remove emby info
|
|
|
|
resp = dialog.yesno(language(29999), language(33087))
|
|
|
|
if resp:
|
|
|
|
import connectmanager
|
|
|
|
# Delete the settings
|
|
|
|
addondir = xbmc.translatePath(
|
|
|
|
"special://profile/addon_data/plugin.video.emby/").decode('utf-8')
|
|
|
|
dataPath = "%ssettings.xml" % addondir
|
|
|
|
xbmcvfs.delete(dataPath)
|
|
|
|
connectmanager.ConnectManager().clear_data()
|
|
|
|
|
|
|
|
dialog.ok(heading=language(29999), line1=language(33088))
|
|
|
|
xbmc.executebuiltin('RestartApp')
|
|
|
|
return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xbmcgui.ListItem())
|
|
|
|
|