diff --git a/resources/lib/API.py b/resources/lib/API.py
index 239b4b89..5c9a6e24 100644
--- a/resources/lib/API.py
+++ b/resources/lib/API.py
@@ -332,7 +332,7 @@ class API():
if(data.get("ImageTags") != None and data.get("ImageTags").get(type) != None):
imageTag = data.get("ImageTags").get(type)
- if (data.get("Type") == "Episode" or data.get("Type") == "Season") and type=="Logo":
+ if (data.get("Type") == "Episode" or data.get("Type") == "Season" or data.get("Type") == "MusicAlbum") and type=="Logo":
imageTag = data.get("ParentLogoImageTag")
if (data.get("Type") == "Episode" or data.get("Type") == "Season") and type=="Art":
imageTag = data.get("ParentArtImageTag")
diff --git a/resources/lib/LibrarySync.py b/resources/lib/LibrarySync.py
index 9c47615d..3430b92a 100644
--- a/resources/lib/LibrarySync.py
+++ b/resources/lib/LibrarySync.py
@@ -22,6 +22,7 @@ from DownloadUtils import DownloadUtils
from ReadEmbyDB import ReadEmbyDB
from ReadKodiDB import ReadKodiDB
from WriteKodiVideoDB import WriteKodiVideoDB
+from WriteKodiMusicDB import WriteKodiMusicDB
from VideoNodes import VideoNodes
addondir = xbmc.translatePath(xbmcaddon.Addon(id='plugin.video.emby').getAddonInfo('profile'))
@@ -40,6 +41,7 @@ class LibrarySync():
startupDone = WINDOW.getProperty("startup") == "done"
syncInstallRunDone = addon.getSetting("SyncInstallRunDone") == "true"
+ performMusicSync = addon.getSetting("enableMusicSync") == "true"
dbSyncIndication = addon.getSetting("dbSyncIndication") == "true"
WINDOW.setProperty("SyncDatabaseRunning", "true")
@@ -56,16 +58,21 @@ class LibrarySync():
try:
completed = True
- connection = utils.KodiSQL()
+
+
+ ### BUILD VIDEO NODES LISTING ###
+ VideoNodes().buildVideoNodesListing()
+
+ ### PROCESS VIDEO LIBRARY ###
+
+ #create the sql connection to video db
+ connection = utils.KodiSQL("video")
cursor = connection.cursor()
#Add the special emby table
if not startupDone:
cursor.execute("CREATE TABLE IF NOT EXISTS emby(emby_id TEXT, kodi_id INTEGER, media_type TEXT, checksum TEXT, parent_id INTEGER)")
connection.commit()
-
- ### BUILD VIDEO NODES LISTING ###
- VideoNodes().buildVideoNodesListing()
# sync movies
self.MoviesFullSync(connection,cursor,pDialog)
@@ -82,6 +89,23 @@ class LibrarySync():
# sync musicvideos
self.MusicVideosFullSync(connection,cursor,pDialog)
+ #close sql connection
+ cursor.close()
+
+ ### PROCESS MUSIC LIBRARY ###
+ if performMusicSync:
+ #create the sql connection to music db
+ connection = utils.KodiSQL("music")
+ cursor = connection.cursor()
+
+ #Add the special emby table
+ if not startupDone:
+ cursor.execute("CREATE TABLE IF NOT EXISTS emby(emby_id TEXT, kodi_id INTEGER, media_type TEXT, checksum TEXT, parent_id INTEGER)")
+ connection.commit()
+
+ self.MusicFullSync(connection,cursor,pDialog)
+ cursor.close()
+
# set the install done setting
if(syncInstallRunDone == False and completed):
addon = xbmcaddon.Addon(id='plugin.video.emby') #force a new instance of the addon
@@ -97,7 +121,6 @@ class LibrarySync():
WINDOW.setProperty("SyncDatabaseRunning", "false")
utils.logMsg("Sync DB", "syncDatabase Exiting", 0)
- cursor.close()
if(pDialog != None):
pDialog.close()
@@ -336,6 +359,149 @@ class LibrarySync():
WINDOW.setProperty(kodiId,"deleted")
WriteKodiVideoDB().deleteItemFromKodiLibrary(kodiId, connection, cursor)
+ def MusicFullSync(self, connection,cursor, pDialog):
+
+ self.ProcessMusicArtists(connection,cursor,pDialog)
+ self.ProcessMusicAlbums(connection,cursor,pDialog)
+ self.ProcessMusicSongs(connection,cursor,pDialog)
+
+ ### commit all changes to database ###
+ connection.commit()
+
+ def ProcessMusicSongs(self,connection,cursor,pDialog):
+
+ allKodiSongIds = list()
+ allEmbySongIds = list()
+
+ allEmbySongs = ReadEmbyDB().getMusicSongs()
+ allKodiSongs = ReadKodiDB().getKodiMusicSongs(connection, cursor)
+
+ for kodisong in allKodiSongs:
+ allKodiSongIds.append(kodisong[1])
+
+ total = len(allEmbySongs) + 1
+ count = 1
+
+ #### PROCESS SONGS ADDS AND UPDATES ###
+ for item in allEmbySongs:
+
+ if (self.ShouldStop()):
+ return False
+
+ allEmbySongIds.append(item["Id"])
+
+ if(pDialog != None):
+ progressTitle = "Processing Music Songs (" + str(count) + " of " + str(total) + ")"
+ pDialog.update(0, "Emby for Kodi - Running Sync", progressTitle)
+ count += 1
+
+ kodiSong = None
+ for kodisong in allKodiSongs:
+ if kodisong[1] == item["Id"]:
+ kodiSong = kodisong
+
+ if kodiSong == None:
+ WriteKodiMusicDB().addOrUpdateSongToKodiLibrary(item["Id"],connection, cursor)
+ else:
+ if kodiSong[2] != API().getChecksum(item):
+ WriteKodiMusicDB().addOrUpdateSongToKodiLibrary(item["Id"],connection, cursor)
+
+ #### PROCESS DELETES #####
+ allEmbySongIds = set(allEmbySongIds)
+ for kodiId in allKodiSongIds:
+ if not kodiId in allEmbySongIds:
+ WINDOW.setProperty(kodiId,"deleted")
+ WriteKodiMusicDB().deleteItemFromKodiLibrary(kodiId, connection, cursor)
+
+ def ProcessMusicArtists(self,connection,cursor,pDialog):
+
+ allKodiArtistIds = list()
+ allEmbyArtistIds = list()
+
+ allEmbyArtists = ReadEmbyDB().getMusicArtists()
+ allKodiArtists = ReadKodiDB().getKodiMusicArtists(connection, cursor)
+
+ for kodiartist in allKodiArtists:
+ allKodiArtistIds.append(kodiartist[1])
+
+ total = len(allEmbyArtists) + 1
+ count = 1
+
+ #### PROCESS SONGS ADDS AND UPDATES ###
+ for item in allEmbyArtists:
+
+ if (self.ShouldStop()):
+ return False
+
+ allEmbyArtistIds.append(item["Id"])
+
+ if(pDialog != None):
+ progressTitle = "Processing Music Artists (" + str(count) + " of " + str(total) + ")"
+ pDialog.update(0, "Emby for Kodi - Running Sync", progressTitle)
+ count += 1
+
+ kodiArtist = None
+ for kodiartist in allKodiArtists:
+ if kodiartist[1] == item["Id"]:
+ kodiArtist = kodiartist
+
+ if kodiArtist == None:
+ WriteKodiMusicDB().addOrUpdateArtistToKodiLibrary(item["Id"],connection, cursor)
+ else:
+ if kodiArtist[2] != API().getChecksum(item):
+ WriteKodiMusicDB().addOrUpdateArtistToKodiLibrary(item["Id"],connection, cursor)
+
+ #### PROCESS DELETES #####
+ allEmbyArtistIds = set(allEmbyArtistIds)
+ for kodiId in allKodiArtistIds:
+ if not kodiId in allEmbyArtistIds:
+ WINDOW.setProperty(kodiId,"deleted")
+ WriteKodiMusicDB().deleteItemFromKodiLibrary(kodiId, connection, cursor)
+
+ def ProcessMusicAlbums(self,connection,cursor,pDialog):
+
+ allKodiAlbumIds = list()
+ allEmbyAlbumIds = list()
+
+ allEmbyAlbums = ReadEmbyDB().getMusicAlbums()
+ allKodiAlbums = ReadKodiDB().getKodiMusicAlbums(connection, cursor)
+
+ for kodialbum in allKodiAlbums:
+ allKodiAlbumIds.append(kodialbum[1])
+
+ total = len(allEmbyAlbums) + 1
+ count = 1
+
+ #### PROCESS SONGS ADDS AND UPDATES ###
+ for item in allEmbyAlbums:
+
+ if (self.ShouldStop()):
+ return False
+
+ allEmbyAlbumIds.append(item["Id"])
+
+ if(pDialog != None):
+ progressTitle = "Processing Music Albums (" + str(count) + " of " + str(total) + ")"
+ pDialog.update(0, "Emby for Kodi - Running Sync", progressTitle)
+ count += 1
+
+ kodiAlbum = None
+ for kodialbum in allKodiAlbums:
+ if kodialbum[1] == item["Id"]:
+ kodiAlbum = kodialbum
+
+ if kodiAlbum == None:
+ WriteKodiMusicDB().addOrUpdateAlbumToKodiLibrary(item["Id"],connection, cursor)
+ else:
+ if kodiAlbum[2] != API().getChecksum(item):
+ WriteKodiMusicDB().addOrUpdateAlbumToKodiLibrary(item["Id"],connection, cursor)
+
+ #### PROCESS DELETES #####
+ allEmbyAlbumIds = set(allEmbyAlbumIds)
+ for kodiId in allKodiAlbumIds:
+ if not kodiId in allEmbyAlbumIds:
+ WINDOW.setProperty(kodiId,"deleted")
+ WriteKodiMusicDB().deleteItemFromKodiLibrary(kodiId, connection, cursor)
def IncrementalSync(self, itemList):
#this will only perform sync for items received by the websocket
@@ -349,7 +515,7 @@ class LibrarySync():
pDialog = xbmcgui.DialogProgressBG()
pDialog.create('Emby for Kodi', 'Performing incremental sync...')
- connection = utils.KodiSQL()
+ connection = utils.KodiSQL("video")
cursor = connection.cursor()
try:
@@ -407,9 +573,25 @@ class LibrarySync():
### commit all changes to database ###
connection.commit()
-
- finally:
cursor.close()
+
+ ### PROCESS MUSIC LIBRARY ###
+ if performMusicSync:
+ connection = utils.KodiSQL("music")
+ cursor = connection.cursor()
+ for item in itemList:
+ MBitem = ReadEmbyDB().getItem(item)
+ if MBitem["Type"] == "MusicArtist":
+ WriteKodiMusicDB().addOrUpdateArtistToKodiLibrary(MBitem["Id"],connection, cursor)
+ if MBitem["Type"] == "MusicAlbum":
+ WriteKodiMusicDB().addOrUpdateAlbumToKodiLibraryToKodiLibrary(MBitem["Id"],connection, cursor)
+ if MBitem["Type"] == "Audio":
+ WriteKodiMusicDB().addOrUpdateSongToKodiLibraryToKodiLibrary(MBitem["Id"],connection, cursor)
+ connection.commit()
+ cursor.close()
+
+ finally:
+
xbmc.executebuiltin("UpdateLibrary(video)")
WINDOW.setProperty("SyncDatabaseRunning", "false")
diff --git a/resources/lib/ReadEmbyDB.py b/resources/lib/ReadEmbyDB.py
index 3d4e7680..6a98af91 100644
--- a/resources/lib/ReadEmbyDB.py
+++ b/resources/lib/ReadEmbyDB.py
@@ -65,7 +65,83 @@ class ReadEmbyDB():
result = newResult
return result
+
+ def getMusicArtists(self, itemList = []):
+ result = None
+ doUtils = DownloadUtils()
+
+ #only get basic info for our sync-compares
+ url = "{server}/Artists?Fields=Name,CumulativeRunTimeTicks,Etag&Recursive=true&format=json"
+
+ jsonData = doUtils.downloadUrl(url)
+ if (jsonData == ""):
+ return result
+
+ if (jsonData[u'Items'] != ""):
+ result = jsonData[u'Items']
+
+ # Work around to only return items from the given list
+ if (result != None and len(result) > 0 and len(itemList) > 0):
+ newResult = []
+ for item in result:
+ if (item[u'Id'] in itemList):
+ newResult.append(item)
+ result = newResult
+
+ return result
+
+ def getMusicSongs(self, itemList = []):
+
+ result = None
+ doUtils = DownloadUtils()
+
+ #only get basic info for our sync-compares
+ url = "{server}/mediabrowser/Users/{UserId}/Items?Fields=Name,CumulativeRunTimeTicks,Etag&Recursive=true&IncludeItemTypes=Audio&format=json"
+
+ jsonData = doUtils.downloadUrl(url)
+ if (jsonData == ""):
+ return result
+
+ if (jsonData[u'Items'] != ""):
+ result = jsonData[u'Items']
+
+ # Work around to only return items from the given list
+ if (result != None and len(result) > 0 and len(itemList) > 0):
+ newResult = []
+ for item in result:
+ if (item[u'Id'] in itemList):
+ newResult.append(item)
+ result = newResult
+
+ return result
+
+ def getMusicAlbums(self, itemList = []):
+
+ result = None
+ doUtils = DownloadUtils()
+
+ #only get basic info for our sync-compares
+ url = "{server}/mediabrowser/Users/{UserId}/Items?Fields=Name,CumulativeRunTimeTicks,Etag&Recursive=true&IncludeItemTypes=MusicAlbum&format=json"
+
+ jsonData = doUtils.downloadUrl(url)
+ if (jsonData == ""):
+ return result
+
+ if (jsonData[u'Items'] != ""):
+ result = jsonData[u'Items']
+
+ # Work around to only return items from the given list
+ if (result != None and len(result) > 0 and len(itemList) > 0):
+ newResult = []
+ for item in result:
+ if (item[u'Id'] in itemList):
+ newResult.append(item)
+ result = newResult
+
+ return result
+
+
def getItem(self, id):
result = None
diff --git a/resources/lib/ReadKodiDB.py b/resources/lib/ReadKodiDB.py
index 5393872f..a12b5feb 100644
--- a/resources/lib/ReadKodiDB.py
+++ b/resources/lib/ReadKodiDB.py
@@ -61,4 +61,23 @@ class ReadKodiDB():
else:
return None
-
\ No newline at end of file
+ def getKodiMusicArtists(self, connection, cursor):
+ #returns all artists in Kodi db
+ cursor.execute("SELECT kodi_id, emby_id, checksum FROM emby WHERE media_type='artist'")
+ allartists = cursor.fetchall()
+ #this will return a list with tuples of all items returned from the database
+ return allartists
+
+ def getKodiMusicAlbums(self, connection, cursor):
+ #returns all artists in Kodi db
+ cursor.execute("SELECT kodi_id, emby_id, checksum FROM emby WHERE media_type='album'")
+ allalbums = cursor.fetchall()
+ #this will return a list with tuples of all items returned from the database
+ return allalbums
+
+ def getKodiMusicSongs(self, connection, cursor):
+ #returns all songs in Kodi db
+ cursor.execute("SELECT kodi_id, emby_id, checksum FROM emby WHERE media_type='song'")
+ allsongs = cursor.fetchall()
+ #this will return a list with tuples of all items returned from the database
+ return allsongs
\ No newline at end of file
diff --git a/resources/lib/Utils.py b/resources/lib/Utils.py
index 86587874..7d3daba5 100644
--- a/resources/lib/Utils.py
+++ b/resources/lib/Utils.py
@@ -48,12 +48,18 @@ def convertEncoding(data):
except:
return data
-def KodiSQL():
- connection = sqlite3.connect(getKodiDBPath())
+def KodiSQL(type="video"):
+
+ if type == "music":
+ dbPath = getKodiMusicDBPath()
+ else:
+ dbPath = getKodiVideoDBPath()
+
+ connection = sqlite3.connect(dbPath)
return connection
-def getKodiDBPath():
+def getKodiVideoDBPath():
if xbmc.getInfoLabel("System.BuildVersion").startswith("13"):
#gotham
dbVersion = "78"
@@ -68,6 +74,22 @@ def getKodiDBPath():
return dbPath
+def getKodiMusicDBPath():
+ if xbmc.getInfoLabel("System.BuildVersion").startswith("13"):
+ #gotham
+ dbVersion = "48"
+ if xbmc.getInfoLabel("System.BuildVersion").startswith("15"):
+ #isengard
+ dbVersion = "52"
+ else:
+ #helix
+ dbVersion = "48"
+
+ dbPath = xbmc.translatePath("special://profile/Database/MyMusic" + dbVersion + ".db")
+
+ return dbPath
+
+
def checkAuthentication():
#check authentication
if addonSettings.getSetting('username') != "" and addonSettings.getSetting('ipaddress') != "":
diff --git a/resources/lib/WriteKodiMusicDB.py b/resources/lib/WriteKodiMusicDB.py
new file mode 100644
index 00000000..7aa0e321
--- /dev/null
+++ b/resources/lib/WriteKodiMusicDB.py
@@ -0,0 +1,447 @@
+#################################################################################################
+# WriteKodiVideoDB
+#################################################################################################
+
+
+import xbmc
+import xbmcgui
+import xbmcaddon
+import xbmcvfs
+import json
+import urllib
+import sqlite3
+import os
+from decimal import Decimal
+
+from DownloadUtils import DownloadUtils
+from PlayUtils import PlayUtils
+from ReadKodiDB import ReadKodiDB
+from ReadEmbyDB import ReadEmbyDB
+from API import API
+import Utils as utils
+
+from xml.etree.ElementTree import Element, SubElement, Comment, tostring
+from xml.etree import ElementTree
+from xml.dom import minidom
+import xml.etree.cElementTree as ET
+
+addon = xbmcaddon.Addon(id='plugin.video.emby')
+addondir = xbmc.translatePath(addon.getAddonInfo('profile'))
+dataPath = os.path.join(addondir,",musicfiles")
+
+
+class WriteKodiMusicDB():
+
+
+
+ def updatePlayCountFromKodi(self, id, type, playcount=0):
+ #when user marks item watched from kodi interface update this in Emby
+
+ utils.logMsg("Emby", "updatePlayCountFromKodi Called")
+ connection = utils.KodiSQL()
+ cursor = connection.cursor()
+ cursor.execute("SELECT emby_id FROM emby WHERE media_type=? AND kodi_id=?",(type,id))
+
+ emby_id = cursor.fetchone()[0]
+ cursor.close
+
+ if(emby_id != None):
+ addon = xbmcaddon.Addon(id='plugin.video.emby')
+ downloadUtils = DownloadUtils()
+ watchedurl = "{server}/mediabrowser/Users/{UserId}/PlayedItems/%s" % emby_id
+ if playcount != 0:
+ downloadUtils.downloadUrl(watchedurl, type="POST")
+ else:
+ downloadUtils.downloadUrl(watchedurl, type="DELETE")
+
+ def addOrUpdateArtistToKodiLibrary( self, embyId ,connection, cursor):
+
+ addon = xbmcaddon.Addon(id='plugin.video.emby')
+ WINDOW = xbmcgui.Window(10000)
+ username = WINDOW.getProperty('currUser')
+ userid = WINDOW.getProperty('userId%s' % username)
+ server = WINDOW.getProperty('server%s' % username)
+ downloadUtils = DownloadUtils()
+
+ MBitem = ReadEmbyDB().getFullItem(embyId)
+
+ # If the item already exist in the local Kodi DB we'll perform a full item update
+ # If the item doesn't exist, we'll add it to the database
+
+ cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?",(MBitem["Id"],))
+ result = cursor.fetchone()
+ if result != None:
+ artistid = result[0]
+ else:
+ artistid = None
+
+
+ #### The artist details #########
+ name = utils.convertEncoding(MBitem["Name"])
+ musicBrainsId = None
+ if MBitem.get("ProviderIds"):
+ if MBitem.get("ProviderIds").get("MusicBrainzArtist"):
+ musicBrainsId = MBitem.get("ProviderIds").get("MusicBrainzArtist")
+
+ genres = " / ".join(MBitem.get("Genres"))
+ bio = utils.convertEncoding(API().getOverview(MBitem))
+ dateadded = None
+ if MBitem.get("DateCreated"):
+ dateadded = MBitem["DateCreated"].split('.')[0].replace('T', " ")
+
+ #safety check: does the musicbrainzartistId already exist?
+ cursor.execute("SELECT idArtist FROM artist WHERE strMusicBrainzArtistID = ?",(musicBrainsId,))
+ result = cursor.fetchone()
+ if result != None:
+ artistid = result[0]
+ else:
+ artistid = None
+
+ ##### ADD THE ARTIST ############
+ if artistid == None:
+
+ utils.logMsg("ADD artist to Kodi library","Id: %s - Title: %s" % (embyId, name))
+
+ #create the artist
+ cursor.execute("select coalesce(max(idArtist),0) as artistid from artist")
+ artistid = cursor.fetchone()[0]
+ artistid = artistid + 1
+ pathsql="insert into artist(idArtist, strArtist, strMusicBrainzArtistID, strGenres, strBiography, dateAdded) values(?, ?, ?, ?, ?, ?)"
+ cursor.execute(pathsql, (artistid, name, musicBrainsId, genres, bio, dateadded))
+
+ #create the reference in emby table
+ pathsql = "INSERT into emby(emby_id, kodi_id, media_type, checksum) values(?, ?, ?, ?)"
+ cursor.execute(pathsql, (MBitem["Id"], artistid, "artist", API().getChecksum(MBitem)))
+
+ #### UPDATE THE ARTIST #####
+ else:
+ utils.logMsg("UPDATE artist to Kodi library","Id: %s - Title: %s" % (embyId, name))
+ pathsql="update artist SET strArtist = ?, strMusicBrainzArtistID = ?, strGenres = ?, strBiography = ?, dateAdded = ? WHERE idArtist = ?"
+ cursor.execute(pathsql, (name, musicBrainsId, genres, bio, dateadded, artistid))
+
+ #update the checksum in emby table
+ cursor.execute("UPDATE emby SET checksum = ? WHERE emby_id = ?", (API().getChecksum(MBitem),MBitem["Id"]))
+
+ #update artwork
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), artistid, "artist", "thumb", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), artistid, "artist", "poster", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Banner"), artistid, "artist", "banner", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Logo"), artistid, "artist", "clearlogo", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Art"), artistid, "artist", "clearart", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Thumb"), artistid, "artist", "landscape", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Disc"), artistid, "artist", "discart", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Backdrop"), artistid, "artist", "fanart", cursor)
+
+ def addOrUpdateAlbumToKodiLibrary( self, embyId ,connection, cursor, isSingle=False):
+
+ addon = xbmcaddon.Addon(id='plugin.video.emby')
+ WINDOW = xbmcgui.Window(10000)
+ username = WINDOW.getProperty('currUser')
+ userid = WINDOW.getProperty('userId%s' % username)
+ server = WINDOW.getProperty('server%s' % username)
+ downloadUtils = DownloadUtils()
+
+ MBitem = ReadEmbyDB().getFullItem(embyId)
+
+ # If the item already exist in the local Kodi DB we'll perform a full item update
+ # If the item doesn't exist, we'll add it to the database
+
+ cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?",(MBitem["Id"],))
+ result = cursor.fetchone()
+ if result != None:
+ albumid = result[0]
+ else:
+ albumid = None
+
+
+ #### The album details #########
+ name = utils.convertEncoding(MBitem["Name"])
+
+ MBartists = []
+ for item in MBitem.get("AlbumArtists"):
+ MBartists.append(item["Name"])
+
+ artists = " / ".join(MBartists)
+ year = MBitem.get("ProductionYear")
+ musicBrainsId = None
+ if MBitem.get("ProviderIds"):
+ if MBitem.get("ProviderIds").get("MusicBrainzAlbum"):
+ musicBrainsId = MBitem.get("ProviderIds").get("MusicBrainzAlbum")
+
+ genres = " / ".join(MBitem.get("Genres"))
+ bio = utils.convertEncoding(API().getOverview(MBitem))
+ dateadded = None
+ if MBitem.get("DateCreated"):
+ dateadded = MBitem["DateCreated"].split('.')[0].replace('T', " ")
+
+ if isSingle:
+ releasetype = "single"
+ name = None
+ else:
+ releasetype = "album"
+
+ ##### ADD THE ALBUM ############
+ if albumid == None:
+
+ utils.logMsg("ADD album to Kodi library","Id: %s - Title: %s" % (embyId, name))
+
+ #create the album
+ cursor.execute("select coalesce(max(idAlbum),0) as albumid from album")
+ albumid = cursor.fetchone()[0]
+ albumid = albumid + 1
+ pathsql="insert into album(idAlbum, strAlbum, strMusicBrainzAlbumID, strArtists, iYear, strGenres, dateAdded) values(?, ?, ?, ?, ?, ?, ?)"
+ cursor.execute(pathsql, (albumid, name, musicBrainsId, artists, year, genres, dateadded))
+
+ #create the reference in emby table
+ pathsql = "INSERT into emby(emby_id, kodi_id, media_type, checksum) values(?, ?, ?, ?)"
+ cursor.execute(pathsql, (MBitem["Id"], albumid, "album", API().getChecksum(MBitem)))
+
+ #### UPDATE THE ALBUM #####
+ else:
+ utils.logMsg("UPDATE album to Kodi library","Id: %s - Title: %s" % (embyId, name))
+ pathsql="update album SET strAlbum = ?, strMusicBrainzAlbumID = ?, strArtists = ?, strGenres = ?, iYear = ?, dateAdded = ? WHERE idAlbum = ?"
+ cursor.execute(pathsql, (name, musicBrainsId, artists, genres, year, dateadded, albumid))
+
+ #update the checksum in emby table
+ cursor.execute("UPDATE emby SET checksum = ? WHERE emby_id = ?", (API().getChecksum(MBitem),MBitem["Id"]))
+
+ #update artwork
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), albumid, "album", "thumb", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "BoxRear"), albumid, "album", "poster", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Banner"), albumid, "album", "banner", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Logo"), albumid, "album", "clearlogo", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Art"), albumid, "album", "clearart", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Thumb"), albumid, "album", "landscape", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Disc"), albumid, "album", "discart", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Backdrop"), albumid, "album", "fanart", cursor)
+
+ #link album to artist
+ artistid = None
+ for artist in MBitem.get("AlbumArtists"):
+ cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?",(artist["Id"],))
+ result = cursor.fetchone()
+ if result:
+ artistid = result[0]
+ sql="INSERT OR REPLACE into album_artist(idArtist, idAlbum, strArtist) values(?, ?, ?)"
+ cursor.execute(sql, (artistid, albumid, artist["Name"]))
+ #update discography
+ sql="INSERT OR REPLACE into discography(idArtist, strAlbum, strYear) values(?, ?, ?)"
+ cursor.execute(sql, (artistid, name, str(year)))
+
+ #return the album id
+ return albumid
+
+ def addOrUpdateSongToKodiLibrary( self, embyId ,connection, cursor):
+
+ addon = xbmcaddon.Addon(id='plugin.video.emby')
+ WINDOW = xbmcgui.Window(10000)
+ username = WINDOW.getProperty('currUser')
+ userid = WINDOW.getProperty('userId%s' % username)
+ server = WINDOW.getProperty('server%s' % username)
+ downloadUtils = DownloadUtils()
+
+ MBitem = ReadEmbyDB().getFullItem(embyId)
+
+ timeInfo = API().getTimeInfo(MBitem)
+ userData=API().getUserData(MBitem)
+
+ # If the item already exist in the local Kodi DB we'll perform a full item update
+ # If the item doesn't exist, we'll add it to the database
+
+ cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?",(MBitem["Id"],))
+ result = cursor.fetchone()
+ if result != None:
+ songid = result[0]
+ else:
+ songid = None
+
+
+ #### The song details #########
+ name = utils.convertEncoding(MBitem["Name"])
+ musicBrainzId = None
+ if MBitem.get("ProviderIds"):
+ if MBitem.get("ProviderIds").get("MusicBrainzTrackId"):
+ musicBrainzId = MBitem.get("ProviderIds").get("MusicBrainzTrackId")
+
+ genres = " / ".join(MBitem.get("Genres"))
+ artists = " / ".join(MBitem.get("Artists"))
+ track = MBitem.get("IndexNumber")
+ duration = int(timeInfo.get('Duration'))*60
+ year = MBitem.get("ProductionYear")
+ bio = utils.convertEncoding(API().getOverview(MBitem))
+ dateadded = None
+ if MBitem.get("DateCreated"):
+ dateadded = MBitem["DateCreated"].split('.')[0].replace('T', " ")
+
+ if userData.get("LastPlayedDate") != None:
+ lastplayed = userData.get("LastPlayedDate")
+ else:
+ lastplayed = None
+
+ playcount = None
+ if userData.get("PlayCount"):
+ playcount = int(userData.get("PlayCount"))
+
+ #get the album
+ albumid = None
+ if MBitem.get("AlbumId"):
+ cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?",(MBitem.get("AlbumId"),))
+ result = cursor.fetchone()
+ if result:
+ albumid = result[0]
+ if not albumid:
+ #no album = single in kodi, we need to create a single album for that
+ albumid = self.addOrUpdateAlbumToKodiLibrary(MBitem["Id"],connection, cursor, True)
+
+ playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
+ #for transcoding we need to create a fake strm file because I couldn't figure out how to set a http or plugin path in the music DB
+ if playurl.startswith("http"):
+ #create fake strm file
+ filename = item["Id"] + ".strm"
+ path = dataPath
+ strmFile = os.path.join(dataPath,filename)
+ text_file = open(strmFile, "w")
+ text_file.writelines(playurl)
+ text_file.close()
+ else:
+ #use the direct file path
+ if "\\" in playurl:
+ filename = playurl.rsplit("\\",1)[-1]
+ path = playurl.replace(filename,"")
+ elif "/" in playurl:
+ filename = playurl.rsplit("/",1)[-1]
+ path = playurl.replace(filename,"")
+
+ #get the path
+ cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?",(path,))
+ result = cursor.fetchone()
+ if result != None:
+ pathid = result[0]
+ else:
+ cursor.execute("select coalesce(max(idPath),0) as pathid from path")
+ pathid = cursor.fetchone()[0]
+ pathid = pathid + 1
+ pathsql = "insert into path(idPath, strPath) values(?, ?)"
+ cursor.execute(pathsql, (pathid,path))
+
+
+ ##### ADD THE SONG ############
+ if songid == None:
+
+ utils.logMsg("ADD song to Kodi library","Id: %s - Title: %s" % (embyId, name))
+
+ #create the song
+ cursor.execute("select coalesce(max(idSong),0) as songid from song")
+ songid = cursor.fetchone()[0]
+ songid = songid + 1
+ pathsql="insert into song(idSong, idAlbum, idPath, strArtists, strGenres, strTitle, iTrack, iDuration, iYear, strFileName, strMusicBrainzTrackID, iTimesPlayed, lastplayed) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
+ cursor.execute(pathsql, (songid, albumid, pathid, artists, genres, name, track, duration, year, filename, musicBrainzId, playcount, lastplayed))
+
+ #create the reference in emby table
+ pathsql = "INSERT into emby(emby_id, kodi_id, media_type, checksum) values(?, ?, ?, ?)"
+ cursor.execute(pathsql, (MBitem["Id"], songid, "song", API().getChecksum(MBitem)))
+
+ #### UPDATE THE SONG #####
+ else:
+ utils.logMsg("UPDATE song to Kodi library","Id: %s - Title: %s" % (embyId, name))
+ pathsql="update song SET idAlbum=?, strArtists=?, strGenres=?, strTitle=?, iTrack=?, iDuration=?, iYear=?, strFileName=?, strMusicBrainzTrackID=?, iTimesPlayed=?, lastplayed=? WHERE idSong = ?"
+ cursor.execute(pathsql, (albumid, artists, genres, name, track, duration, year, filename, musicBrainzId, playcount, lastplayed, songid))
+
+ #update the checksum in emby table
+ cursor.execute("UPDATE emby SET checksum = ? WHERE emby_id = ?", (API().getChecksum(MBitem),MBitem["Id"]))
+
+ #add genres
+ self.AddGenresToMedia(songid, MBitem.get("Genres"), "song", cursor)
+
+ #link song to album
+ if albumid:
+ sql="INSERT OR REPLACE into albuminfosong(idAlbumInfoSong, idAlbumInfo, iTrack, strTitle, iDuration) values(?, ?, ?, ?, ?)"
+ cursor.execute(sql, (songid, albumid, track, name, duration))
+
+ #link song to artist
+ for artist in MBitem.get("ArtistItems"):
+ cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?",(artist["Id"],))
+ result = cursor.fetchone()
+ if result:
+ artistid = result[0]
+ sql="INSERT OR REPLACE into song_artist(idArtist, idSong, strArtist) values(?, ?, ?)"
+ cursor.execute(sql, (artistid, songid, artist["Name"]))
+
+ #update artwork
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), songid, "song", "thumb", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), songid, "song", "poster", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Banner"), songid, "song", "banner", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Logo"), songid, "song", "clearlogo", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Art"), songid, "song", "clearart", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Thumb"), songid, "song", "landscape", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Disc"), songid, "song", "discart", cursor)
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Backdrop"), songid, "song", "fanart", cursor)
+
+ def deleteItemFromKodiLibrary(self, id, connection, cursor ):
+
+ cursor.execute("SELECT kodi_id, media_type FROM emby WHERE emby_id=?", (id,))
+ result = cursor.fetchone()
+ if result:
+ kodi_id = result[0]
+ media_type = result[1]
+ if media_type == "movie":
+ utils.logMsg("deleting movie from Kodi library --> ",id)
+ cursor.execute("DELETE FROM movie WHERE idMovie = ?", (kodi_id,))
+ if media_type == "episode":
+ utils.logMsg("deleting episode from Kodi library --> ",id)
+ cursor.execute("DELETE FROM episode WHERE idEpisode = ?", (kodi_id,))
+ if media_type == "tvshow":
+ utils.logMsg("deleting tvshow from Kodi library --> ",id)
+ cursor.execute("DELETE FROM tvshow WHERE idShow = ?", (kodi_id,))
+ if media_type == "musicvideo":
+ utils.logMsg("deleting musicvideo from Kodi library --> ",id)
+ cursor.execute("DELETE FROM musicvideo WHERE idMVideo = ?", (kodi_id,))
+
+ #delete the record in emby table
+ cursor.execute("DELETE FROM emby WHERE emby_id = ?", (id,))
+
+ def addOrUpdateArt(self, imageUrl, kodiId, mediaType, imageType, cursor):
+ updateDone = False
+ if imageUrl:
+ cursor.execute("SELECT url FROM art WHERE media_id = ? AND media_type = ? AND type = ?", (kodiId, mediaType, imageType))
+ result = cursor.fetchone()
+ if(result == None):
+ utils.logMsg("ArtworkSync", "Adding Art Link for kodiId: " + str(kodiId) + " (" + imageUrl + ")")
+ cursor.execute("INSERT INTO art(media_id, media_type, type, url) values(?, ?, ?, ?)", (kodiId, mediaType, imageType, imageUrl))
+ else:
+ url = result[0];
+ if(url != imageUrl):
+ utils.logMsg("ArtworkSync", "Updating Art Link for kodiId: " + str(kodiId) + " (" + url + ") -> (" + imageUrl + ")")
+ cursor.execute("UPDATE art set url = ? WHERE media_id = ? AND media_type = ? AND type = ?", (imageUrl, kodiId, mediaType, imageType))
+
+ def AddGenresToMedia(self, id, genres, mediatype, cursor):
+
+ if genres:
+
+ for genre in genres:
+
+ idGenre = None
+ cursor.execute("SELECT idGenre as idGenre FROM genre WHERE strGenre = ?",(genre,))
+ result = cursor.fetchone()
+ if result != None:
+ idGenre = result[0]
+ #create genre
+ if idGenre == None:
+ cursor.execute("select coalesce(max(idGenre),0) as idGenre from genre")
+ idGenre = cursor.fetchone()[0]
+ idGenre = idGenre + 1
+ sql="insert into genre(idGenre, strGenre) values(?, ?)"
+ cursor.execute(sql, (idGenre,genre))
+
+ #assign genre to item
+ if mediatype == "album":
+ sql="INSERT OR REPLACE into album_genre(idGenre, idAlbum) values(?, ?)"
+ cursor.execute(sql, (idGenre,id))
+ elif mediatype == "song":
+ sql="INSERT OR REPLACE into song_genre(idGenre, idSong) values(?, ?)"
+ cursor.execute(sql, (idGenre,id))
+ else:
+ return
+
+
+
diff --git a/resources/settings.xml b/resources/settings.xml
index ec3d8736..96677c2c 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -18,6 +18,7 @@
+