# -*- coding: utf-8 -*- ################################################################################################# import logging import sqlite3 import sys import traceback import xbmc import xbmcgui import xbmcplugin import xbmcvfs from views import Playlist, VideoNodes from utils import window, should_stop, settings, language ################################################################################################# log = logging.getLogger("EMBY."+__name__) KODI = xbmc.getInfoLabel('System.BuildVersion')[:2] ################################################################################################# def video_database(): db_version = { '13': 78, # Gotham '14': 90, # Helix '15': 93, # Isengard '16': 99, # Jarvis '17': 107,# Krypton '18': 109 # Leia } return xbmc.translatePath("special://database/MyVideos%s.db" % db_version.get(KODI, "")).decode('utf-8') def music_database(): db_version = { '13': 46, # Gotham '14': 48, # Helix '15': 52, # Isengard '16': 56, # Jarvis '17': 60, # Krypton '18': 68 # Leia } return xbmc.translatePath("special://database/MyMusic%s.db" % db_version.get(KODI, "")).decode('utf-8') 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 class DatabaseConn(object): # To be called as context manager - i.e. with DatabaseConn() as conn: #dostuff def __init__(self, database_file="video", commit_on_close=True, timeout=120): """ database_file can be custom: emby, texture, music, video, :memory: or path to the file commit_mode set to None to autocommit (isolation_level). See python documentation. """ self.db_file = database_file self.commit_on_close = commit_on_close self.timeout = timeout def __enter__(self): # Open the connection self.path = self._SQL(self.db_file) #traceback.print_stack() 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) log.info("opened: %s - %s", self.path, id(self.conn)) self.cursor = self.conn.cursor() if self.db_file == "emby": verify_emby_database(self.cursor) self.conn.commit() return self.cursor def _SQL(self, media_type): 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 def __exit__(self, exc_type, exc_val, exc_tb): # Close the connection changes = self.conn.total_changes if exc_type is not None: # Errors were raised in the with statement log.error("Type: %s Value: %s", exc_type, exc_val) if self.commit_on_close == True and changes: log.info("number of rows updated: %s", changes) if self.db_file == "video": kodi_commit() self.conn.commit() log.info("commit: %s", self.path) log.info("closing: %s - %s", self.path, id(self.conn)) self.cursor.close() self.conn.close() def verify_emby_database(cursor): # Create the tables for the emby database # emby, view, version 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, group_series TEXT)""") cursor.execute("CREATE TABLE IF NOT EXISTS version(idVersion TEXT)") columns = cursor.execute("SELECT * FROM view") if 'group_series' not in [description[0] for description in columns.description]: log.info("Add missing column group_series") cursor.execute("ALTER TABLE view ADD COLUMN group_series 'TEXT'") 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 Playlist().delete_playlists() # Clean up the video nodes VideoNodes().deleteNodes() # Wipe the kodi databases log.warn("Resetting the Kodi video database.") 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) if settings('enableMusic') == "true": log.warn("Resetting the Kodi music database.") with DatabaseConn('music') 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) # 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") # 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') try: xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xbmcgui.ListItem()) except: pass