Again, big clean-up

This commit is contained in:
tomkat83 2016-02-11 14:03:04 +01:00
parent c451a236e7
commit e8900b0a4a
4 changed files with 173 additions and 148 deletions

View file

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################# ###############################################################################
from utils import logging, kodiSQL from utils import logging, kodiSQL
################################################################################################# ###############################################################################
class GetEmbyDB(): class GetEmbyDB():

View file

@ -1,17 +1,41 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################## ###############################################################################
import xbmc import xbmc
import artwork import artwork
import clientinfo import clientinfo
import utils from utils import logging, kodiSQL
################################################################################################## ###############################################################################
@utils.logging class GetKodiDB():
"""
Usage: with GetKodiDB(itemType) as kodi_db:
do stuff with kodi_db
Parameters:
itemType: itemtype for Kodi DB, e.g. 'video'
On exiting "with" (no matter what), commits get automatically committed
and the db gets closed
"""
def __init__(self, itemType):
self.itemType = itemType
def __enter__(self):
self.kodiconn = kodiSQL(self.itemType)
self.emby_db = Kodidb_Functions(self.kodiconn.cursor())
return self.emby_db
def __exit__(self, type, value, traceback):
self.kodiconn.commit()
self.kodiconn.close()
@logging
class Kodidb_Functions(): class Kodidb_Functions():
kodiversion = int(xbmc.getInfoLabel("System.BuildVersion")[:2]) kodiversion = int(xbmc.getInfoLabel("System.BuildVersion")[:2])
@ -238,7 +262,6 @@ class Kodidb_Functions():
query = "INSERT INTO actor(actor_id, name) values(?, ?)" query = "INSERT INTO actor(actor_id, name) values(?, ?)"
cursor.execute(query, (actorid, name)) cursor.execute(query, (actorid, name))
self.logMsg("Add people to media, processing: %s" % name, 2)
finally: finally:
# Link person to content # Link person to content
@ -297,7 +320,6 @@ class Kodidb_Functions():
query = "INSERT INTO actors(idActor, strActor) values(?, ?)" query = "INSERT INTO actors(idActor, strActor) values(?, ?)"
cursor.execute(query, (actorid, name)) cursor.execute(query, (actorid, name))
self.logMsg("Add people to media, processing: %s" % name, 2)
finally: finally:
# Link person to content # Link person to content
@ -447,8 +469,7 @@ class Kodidb_Functions():
query = "INSERT INTO genre(genre_id, name) values(?, ?)" query = "INSERT INTO genre(genre_id, name) values(?, ?)"
cursor.execute(query, (genre_id, genre)) cursor.execute(query, (genre_id, genre))
self.logMsg("Add Genres to media, processing: %s" % genre, 2)
finally: finally:
# Assign genre to item # Assign genre to item
query = ( query = (
@ -492,8 +513,7 @@ class Kodidb_Functions():
query = "INSERT INTO genre(idGenre, strGenre) values(?, ?)" query = "INSERT INTO genre(idGenre, strGenre) values(?, ?)"
cursor.execute(query, (idGenre, genre)) cursor.execute(query, (idGenre, genre))
self.logMsg("Add Genres to media, processing: %s" % genre, 2)
finally: finally:
# Assign genre to item # Assign genre to item
if "movie" in mediatype: if "movie" in mediatype:
@ -554,7 +574,6 @@ class Kodidb_Functions():
query = "INSERT INTO studio(studio_id, name) values(?, ?)" query = "INSERT INTO studio(studio_id, name) values(?, ?)"
cursor.execute(query, (studioid, studio)) cursor.execute(query, (studioid, studio))
self.logMsg("Add Studios to media, processing: %s" % studio, 2)
finally: # Assign studio to item finally: # Assign studio to item
query = ( query = (
@ -585,7 +604,6 @@ class Kodidb_Functions():
query = "INSERT INTO studio(idstudio, strstudio) values(?, ?)" query = "INSERT INTO studio(idstudio, strstudio) values(?, ?)"
cursor.execute(query, (studioid, studio)) cursor.execute(query, (studioid, studio))
self.logMsg("Add Studios to media, processing: %s" % studio, 2)
finally: # Assign studio to item finally: # Assign studio to item
if "movie" in mediatype: if "movie" in mediatype:

View file

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################## ###############################################################################
import threading from threading import Thread, Lock
from datetime import datetime from datetime import datetime
import Queue import Queue
@ -10,7 +10,6 @@ import xbmc
import xbmcgui import xbmcgui
import xbmcvfs import xbmcvfs
import api
import utils import utils
import clientinfo import clientinfo
import downloadutils import downloadutils
@ -24,12 +23,12 @@ import videonodes
import PlexAPI import PlexAPI
import PlexFunctions import PlexFunctions
################################################################################################## ###############################################################################
@utils.ThreadMethodsAdditionalStop('emby_shouldStop') @utils.ThreadMethodsAdditionalStop('emby_shouldStop')
@utils.ThreadMethods @utils.ThreadMethods
class ThreadedGetMetadata(threading.Thread): class ThreadedGetMetadata(Thread):
""" """
Threaded download of Plex XML metadata for a certain library item. Threaded download of Plex XML metadata for a certain library item.
Fills the out_queue with the downloaded etree XML objects Fills the out_queue with the downloaded etree XML objects
@ -37,15 +36,15 @@ class ThreadedGetMetadata(threading.Thread):
Input: Input:
queue Queue.Queue() object that you'll need to fill up queue Queue.Queue() object that you'll need to fill up
with Plex itemIds with Plex itemIds
out_queue Queue.Queue() object where this thread will store out_queue Queue() object where this thread will store
the downloaded metadata XMLs as etree objects the downloaded metadata XMLs as etree objects
lock threading.Lock(), used for counting where we are lock Lock(), used for counting where we are
""" """
def __init__(self, queue, out_queue, lock): def __init__(self, queue, out_queue, lock):
self.queue = queue self.queue = queue
self.out_queue = out_queue self.out_queue = out_queue
self.lock = lock self.lock = lock
threading.Thread.__init__(self) Thread.__init__(self)
def run(self): def run(self):
# cache local variables because it's faster # cache local variables because it's faster
@ -81,7 +80,7 @@ class ThreadedGetMetadata(threading.Thread):
@utils.ThreadMethodsAdditionalStop('emby_shouldStop') @utils.ThreadMethodsAdditionalStop('emby_shouldStop')
@utils.ThreadMethods @utils.ThreadMethods
class ThreadedProcessMetadata(threading.Thread): class ThreadedProcessMetadata(Thread):
""" """
Not yet implemented - if ever. Only to be called by ONE thread! Not yet implemented - if ever. Only to be called by ONE thread!
Processes the XML metadata in the queue Processes the XML metadata in the queue
@ -91,13 +90,13 @@ class ThreadedProcessMetadata(threading.Thread):
the downloaded XML eTree objects the downloaded XML eTree objects
itemType: as used to call functions in itemtypes.py itemType: as used to call functions in itemtypes.py
e.g. 'Movies' => itemtypes.Movies() e.g. 'Movies' => itemtypes.Movies()
lock: threading.Lock(), used for counting where we are lock: Lock(), used for counting where we are
""" """
def __init__(self, queue, itemType, lock): def __init__(self, queue, itemType, lock):
self.queue = queue self.queue = queue
self.lock = lock self.lock = lock
self.itemType = itemType self.itemType = itemType
threading.Thread.__init__(self) Thread.__init__(self)
def run(self): def run(self):
# Constructs the method name, e.g. itemtypes.Movies # Constructs the method name, e.g. itemtypes.Movies
@ -132,15 +131,13 @@ class ThreadedProcessMetadata(threading.Thread):
# Keep track of where we are at # Keep track of where we are at
processMetadataCount += 1 processMetadataCount += 1
processingViewName = title processingViewName = title
del plexitem
del updateItem
# signals to queue job is done # signals to queue job is done
queue.task_done() queue.task_done()
@utils.ThreadMethodsAdditionalStop('emby_shouldStop') @utils.ThreadMethodsAdditionalStop('emby_shouldStop')
@utils.ThreadMethods @utils.ThreadMethods
class ThreadedShowSyncInfo(threading.Thread): class ThreadedShowSyncInfo(Thread):
""" """
Threaded class to show the Kodi statusbar of the metadata download. Threaded class to show the Kodi statusbar of the metadata download.
@ -155,7 +152,7 @@ class ThreadedShowSyncInfo(threading.Thread):
self.addonName = clientinfo.ClientInfo().getAddonName() self.addonName = clientinfo.ClientInfo().getAddonName()
self.dialog = dialog self.dialog = dialog
self.itemType = itemType self.itemType = itemType
threading.Thread.__init__(self) Thread.__init__(self)
def run(self): def run(self):
# cache local variables because it's faster # cache local variables because it's faster
@ -201,7 +198,7 @@ class ThreadedShowSyncInfo(threading.Thread):
@utils.ThreadMethodsAdditionalSuspend('suspend_LibraryThread') @utils.ThreadMethodsAdditionalSuspend('suspend_LibraryThread')
@utils.ThreadMethodsAdditionalStop('emby_shouldStop') @utils.ThreadMethodsAdditionalStop('emby_shouldStop')
@utils.ThreadMethods @utils.ThreadMethods
class LibrarySync(threading.Thread): class LibrarySync(Thread):
# Borg, even though it's planned to only have 1 instance up and running! # Borg, even though it's planned to only have 1 instance up and running!
_shared_state = {} _shared_state = {}
# How long should we look into the past for fast syncing items (in s) # How long should we look into the past for fast syncing items (in s)
@ -224,7 +221,7 @@ class LibrarySync(threading.Thread):
self.showDbSync = True if \ self.showDbSync = True if \
utils.settings('dbSyncIndicator') == 'true' else False utils.settings('dbSyncIndicator') == 'true' else False
threading.Thread.__init__(self) Thread.__init__(self)
def startSync(self): def startSync(self):
utils.window('emby_dbScan', value="true") utils.window('emby_dbScan', value="true")
@ -419,18 +416,108 @@ class LibrarySync(threading.Thread):
sound=False) sound=False)
return True return True
def processView(self, folderItem, kodi_db, emby_db, totalnodes):
vnodes = self.vnodes
folder = folderItem.attrib
mediatype = folder['type']
# Only process supported formats
if mediatype not in ['movie', 'show']:
return
folderid = folder['key']
foldername = folder['title']
viewtype = folder['type']
# Get current media folders from emby database
view = emby_db.getView_byId(folderid)
try:
current_viewname = view[0]
current_viewtype = view[1]
current_tagid = view[2]
except TypeError:
self.logMsg("Creating viewid: %s in Emby database."
% folderid, 1)
tagid = kodi_db.createTag(foldername)
# Create playlist for the video library
if mediatype in ['movies', 'tvshows', 'musicvideos']:
utils.playlistXSP(mediatype, foldername, viewtype)
# Create the video node
if (mediatype in ['movies', 'tvshows', 'musicvideos',
'homevideos']):
vnodes.viewNode(totalnodes,
foldername,
mediatype,
viewtype)
totalnodes += 1
# Add view to emby database
emby_db.addView(folderid, foldername, viewtype, tagid)
else:
self.logMsg(' '.join((
"Found viewid: %s" % folderid,
"viewname: %s" % current_viewname,
"viewtype: %s" % current_viewtype,
"tagid: %s" % current_tagid)), 2)
# View was modified, update with latest info
if current_viewname != foldername:
self.logMsg("viewid: %s new viewname: %s"
% (folderid, foldername), 1)
tagid = kodi_db.createTag(foldername)
# Update view with new info
emby_db.updateView(foldername, tagid, folderid)
if mediatype != "music":
if emby_db.getView_byName(current_viewname) is None:
# The tag could be a combined view. Ensure there's
# no other tags with the same name before deleting
# playlist.
utils.playlistXSP(mediatype,
current_viewname,
current_viewtype,
True)
# Delete video node
if mediatype != "musicvideos":
vnodes.viewNode(totalnodes,
current_viewname,
mediatype,
current_viewtype,
delete=True)
# Added new playlist
if mediatype in ['movies', 'tvshows', 'musicvideos']:
utils.playlistXSP(mediatype, foldername, viewtype)
# Add new video node
if mediatype != "musicvideos":
vnodes.viewNode(totalnodes,
foldername,
mediatype,
viewtype)
totalnodes += 1
# Update items with new tag
items = emby_db.getItem_byView(folderid)
for item in items:
# Remove the "s" from viewtype for tags
kodi_db.updateTag(current_tagid,
tagid,
item[0],
current_viewtype[:-1])
else:
if mediatype != "music":
# Validate the playlist exists or recreate it
if mediatype in ['movies', 'tvshows', 'musicvideos']:
utils.playlistXSP(mediatype, foldername, viewtype)
# Create the video node if not already exists
if mediatype != "musicvideos":
vnodes.viewNode(totalnodes,
foldername,
mediatype,
viewtype)
totalnodes += 1
def maintainViews(self): def maintainViews(self):
""" """
Compare the views to Plex Compare the views to Plex
""" """
# Open DB links
embyconn = utils.kodiSQL('emby')
embycursor = embyconn.cursor()
kodiconn = utils.kodiSQL('video')
kodicursor = kodiconn.cursor()
emby_db = embydb.Embydb_Functions(embycursor)
kodi_db = kodidb.Kodidb_Functions(kodicursor)
doUtils = self.doUtils doUtils = self.doUtils
vnodes = self.vnodes vnodes = self.vnodes
@ -444,111 +531,33 @@ class LibrarySync(threading.Thread):
vnodes.clearProperties() vnodes.clearProperties()
totalnodes = 0 totalnodes = 0
# Set views for supported media type with embydb.GetEmbyDB() as emby_db:
mediatypes = [ with kodidb.GetKodiDB('video') as kodi_db:
'movie', for folderItem in result:
'show' self.processView(folderItem, kodi_db, emby_db, totalnodes)
]
for folderItem in result:
folder = folderItem.attrib
mediatype = folder['type']
if mediatype in mediatypes:
folderid = folder['key']
foldername = folder['title']
viewtype = folder['type']
# Get current media folders from emby database
view = emby_db.getView_byId(folderid)
try:
current_viewname = view[0]
current_viewtype = view[1]
current_tagid = view[2]
except TypeError:
self.logMsg("Creating viewid: %s in Emby database." % folderid, 1)
tagid = kodi_db.createTag(foldername)
# Create playlist for the video library
if mediatype in ['movies', 'tvshows', 'musicvideos']:
utils.playlistXSP(mediatype, foldername, viewtype)
# Create the video node
if mediatype in ['movies', 'tvshows', 'musicvideos', 'homevideos']:
vnodes.viewNode(totalnodes, foldername, mediatype, viewtype)
totalnodes += 1
# Add view to emby database
emby_db.addView(folderid, foldername, viewtype, tagid)
else: else:
self.logMsg(' '.join(( # Add video nodes listings
vnodes.singleNode(totalnodes,
"Favorite movies",
"movies",
"favourites")
totalnodes += 1
vnodes.singleNode(totalnodes,
"Favorite tvshows",
"tvshows",
"favourites")
totalnodes += 1
vnodes.singleNode(totalnodes,
"channels",
"movies",
"channels")
totalnodes += 1
# Save total
utils.window('Emby.nodes.total', str(totalnodes))
"Found viewid: %s" % folderid, # update views for all:
"viewname: %s" % current_viewname, self.views = emby_db.getAllViewInfo()
"viewtype: %s" % current_viewtype,
"tagid: %s" % current_tagid)), 2)
# View was modified, update with latest info
if current_viewname != foldername:
self.logMsg("viewid: %s new viewname: %s" % (folderid, foldername), 1)
tagid = kodi_db.createTag(foldername)
# Update view with new info
emby_db.updateView(foldername, tagid, folderid)
if mediatype != "music":
if emby_db.getView_byName(current_viewname) is None:
# The tag could be a combined view. Ensure there's no other tags
# with the same name before deleting playlist.
utils.playlistXSP(
mediatype, current_viewname, current_viewtype, True)
# Delete video node
if mediatype != "musicvideos":
vnodes.viewNode(
totalnodes,
current_viewname,
mediatype,
current_viewtype,
delete=True)
# Added new playlist
if mediatype in ['movies', 'tvshows', 'musicvideos']:
utils.playlistXSP(mediatype, foldername, viewtype)
# Add new video node
if mediatype != "musicvideos":
vnodes.viewNode(totalnodes, foldername, mediatype, viewtype)
totalnodes += 1
# Update items with new tag
items = emby_db.getItem_byView(folderid)
for item in items:
# Remove the "s" from viewtype for tags
kodi_db.updateTag(
current_tagid, tagid, item[0], current_viewtype[:-1])
else:
if mediatype != "music":
# Validate the playlist exists or recreate it
if mediatype in ['movies', 'tvshows', 'musicvideos']:
utils.playlistXSP(mediatype, foldername, viewtype)
# Create the video node if not already exists
if mediatype != "musicvideos":
vnodes.viewNode(totalnodes, foldername, mediatype, viewtype)
totalnodes += 1
else:
# Add video nodes listings
# vnodes.singleNode(totalnodes, "Favorite movies", "movies", "favourites")
# totalnodes += 1
# vnodes.singleNode(totalnodes, "Favorite tvshows", "tvshows", "favourites")
# totalnodes += 1
# vnodes.singleNode(totalnodes, "channels", "movies", "channels")
# totalnodes += 1
# Save total
utils.window('Emby.nodes.total', str(totalnodes))
# update views for all:
self.views = emby_db.getAllViewInfo()
self.logMsg("views saved: %s" % self.views, 1) self.logMsg("views saved: %s" % self.views, 1)
# commit changes to DB
embyconn.commit()
kodiconn.commit()
embyconn.close()
kodiconn.close()
def GetUpdatelist(self, xml, itemType, method, viewName, viewId, def GetUpdatelist(self, xml, itemType, method, viewName, viewId,
dontCheck=False): dontCheck=False):
@ -638,8 +647,8 @@ class LibrarySync(threading.Thread):
self.logMsg("Starting sync threads", 1) self.logMsg("Starting sync threads", 1)
getMetadataQueue = Queue.Queue() getMetadataQueue = Queue.Queue()
processMetadataQueue = Queue.Queue(maxsize=100) processMetadataQueue = Queue.Queue(maxsize=100)
getMetadataLock = threading.Lock() getMetadataLock = Lock()
processMetadataLock = threading.Lock() processMetadataLock = Lock()
# To keep track # To keep track
global getMetadataCount global getMetadataCount
getMetadataCount = 0 getMetadataCount = 0

View file

@ -1,17 +1,15 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################# ###############################################################################
import cProfile import cProfile
import inspect import inspect
import pstats import pstats
import sqlite3 import sqlite3
from datetime import datetime, time from datetime import datetime, time, timedelta
import time
import unicodedata import unicodedata
import xml.etree.ElementTree as etree import xml.etree.ElementTree as etree
from functools import wraps from functools import wraps
from datetime import datetime, timedelta
from calendar import timegm from calendar import timegm
import xbmc import xbmc
@ -20,7 +18,7 @@ import xbmcgui
import xbmcvfs import xbmcvfs
################################################################################################# ###############################################################################
addonName = xbmcaddon.Addon().getAddonInfo('name') addonName = xbmcaddon.Addon().getAddonInfo('name')