diff --git a/resources/lib/artwork.py b/resources/lib/artwork.py index 2b828a2d..441dc2de 100644 --- a/resources/lib/artwork.py +++ b/resources/lib/artwork.py @@ -13,7 +13,9 @@ import xbmcvfs import requests import image_cache_thread -from utils import window, settings, dialog, language as lang, kodiSQL, JSONRPC +from utils import window, settings, dialog, language as lang, JSONRPC +from database import DatabaseConn +from contextlib import closing ################################################################################################## @@ -164,47 +166,49 @@ class Artwork(object): def _cache_all_video_entries(self, pdialog): - conn = kodiSQL('video') - cursor = conn.cursor() - cursor.execute("SELECT url FROM art WHERE media_type != 'actor'") # dont include actors - result = cursor.fetchall() - total = len(result) - log.info("Image cache sync about to process %s images", total) - cursor.close() + with DatabaseConn('video') as conn: + with closing(conn.cursor()) as cursor_video: + + cursor_video.execute("SELECT url FROM art WHERE media_type != 'actor'") # dont include actors + result = cursor_video.fetchall() + total = len(result) + log.info("Image cache sync about to process %s images", total) + cursor_video.close() - count = 0 - for url in result: + count = 0 + for url in result: - if pdialog.iscanceled(): - break + if pdialog.iscanceled(): + break - percentage = int((float(count) / float(total))*100) - message = "%s of %s (%s)" % (count, total, len(self.image_cache_threads)) - pdialog.update(percentage, "%s %s" % (lang(33045), message)) - self.cache_texture(url[0]) - count += 1 + percentage = int((float(count) / float(total))*100) + message = "%s of %s (%s)" % (count, total, len(self.image_cache_threads)) + pdialog.update(percentage, "%s %s" % (lang(33045), message)) + self.cache_texture(url[0]) + count += 1 def _cache_all_music_entries(self, pdialog): - conn = kodiSQL('music') - cursor = conn.cursor() - cursor.execute("SELECT url FROM art") - result = cursor.fetchall() - total = len(result) - log.info("Image cache sync about to process %s images", total) - cursor.close() + with DatabaseConn('music') as conn: + with closing(conn.cursor()) as cursor_music: + + cursor_music.execute("SELECT url FROM art") + result = cursor_music.fetchall() + total = len(result) + + log.info("Image cache sync about to process %s images", total) - count = 0 - for url in result: + count = 0 + for url in result: - if pdialog.iscanceled(): - break + if pdialog.iscanceled(): + break - percentage = int((float(count) / float(total))*100) - message = "%s of %s" % (count, total) - pdialog.update(percentage, "%s %s" % (lang(33045), message)) - self.cache_texture(url[0]) - count += 1 + percentage = int((float(count) / float(total))*100) + message = "%s of %s" % (count, total) + pdialog.update(percentage, "%s %s" % (lang(33045), message)) + self.cache_texture(url[0]) + count += 1 @classmethod def delete_cache(cls): @@ -226,16 +230,14 @@ class Artwork(object): log.debug("deleted: %s", filename) # remove all existing data from texture DB - conn = kodiSQL('texture') - cursor = conn.cursor() - cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"') - rows = cursor.fetchall() - for row in rows: - table_name = row[0] - if table_name != "version": - cursor.execute("DELETE FROM " + table_name) - conn.commit() - cursor.close() + with DatabaseConn('texture') as conn: + with closing(conn.cursor()) as cursor_texture: + cursor_texture.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"') + rows = cursor_texture.fetchall() + for row in rows: + table_name = row[0] + if table_name != "version": + cursor_texture.execute("DELETE FROM " + table_name) def _add_worker_image_thread(self, url): @@ -428,33 +430,29 @@ class Artwork(object): @classmethod def delete_cached_artwork(cls, url): - # Only necessary to remove and apply a new backdrop or poster - conn = kodiSQL('texture') - cursor = conn.cursor() + # Only necessary to remove and apply a new backdrop or poster + with DatabaseConn('texture') as conn: + with closing(conn.cursor()) as cursor_texture: + try: + cursor_texture.execute("SELECT cachedurl FROM texture WHERE url = ?", (url,)) + cached_url = cursor_texture.fetchone()[0] - try: - cursor.execute("SELECT cachedurl FROM texture WHERE url = ?", (url,)) - cached_url = cursor.fetchone()[0] + except TypeError: + log.info("Could not find cached url") - except TypeError: - log.info("Could not find cached url") + except OperationalError: + log.info("Database is locked. Skip deletion process.") - except OperationalError: - log.info("Database is locked. Skip deletion process.") + else: # Delete thumbnail as well as the entry + thumbnails = xbmc.translatePath("special://thumbnails/%s" % cached_url).decode('utf-8') + log.info("Deleting cached thumbnail: %s", thumbnails) + xbmcvfs.delete(thumbnails) - else: # Delete thumbnail as well as the entry - thumbnails = xbmc.translatePath("special://thumbnails/%s" % cached_url).decode('utf-8') - log.info("Deleting cached thumbnail: %s", thumbnails) - xbmcvfs.delete(thumbnails) + try: + cursor_texture.execute("DELETE FROM texture WHERE url = ?", (url,)) + except OperationalError: + log.debug("Issue deleting url from cache. Skipping.") - try: - cursor.execute("DELETE FROM texture WHERE url = ?", (url,)) - conn.commit() - except OperationalError: - log.debug("Issue deleting url from cache. Skipping.") - - finally: - cursor.close() def get_people_artwork(self, people): # append imageurl if existing diff --git a/resources/lib/context_entry.py b/resources/lib/context_entry.py index d7a7bf0c..fa9a2d05 100644 --- a/resources/lib/context_entry.py +++ b/resources/lib/context_entry.py @@ -11,7 +11,7 @@ import api import read_embyserver as embyserver import embydb_functions as embydb import musicutils as musicutils -from utils import settings, dialog, language as lang, kodiSQL +from utils import settings, dialog, language as lang from dialogs import context from database import DatabaseConn from contextlib import closing @@ -165,31 +165,28 @@ class ContextMenu(object): def _rate_song(self): - conn = kodiSQL('music') - cursor = conn.cursor() - query = "SELECT rating FROM song WHERE idSong = ?" - cursor.execute(query, (self.kodi_id,)) - try: - value = cursor.fetchone()[0] - current_value = int(round(float(value), 0)) - except TypeError: - pass - else: - new_value = dialog("numeric", 0, lang(30411), str(current_value)) - if new_value > -1: + with DatabaseConn('music') as conn: + with closing(conn.cursor()) as cursor_music: + query = "SELECT rating FROM song WHERE idSong = ?" + cursor_music.execute(query, (self.kodi_id,)) + try: + value = cursor_music.fetchone()[0] + current_value = int(round(float(value), 0)) + except TypeError: + pass + else: + new_value = dialog("numeric", 0, lang(30411), str(current_value)) + if new_value > -1: - new_value = int(new_value) - if new_value > 5: - new_value = 5 + new_value = int(new_value) + if new_value > 5: + new_value = 5 - if settings('enableUpdateSongRating') == "true": - musicutils.updateRatingToFile(new_value, self.api.get_file_path()) + if settings('enableUpdateSongRating') == "true": + musicutils.updateRatingToFile(new_value, self.api.get_file_path()) - query = "UPDATE song SET rating = ? WHERE idSong = ?" - cursor.execute(query, (new_value, self.kodi_id,)) - conn.commit() - finally: - cursor.close() + query = "UPDATE song SET rating = ? WHERE idSong = ?" + cursor_music.execute(query, (new_value, self.kodi_id,)) def _delete_item(self): diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index 7c5d6178..a94d46e0 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -180,12 +180,10 @@ def emby_backup(): shutil.copy(src=xbmc.translatePath("special://database/emby.db").decode('utf-8'), dst=database) # Videos database - shutil.copy(src=utils.getKodiVideoDBPath(), - dst=database) + shutil.copy(src=DatabaseConn()._SQL('video'), dst=database) # Music database if settings('enableMusic') == "true": - shutil.copy(src=utils.getKodiMusicDBPath(), - dst=database) + shutil.copy(src=DatabaseConn()._SQL('music'), dst=database) dialog(type_="ok", heading="{emby}", diff --git a/resources/lib/itemtypes.py b/resources/lib/itemtypes.py index 6dda8b38..d4645afc 100644 --- a/resources/lib/itemtypes.py +++ b/resources/lib/itemtypes.py @@ -6,7 +6,9 @@ import logging import read_embyserver as embyserver from objects import Movies, MusicVideos, TVShows, Music -from utils import settings, kodiSQL +from utils import settings +from database import DatabaseConn +from contextlib import closing ################################################################################################# @@ -58,46 +60,40 @@ class Items(object): if pdialog: pdialog.update(heading="Processing %s: %s items" % (process, total)) - for itemtype in items: + # this is going to open a music connection even if it is not needed but + # I feel that is better than trying to sort out the login yourself + with DatabaseConn('music') as conn: + with closing(conn.cursor()) as cursor_music: + + for itemtype in items: - # Safety check - if not itemtypes.get(itemtype): - # We don't process this type of item - continue + # Safety check + if not itemtypes.get(itemtype): + # We don't process this type of item + continue - itemlist = items[itemtype] - if not itemlist: - # The list to process is empty - continue + itemlist = items[itemtype] + if not itemlist: + # The list to process is empty + continue - musicconn = None + if itemtype in ('MusicAlbum', 'MusicArtist', 'AlbumArtist', 'Audio'): + if self.music_enabled: + items_process = itemtypes[itemtype](embycursor, cursor_music, pdialog) # see note above + else: + # Music is not enabled, do not proceed with itemtype + continue + else: + update_videolibrary = True + items_process = itemtypes[itemtype](embycursor, kodicursor, pdialog) - if itemtype in ('MusicAlbum', 'MusicArtist', 'AlbumArtist', 'Audio'): - if self.music_enabled: - musicconn = kodiSQL('music') - musiccursor = musicconn.cursor() - items_process = itemtypes[itemtype](embycursor, musiccursor, pdialog) - else: - # Music is not enabled, do not proceed with itemtype - continue - else: - update_videolibrary = True - items_process = itemtypes[itemtype](embycursor, kodicursor, pdialog) + if process == "added": + items_process.add_all(itemtype, itemlist) + elif process == "remove": + items_process.remove_all(itemtype, itemlist) + else: + process_items = self.emby.getFullItems(itemlist) + items_process.process_all(itemtype, process, process_items, total) - if process == "added": - items_process.add_all(itemtype, itemlist) - elif process == "remove": - items_process.remove_all(itemtype, itemlist) - else: - process_items = self.emby.getFullItems(itemlist) - items_process.process_all(itemtype, process, process_items, total) - - - if musicconn is not None: - # close connection for special types - log.info("updating music database") - musicconn.commit() - musiccursor.close() - return (True, update_videolibrary) diff --git a/resources/lib/kodimonitor.py b/resources/lib/kodimonitor.py index 2454c4ef..c0a9bd72 100644 --- a/resources/lib/kodimonitor.py +++ b/resources/lib/kodimonitor.py @@ -11,7 +11,7 @@ import xbmcgui import downloadutils import embydb_functions as embydb import playbackutils as pbutils -from utils import window, settings, kodiSQL +from utils import window, settings from ga_client import log_error from database import DatabaseConn from contextlib import closing diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index 31622fb4..94b52997 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -291,7 +291,7 @@ class LibrarySync(threading.Thread): continue startTime = datetime.now() - completed = process[itemtype](cursor_emby, kodicursor, pDialog) + completed = process[itemtype](cursor_emby, cursor_video, pDialog) if not completed: xbmc.executebuiltin('InhibitIdleShutdown(false)') utils.setScreensaver(value=screensaver) @@ -913,7 +913,7 @@ class LibrarySync(threading.Thread): if not startupComplete: # Verify the video database can be found - videoDb = utils.getKodiVideoDBPath() + videoDb = DatabaseConn()._SQL('video') if not xbmcvfs.exists(videoDb): # Database does not exists log.error( diff --git a/resources/lib/playlist.py b/resources/lib/playlist.py index 1eaac424..82137c0f 100644 --- a/resources/lib/playlist.py +++ b/resources/lib/playlist.py @@ -11,7 +11,7 @@ import playutils import playbackutils import embydb_functions as embydb import read_embyserver as embyserver -from utils import window, kodiSQL, JSONRPC +from utils import window, JSONRPC from database import DatabaseConn from contextlib import closing diff --git a/resources/lib/read_embyserver.py b/resources/lib/read_embyserver.py index 5ea9cafa..e2cec77f 100644 --- a/resources/lib/read_embyserver.py +++ b/resources/lib/read_embyserver.py @@ -8,7 +8,7 @@ import hashlib import xbmc import downloadutils -from utils import window, settings, kodiSQL +from utils import window, settings from database import DatabaseConn from contextlib import closing diff --git a/resources/lib/utils.py b/resources/lib/utils.py index b82a167f..9191c702 100644 --- a/resources/lib/utils.py +++ b/resources/lib/utils.py @@ -120,55 +120,6 @@ def should_stop(): else: # Keep going return False -def kodiSQL(media_type="video"): - - if media_type == "emby": - dbPath = xbmc.translatePath("special://database/emby.db").decode('utf-8') - elif media_type == "texture": - dbPath = xbmc.translatePath("special://database/Textures13.db").decode('utf-8') - elif media_type == "music": - dbPath = getKodiMusicDBPath() - else: - dbPath = getKodiVideoDBPath() - - if settings('dblock') == "true": - connection = sqlite3.connect(dbPath, isolation_level=None, timeout=20) - else: - connection = sqlite3.connect(dbPath, timeout=20) - return connection - -def getKodiVideoDBPath(): - - dbVersion = { - - "13": 78, # Gotham - "14": 90, # Helix - "15": 93, # Isengard - "16": 99, # Jarvis - "17": 107 # Krypton - } - - dbPath = xbmc.translatePath( - "special://database/MyVideos%s.db" - % dbVersion.get(xbmc.getInfoLabel('System.BuildVersion')[:2], "")).decode('utf-8') - return dbPath - -def getKodiMusicDBPath(): - - dbVersion = { - - "13": 46, # Gotham - "14": 48, # Helix - "15": 52, # Isengard - "16": 56, # Jarvis - "17": 60 # Krypton - } - - dbPath = xbmc.translatePath( - "special://database/MyMusic%s.db" - % dbVersion.get(xbmc.getInfoLabel('System.BuildVersion')[:2], "")).decode('utf-8') - return dbPath - ################################################################################################# # Utility methods