mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-12-24 17:56:11 +00:00
remove old kodiSQL function
use DatabaseCon for DB file paths switch last few DB Cons to use the new DatabaseCon context class
This commit is contained in:
parent
881b3f8e70
commit
b55b4d0b96
9 changed files with 123 additions and 183 deletions
|
@ -13,7 +13,9 @@ import xbmcvfs
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
import image_cache_thread
|
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):
|
def _cache_all_video_entries(self, pdialog):
|
||||||
|
|
||||||
conn = kodiSQL('video')
|
with DatabaseConn('video') as conn:
|
||||||
cursor = conn.cursor()
|
with closing(conn.cursor()) as cursor_video:
|
||||||
cursor.execute("SELECT url FROM art WHERE media_type != 'actor'") # dont include actors
|
|
||||||
result = cursor.fetchall()
|
cursor_video.execute("SELECT url FROM art WHERE media_type != 'actor'") # dont include actors
|
||||||
total = len(result)
|
result = cursor_video.fetchall()
|
||||||
log.info("Image cache sync about to process %s images", total)
|
total = len(result)
|
||||||
cursor.close()
|
log.info("Image cache sync about to process %s images", total)
|
||||||
|
cursor_video.close()
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
for url in result:
|
for url in result:
|
||||||
|
|
||||||
if pdialog.iscanceled():
|
if pdialog.iscanceled():
|
||||||
break
|
break
|
||||||
|
|
||||||
percentage = int((float(count) / float(total))*100)
|
percentage = int((float(count) / float(total))*100)
|
||||||
message = "%s of %s (%s)" % (count, total, len(self.image_cache_threads))
|
message = "%s of %s (%s)" % (count, total, len(self.image_cache_threads))
|
||||||
pdialog.update(percentage, "%s %s" % (lang(33045), message))
|
pdialog.update(percentage, "%s %s" % (lang(33045), message))
|
||||||
self.cache_texture(url[0])
|
self.cache_texture(url[0])
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
def _cache_all_music_entries(self, pdialog):
|
def _cache_all_music_entries(self, pdialog):
|
||||||
|
|
||||||
conn = kodiSQL('music')
|
with DatabaseConn('music') as conn:
|
||||||
cursor = conn.cursor()
|
with closing(conn.cursor()) as cursor_music:
|
||||||
cursor.execute("SELECT url FROM art")
|
|
||||||
result = cursor.fetchall()
|
cursor_music.execute("SELECT url FROM art")
|
||||||
total = len(result)
|
result = cursor_music.fetchall()
|
||||||
log.info("Image cache sync about to process %s images", total)
|
total = len(result)
|
||||||
cursor.close()
|
|
||||||
|
log.info("Image cache sync about to process %s images", total)
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
for url in result:
|
for url in result:
|
||||||
|
|
||||||
if pdialog.iscanceled():
|
if pdialog.iscanceled():
|
||||||
break
|
break
|
||||||
|
|
||||||
percentage = int((float(count) / float(total))*100)
|
percentage = int((float(count) / float(total))*100)
|
||||||
message = "%s of %s" % (count, total)
|
message = "%s of %s" % (count, total)
|
||||||
pdialog.update(percentage, "%s %s" % (lang(33045), message))
|
pdialog.update(percentage, "%s %s" % (lang(33045), message))
|
||||||
self.cache_texture(url[0])
|
self.cache_texture(url[0])
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def delete_cache(cls):
|
def delete_cache(cls):
|
||||||
|
@ -226,16 +230,14 @@ class Artwork(object):
|
||||||
log.debug("deleted: %s", filename)
|
log.debug("deleted: %s", filename)
|
||||||
|
|
||||||
# remove all existing data from texture DB
|
# remove all existing data from texture DB
|
||||||
conn = kodiSQL('texture')
|
with DatabaseConn('texture') as conn:
|
||||||
cursor = conn.cursor()
|
with closing(conn.cursor()) as cursor_texture:
|
||||||
cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
|
cursor_texture.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
|
||||||
rows = cursor.fetchall()
|
rows = cursor_texture.fetchall()
|
||||||
for row in rows:
|
for row in rows:
|
||||||
table_name = row[0]
|
table_name = row[0]
|
||||||
if table_name != "version":
|
if table_name != "version":
|
||||||
cursor.execute("DELETE FROM " + table_name)
|
cursor_texture.execute("DELETE FROM " + table_name)
|
||||||
conn.commit()
|
|
||||||
cursor.close()
|
|
||||||
|
|
||||||
def _add_worker_image_thread(self, url):
|
def _add_worker_image_thread(self, url):
|
||||||
|
|
||||||
|
@ -428,33 +430,29 @@ class Artwork(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def delete_cached_artwork(cls, url):
|
def delete_cached_artwork(cls, url):
|
||||||
# Only necessary to remove and apply a new backdrop or poster
|
# Only necessary to remove and apply a new backdrop or poster
|
||||||
conn = kodiSQL('texture')
|
with DatabaseConn('texture') as conn:
|
||||||
cursor = conn.cursor()
|
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:
|
except TypeError:
|
||||||
cursor.execute("SELECT cachedurl FROM texture WHERE url = ?", (url,))
|
log.info("Could not find cached url")
|
||||||
cached_url = cursor.fetchone()[0]
|
|
||||||
|
|
||||||
except TypeError:
|
except OperationalError:
|
||||||
log.info("Could not find cached url")
|
log.info("Database is locked. Skip deletion process.")
|
||||||
|
|
||||||
except OperationalError:
|
else: # Delete thumbnail as well as the entry
|
||||||
log.info("Database is locked. Skip deletion process.")
|
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
|
try:
|
||||||
thumbnails = xbmc.translatePath("special://thumbnails/%s" % cached_url).decode('utf-8')
|
cursor_texture.execute("DELETE FROM texture WHERE url = ?", (url,))
|
||||||
log.info("Deleting cached thumbnail: %s", thumbnails)
|
except OperationalError:
|
||||||
xbmcvfs.delete(thumbnails)
|
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):
|
def get_people_artwork(self, people):
|
||||||
# append imageurl if existing
|
# append imageurl if existing
|
||||||
|
|
|
@ -11,7 +11,7 @@ import api
|
||||||
import read_embyserver as embyserver
|
import read_embyserver as embyserver
|
||||||
import embydb_functions as embydb
|
import embydb_functions as embydb
|
||||||
import musicutils as musicutils
|
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 dialogs import context
|
||||||
from database import DatabaseConn
|
from database import DatabaseConn
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
@ -165,31 +165,28 @@ class ContextMenu(object):
|
||||||
|
|
||||||
def _rate_song(self):
|
def _rate_song(self):
|
||||||
|
|
||||||
conn = kodiSQL('music')
|
with DatabaseConn('music') as conn:
|
||||||
cursor = conn.cursor()
|
with closing(conn.cursor()) as cursor_music:
|
||||||
query = "SELECT rating FROM song WHERE idSong = ?"
|
query = "SELECT rating FROM song WHERE idSong = ?"
|
||||||
cursor.execute(query, (self.kodi_id,))
|
cursor_music.execute(query, (self.kodi_id,))
|
||||||
try:
|
try:
|
||||||
value = cursor.fetchone()[0]
|
value = cursor_music.fetchone()[0]
|
||||||
current_value = int(round(float(value), 0))
|
current_value = int(round(float(value), 0))
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
new_value = dialog("numeric", 0, lang(30411), str(current_value))
|
new_value = dialog("numeric", 0, lang(30411), str(current_value))
|
||||||
if new_value > -1:
|
if new_value > -1:
|
||||||
|
|
||||||
new_value = int(new_value)
|
new_value = int(new_value)
|
||||||
if new_value > 5:
|
if new_value > 5:
|
||||||
new_value = 5
|
new_value = 5
|
||||||
|
|
||||||
if settings('enableUpdateSongRating') == "true":
|
if settings('enableUpdateSongRating') == "true":
|
||||||
musicutils.updateRatingToFile(new_value, self.api.get_file_path())
|
musicutils.updateRatingToFile(new_value, self.api.get_file_path())
|
||||||
|
|
||||||
query = "UPDATE song SET rating = ? WHERE idSong = ?"
|
query = "UPDATE song SET rating = ? WHERE idSong = ?"
|
||||||
cursor.execute(query, (new_value, self.kodi_id,))
|
cursor_music.execute(query, (new_value, self.kodi_id,))
|
||||||
conn.commit()
|
|
||||||
finally:
|
|
||||||
cursor.close()
|
|
||||||
|
|
||||||
def _delete_item(self):
|
def _delete_item(self):
|
||||||
|
|
||||||
|
|
|
@ -180,12 +180,10 @@ def emby_backup():
|
||||||
shutil.copy(src=xbmc.translatePath("special://database/emby.db").decode('utf-8'),
|
shutil.copy(src=xbmc.translatePath("special://database/emby.db").decode('utf-8'),
|
||||||
dst=database)
|
dst=database)
|
||||||
# Videos database
|
# Videos database
|
||||||
shutil.copy(src=utils.getKodiVideoDBPath(),
|
shutil.copy(src=DatabaseConn()._SQL('video'), dst=database)
|
||||||
dst=database)
|
|
||||||
# Music database
|
# Music database
|
||||||
if settings('enableMusic') == "true":
|
if settings('enableMusic') == "true":
|
||||||
shutil.copy(src=utils.getKodiMusicDBPath(),
|
shutil.copy(src=DatabaseConn()._SQL('music'), dst=database)
|
||||||
dst=database)
|
|
||||||
|
|
||||||
dialog(type_="ok",
|
dialog(type_="ok",
|
||||||
heading="{emby}",
|
heading="{emby}",
|
||||||
|
|
|
@ -6,7 +6,9 @@ import logging
|
||||||
|
|
||||||
import read_embyserver as embyserver
|
import read_embyserver as embyserver
|
||||||
from objects import Movies, MusicVideos, TVShows, Music
|
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:
|
if pdialog:
|
||||||
pdialog.update(heading="Processing %s: %s items" % (process, total))
|
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
|
# Safety check
|
||||||
if not itemtypes.get(itemtype):
|
if not itemtypes.get(itemtype):
|
||||||
# We don't process this type of item
|
# We don't process this type of item
|
||||||
continue
|
continue
|
||||||
|
|
||||||
itemlist = items[itemtype]
|
itemlist = items[itemtype]
|
||||||
if not itemlist:
|
if not itemlist:
|
||||||
# The list to process is empty
|
# The list to process is empty
|
||||||
continue
|
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 process == "added":
|
||||||
if self.music_enabled:
|
items_process.add_all(itemtype, itemlist)
|
||||||
musicconn = kodiSQL('music')
|
elif process == "remove":
|
||||||
musiccursor = musicconn.cursor()
|
items_process.remove_all(itemtype, itemlist)
|
||||||
items_process = itemtypes[itemtype](embycursor, musiccursor, pdialog)
|
else:
|
||||||
else:
|
process_items = self.emby.getFullItems(itemlist)
|
||||||
# Music is not enabled, do not proceed with itemtype
|
items_process.process_all(itemtype, process, process_items, total)
|
||||||
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 musicconn is not None:
|
|
||||||
# close connection for special types
|
|
||||||
log.info("updating music database")
|
|
||||||
musicconn.commit()
|
|
||||||
musiccursor.close()
|
|
||||||
|
|
||||||
return (True, update_videolibrary)
|
return (True, update_videolibrary)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import xbmcgui
|
||||||
import downloadutils
|
import downloadutils
|
||||||
import embydb_functions as embydb
|
import embydb_functions as embydb
|
||||||
import playbackutils as pbutils
|
import playbackutils as pbutils
|
||||||
from utils import window, settings, kodiSQL
|
from utils import window, settings
|
||||||
from ga_client import log_error
|
from ga_client import log_error
|
||||||
from database import DatabaseConn
|
from database import DatabaseConn
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
|
@ -291,7 +291,7 @@ class LibrarySync(threading.Thread):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
startTime = datetime.now()
|
startTime = datetime.now()
|
||||||
completed = process[itemtype](cursor_emby, kodicursor, pDialog)
|
completed = process[itemtype](cursor_emby, cursor_video, pDialog)
|
||||||
if not completed:
|
if not completed:
|
||||||
xbmc.executebuiltin('InhibitIdleShutdown(false)')
|
xbmc.executebuiltin('InhibitIdleShutdown(false)')
|
||||||
utils.setScreensaver(value=screensaver)
|
utils.setScreensaver(value=screensaver)
|
||||||
|
@ -913,7 +913,7 @@ class LibrarySync(threading.Thread):
|
||||||
|
|
||||||
if not startupComplete:
|
if not startupComplete:
|
||||||
# Verify the video database can be found
|
# Verify the video database can be found
|
||||||
videoDb = utils.getKodiVideoDBPath()
|
videoDb = DatabaseConn()._SQL('video')
|
||||||
if not xbmcvfs.exists(videoDb):
|
if not xbmcvfs.exists(videoDb):
|
||||||
# Database does not exists
|
# Database does not exists
|
||||||
log.error(
|
log.error(
|
||||||
|
|
|
@ -11,7 +11,7 @@ import playutils
|
||||||
import playbackutils
|
import playbackutils
|
||||||
import embydb_functions as embydb
|
import embydb_functions as embydb
|
||||||
import read_embyserver as embyserver
|
import read_embyserver as embyserver
|
||||||
from utils import window, kodiSQL, JSONRPC
|
from utils import window, JSONRPC
|
||||||
from database import DatabaseConn
|
from database import DatabaseConn
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import hashlib
|
||||||
import xbmc
|
import xbmc
|
||||||
|
|
||||||
import downloadutils
|
import downloadutils
|
||||||
from utils import window, settings, kodiSQL
|
from utils import window, settings
|
||||||
from database import DatabaseConn
|
from database import DatabaseConn
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
|
||||||
|
|
|
@ -120,55 +120,6 @@ def should_stop():
|
||||||
else: # Keep going
|
else: # Keep going
|
||||||
return False
|
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
|
# Utility methods
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue