diff --git a/resources/lib/PlexAPI.py b/resources/lib/PlexAPI.py
index 5d21ae98..860c48eb 100644
--- a/resources/lib/PlexAPI.py
+++ b/resources/lib/PlexAPI.py
@@ -1420,8 +1420,8 @@ class API():
# localtime = time.strftime('%H:%M', date_time)
# return localtime + ' ' + localdate
try:
- DATEFORMAT = xbmc.getRegion('dateshort')
- TIMEFORMAT = xbmc.getRegion('meridiem')
+ # DATEFORMAT = xbmc.getRegion('dateshort')
+ # TIMEFORMAT = xbmc.getRegion('meridiem')
date_time = time.localtime(float(stamp))
localdate = time.strftime('%Y-%m-%d %H:%M:%S', date_time)
except:
@@ -1447,7 +1447,7 @@ class API():
"""
Returns the Plex key such as '246922' as a string
"""
- return self.item.attrib.get('ratingKey', '')
+ return self.item.attrib.get('ratingKey', None)
def getKey(self):
"""
@@ -1491,7 +1491,7 @@ class API():
try:
playcount = int(item['viewCount'])
- except KeyError:
+ except:
playcount = None
if playcount:
@@ -1499,9 +1499,14 @@ class API():
try:
lastPlayedDate = self.DateToKodi(int(item['lastViewedAt']))
- except KeyError:
+ except:
lastPlayedDate = None
+ try:
+ userrating = int(item['userRating'])
+ except:
+ userrating = None
+
resume, runtime = self.getRuntime()
return {
'Favorite': favorite,
@@ -1510,7 +1515,8 @@ class API():
'LastPlayedDate': lastPlayedDate,
'Resume': resume,
'Runtime': runtime,
- 'Rating': rating
+ 'Rating': rating,
+ 'UserRating': userrating
}
def getPeople(self):
diff --git a/resources/lib/PlexFunctions.py b/resources/lib/PlexFunctions.py
index 1a5b9333..c95457b8 100644
--- a/resources/lib/PlexFunctions.py
+++ b/resources/lib/PlexFunctions.py
@@ -3,10 +3,8 @@ from urllib import urlencode
from ast import literal_eval
from urlparse import urlparse, parse_qs
import re
-import json
from xbmcaddon import Addon
-import xbmc
import downloadutils
from utils import logMsg, settings
@@ -35,7 +33,10 @@ def GetItemClassFromType(itemType):
'movie': 'Movies',
'episodes': 'TVShows',
'episode': 'TVShows',
- 'show': 'TVShows'
+ 'show': 'TVShows',
+ 'artist': 'Music',
+ 'album': 'Music',
+ 'track': 'Music'
}
return classes[itemType]
@@ -97,7 +98,10 @@ def GetMethodFromPlexType(plexType):
'movie': 'add_update',
'episode': 'add_updateEpisode',
'show': 'add_update',
- 'season': 'add_updateSeason'
+ 'season': 'add_updateSeason',
+ 'track': 'add_updateSong',
+ 'album': 'add_updateAlbum',
+ 'artist': 'add_updateArtist'
}
return methods[plexType]
@@ -199,17 +203,22 @@ def GetAllPlexChildren(key):
return xml
-def GetPlexSectionResults(viewId, headerOptions={}):
+def GetPlexSectionResults(viewId, args=None):
"""
Returns a list (XML API dump) of all Plex items in the Plex
section with key = viewId.
+ Input:
+ args: optional dict to be urlencoded
+
Returns None if something went wrong
"""
result = []
url = "{server}/library/sections/%s/all" % viewId
- result = downloadutils.DownloadUtils().downloadUrl(
- url, headerOptions=headerOptions)
+ if args:
+ url += "?" + urlencode(args)
+
+ result = downloadutils.DownloadUtils().downloadUrl(url)
try:
result.tag
diff --git a/resources/lib/artwork.py b/resources/lib/artwork.py
index 1b039b30..f77022fd 100644
--- a/resources/lib/artwork.py
+++ b/resources/lib/artwork.py
@@ -270,8 +270,6 @@ class Artwork():
def CacheTexture(self, url):
# Cache a single image url to the texture cache
if url and self.enableTextureCache:
- self.logMsg("Processing: %s" % url, 2)
-
if(self.imageCacheLimitThreads == 0 or self.imageCacheLimitThreads == None):
#Add image to texture cache by simply calling it at the http endpoint
@@ -389,8 +387,6 @@ class Artwork():
except TypeError: # Add the artwork
cacheimage = True
- self.logMsg("Adding Art Link for kodiId: %s (%s)" % (kodiId, imageUrl), 2)
-
query = (
'''
INSERT INTO art(media_id, media_type, type, url)
@@ -409,10 +405,6 @@ class Artwork():
imageType in ("fanart", "poster")):
# Delete current entry before updating with the new one
self.deleteCachedArtwork(url)
-
- self.logMsg(
- "Updating Art url for %s kodiId: %s (%s) -> (%s)"
- % (imageType, kodiId, url, imageUrl), 1)
query = ' '.join((
diff --git a/resources/lib/itemtypes.py b/resources/lib/itemtypes.py
index d8a677d2..091063f2 100644
--- a/resources/lib/itemtypes.py
+++ b/resources/lib/itemtypes.py
@@ -19,6 +19,7 @@ import kodidb_functions as kodidb
import read_embyserver as embyserver
import musicutils as musicutils
import PlexAPI
+from PlexFunctions import GetPlexMetadata
##################################################################################################
@@ -26,13 +27,15 @@ import PlexAPI
@utils.logging
class Items(object):
"""
- Items to be called with "with Items as xxx:" to ensure that __enter__
+ Items to be called with "with Items() as xxx:" to ensure that __enter__
method is called (opens db connections)
+
+ Input:
+ kodiType: optional argument; e.g. 'video' or 'music'
"""
def __init__(self):
self.doUtils = downloadutils.DownloadUtils()
-
self.kodiversion = int(xbmc.getInfoLabel("System.BuildVersion")[:2])
self.directpath = utils.settings('useDirectPaths') == "1"
self.music_enabled = utils.settings('enableMusic') == "true"
@@ -283,7 +286,6 @@ class Movies(Items):
self.add_updateBoxset(boxset)
def add_update(self, item, viewtag=None, viewid=None):
- self.logMsg("Entering add_update", 1)
# Process single movie
kodicursor = self.kodicursor
emby_db = self.emby_db
@@ -291,7 +293,8 @@ class Movies(Items):
artwork = self.artwork
API = PlexAPI.API(item)
- # If the item already exist in the local Kodi DB we'll perform a full item update
+ # 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
update_item = True
itemid = API.getRatingKey()
@@ -306,16 +309,14 @@ class Movies(Items):
pathid = emby_dbitem[2]
except TypeError:
- update_item = False
- self.logMsg("movieid: %s not found." % itemid, 2)
# movieid
+ update_item = False
kodicursor.execute("select coalesce(max(idMovie),0) from movie")
movieid = kodicursor.fetchone()[0] + 1
if not viewtag or not viewid:
# Get view tag from emby
viewtag, viewid, mediatype = self.emby.getView_embyId(itemid)
- self.logMsg("View tag found: %s" % viewtag, 2)
# fileId information
checksum = API.getChecksum()
@@ -349,7 +350,6 @@ class Movies(Items):
studio = studios[0]
except IndexError:
studio = None
- self.logMsg("Retrieved metadata for %s" % itemid, 2)
# Find one trailer
trailer = None
@@ -470,33 +470,24 @@ class Movies(Items):
# Process cast
people = API.getPeopleList()
kodi_db.addPeople(movieid, people, "movie")
- self.logMsg('People added', 2)
# Process genres
kodi_db.addGenres(movieid, genres, "movie")
- self.logMsg('Genres added', 2)
# Process artwork
allartworks = API.getAllArtwork()
- self.logMsg('Artwork processed', 2)
artwork.addArtwork(allartworks, movieid, "movie", kodicursor)
- self.logMsg('Artwork added', 2)
# Process stream details
streams = API.getMediaStreams()
- self.logMsg('Streames processed', 2)
kodi_db.addStreams(fileid, streams, runtime)
- self.logMsg('Streames added', 2)
# Process studios
kodi_db.addStudios(movieid, studios, "movie")
- self.logMsg('Studios added', 2)
# Process tags: view, emby tags
tags = [viewtag]
# tags.extend(item['Tags'])
# if userdata['Favorite']:
# tags.append("Favorite movies")
kodi_db.addTags(movieid, tags, "movie")
- self.logMsg('Tags added', 2)
# Process playstates
kodi_db.addPlaystate(fileid, resume, runtime, playcount, dateplayed)
- self.logMsg('Done processing %s' % itemid, 2)
def remove(self, itemid):
# Remove movieid, fileid, emby reference
@@ -900,11 +891,6 @@ class TVShows(Items):
artwork = self.artwork
API = PlexAPI.API(item)
- # if utils.settings('syncEmptyShows') == "false" and not item['RecursiveItemCount']:
- # self.logMsg("Skipping empty show: %s" % item['Name'], 1)
- # return
- # 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
update_item = True
itemid = API.getRatingKey()
if not itemid:
@@ -917,8 +903,6 @@ class TVShows(Items):
except TypeError:
update_item = False
- self.logMsg("View tag found: %s" % viewtag, 2)
-
# fileId information
checksum = API.getChecksum()
@@ -937,7 +921,7 @@ class TVShows(Items):
except IndexError:
studio = None
- ##### GET THE FILE AND PATH #####
+ # GET THE FILE AND PATH #####
playurl = API.getKey()
if self.directpath:
@@ -971,8 +955,7 @@ class TVShows(Items):
toplevelpath = "plugin://plugin.video.plexkodiconnect.tvshows/"
path = "%s%s/" % (toplevelpath, itemid)
-
- ##### UPDATE THE TVSHOW #####
+ # UPDATE THE TVSHOW #####
if update_item:
self.logMsg("UPDATE tvshow itemid: %s - Title: %s" % (itemid, title), 1)
@@ -1066,6 +1049,9 @@ class TVShows(Items):
API = PlexAPI.API(item)
showid = viewid
itemid = API.getRatingKey()
+ if not itemid:
+ self.logMsg('Error getting itemid for season, skipping', -1)
+ return
kodicursor = self.kodicursor
emby_db = self.emby_db
kodi_db = self.kodi_db
@@ -1078,16 +1064,12 @@ class TVShows(Items):
emby_dbitem = emby_db.getItem_byId(itemid)
try:
embyDbItemId = emby_dbitem[0]
- self.logMsg("Updating Season: %s" % itemid, 2)
except TypeError:
update_item = False
- self.logMsg("Season: %s not found." % itemid, 2)
# Process artwork
allartworks = API.getAllArtwork()
artwork.addArtwork(allartworks, seasonid, "season", kodicursor)
- self.logMsg("Updated season %s, Plex Id: %s of Plex show Id: %s" % (
- seasonnum, itemid, showid), 2)
if update_item:
# Update a reference: checksum in emby table
@@ -1108,20 +1090,21 @@ class TVShows(Items):
artwork = self.artwork
API = PlexAPI.API(item)
- # If the item already exist in the local Kodi DB we'll perform a full item update
+ # 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
update_item = True
itemid = API.getRatingKey()
+ if not itemid:
+ self.logMsg('Error getting itemid for episode, skipping', -1)
+ return
emby_dbitem = emby_db.getItem_byId(itemid)
- self.logMsg("Processing episode with Plex Id: %s" % itemid, 2)
try:
episodeid = emby_dbitem[0]
fileid = emby_dbitem[1]
pathid = emby_dbitem[2]
-
except TypeError:
update_item = False
- self.logMsg("episodeid: %s not found." % itemid, 2)
# episodeid
kodicursor.execute("select coalesce(max(idEpisode),0) from episode")
episodeid = kodicursor.fetchone()[0] + 1
@@ -1145,12 +1128,8 @@ class TVShows(Items):
resume, runtime = API.getRuntime()
premieredate = API.getPremiereDate()
- self.logMsg("Retrieved metadata for %s" % itemid, 2)
-
# episode details
seriesId, seriesName, season, episode = API.getEpisodeDetails()
- self.logMsg("Got episode details: %s %s: s%se%s"
- % (seriesId, seriesName, season, episode), 2)
if season is None:
if item.get('AbsoluteEpisodeNumber'):
@@ -1171,7 +1150,7 @@ class TVShows(Items):
airsBeforeSeason = "-1"
airsBeforeEpisode = "-1"
# Append multi episodes to title
- # if item.get('IndexNumberEnd'):
+ # if item.get('IndexNumberEnd'):
# title = "| %02d | %s" % (item['IndexNumberEnd'], title)
# Get season id
@@ -1190,11 +1169,9 @@ class TVShows(Items):
# self.logMsg("Skipping: %s. Unable to add series: %s." % (itemid, seriesId), -1)
self.logMsg("Parent tvshow now found, skip item", 2)
return False
- self.logMsg("showid: %s" % showid, 2)
seasonid = kodi_db.addSeason(showid, season)
- self.logMsg("seasonid: %s" % seasonid, 2)
- ##### GET THE FILE AND PATH #####
+ # GET THE FILE AND PATH #####
playurl = API.getKey()
filename = playurl
@@ -1235,7 +1212,7 @@ class TVShows(Items):
}
filename = "%s?%s" % (path, urllib.urlencode(params))
- ##### UPDATE THE EPISODE #####
+ # UPDATE THE EPISODE #####
if update_item:
self.logMsg("UPDATE episode itemid: %s" % (itemid), 1)
@@ -1484,12 +1461,11 @@ class TVShows(Items):
kodicursor.execute("DELETE FROM files WHERE idFile = ?", (fileid,))
self.logMsg("Removed episode: %s." % kodiid, 2)
+
class Music(Items):
-
- def __init__(self, embycursor, musiccursor):
-
- Items.__init__(self, embycursor, musiccursor)
+ def __init__(self):
+ Items.__init__(self)
self.directstream = utils.settings('streamMusic') == "true"
self.enableimportsongrating = utils.settings('enableImportSongRating') == "true"
@@ -1498,6 +1474,20 @@ class Music(Items):
self.userid = utils.window('emby_currUser')
self.server = utils.window('emby_server%s' % self.userid)
+ def __enter__(self):
+ """
+ OVERWRITE this method, because we need to open another DB.
+ Open DB connections and cursors
+ """
+ self.embyconn = utils.kodiSQL('emby')
+ self.embycursor = self.embyconn.cursor()
+ # Here it is, not 'video' but 'music'
+ self.kodiconn = utils.kodiSQL('music')
+ self.kodicursor = self.kodiconn.cursor()
+ self.emby_db = embydb.Embydb_Functions(self.embycursor)
+ self.kodi_db = kodidb.Kodidb_Functions(self.kodicursor)
+ return self
+
def added(self, items, pdialog):
total = len(items)
@@ -1545,38 +1535,37 @@ class Music(Items):
if not pdialog and self.contentmsg:
self.contentPop(title, self.newmusic_time)
- def add_updateArtist(self, item, artisttype="MusicArtist"):
- # Process a single artist
- kodiversion = self.kodiversion
+ def add_updateArtist(self, item, viewtag=None, viewid=None,
+ artisttype="MusicArtist"):
kodicursor = self.kodicursor
emby_db = self.emby_db
kodi_db = self.kodi_db
artwork = self.artwork
- API = api.API(item)
+ API = PlexAPI.API(item)
update_item = True
- itemid = item['Id']
+ itemid = API.getRatingKey()
emby_dbitem = emby_db.getItem_byId(itemid)
try:
artistid = emby_dbitem[0]
except TypeError:
update_item = False
- self.logMsg("artistid: %s not found." % itemid, 2)
- ##### The artist details #####
+ # The artist details #####
lastScraped = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
dateadded = API.getDateCreated()
checksum = API.getChecksum()
- name = item['Name']
- musicBrainzId = API.getProvider('MusicBrainzArtist')
- genres = " / ".join(item.get('Genres'))
- bio = API.getOverview()
+ name, sortname = API.getTitle()
+ # musicBrainzId = API.getProvider('MusicBrainzArtist')
+ musicBrainzId = None
+ genres = API.joinList(API.getGenres())
+ bio = API.getPlot()
# Associate artwork
- artworks = artwork.getAllArtwork(item, parentInfo=True)
+ artworks = API.getAllArtwork(parentInfo=True)
thumb = artworks['Primary']
- backdrops = artworks['Backdrop'] # List
+ backdrops = artworks['Backdrop'] # List
if thumb:
thumb = "%s" % thumb
@@ -1585,22 +1574,24 @@ class Music(Items):
else:
fanart = ""
-
- ##### UPDATE THE ARTIST #####
+ # UPDATE THE ARTIST #####
if update_item:
- self.logMsg("UPDATE artist itemid: %s - Name: %s" % (itemid, name), 1)
+ self.logMsg("UPDATE artist itemid: %s - Name: %s"
+ % (itemid, name), 1)
# Update the checksum in emby table
emby_db.updateReference(itemid, checksum)
- ##### OR ADD THE ARTIST #####
+ # OR ADD THE ARTIST #####
else:
self.logMsg("ADD artist itemid: %s - Name: %s" % (itemid, name), 1)
- # safety checks: It looks like Emby supports the same artist multiple times.
- # Kodi doesn't allow that. In case that happens we just merge the artist entries.
+ # safety checks: It looks like Emby supports the same artist
+ # multiple times.
+ # Kodi doesn't allow that. In case that happens we just merge the
+ # artist entries.
artistid = kodi_db.addArtist(name, musicBrainzId)
# Create the reference in emby table
- emby_db.addReference(itemid, artistid, artisttype, "artist", checksum=checksum)
-
+ emby_db.addReference(
+ itemid, artistid, artisttype, "artist", checksum=checksum)
# Process the artist
if self.kodiversion in (16, 17):
@@ -1611,7 +1602,8 @@ class Music(Items):
"lastScraped = ?",
"WHERE idArtist = ?"
))
- kodicursor.execute(query, (genres, bio, thumb, fanart, lastScraped, artistid))
+ kodicursor.execute(query, (genres, bio, thumb, fanart,
+ lastScraped, artistid))
else:
query = ' '.join((
@@ -1621,73 +1613,79 @@ class Music(Items):
"WHERE idArtist = ?"
))
kodicursor.execute(query, (genres, bio, thumb, fanart, lastScraped,
- dateadded, artistid))
-
+ dateadded, artistid))
# Update artwork
artwork.addArtwork(artworks, artistid, "artist", kodicursor)
- def add_updateAlbum(self, item):
- # Process a single artist
- emby = self.emby
+ def add_updateAlbum(self, item, viewtag=None, viewid=None):
kodiversion = self.kodiversion
kodicursor = self.kodicursor
emby_db = self.emby_db
kodi_db = self.kodi_db
artwork = self.artwork
- API = api.API(item)
+ API = PlexAPI.API(item)
update_item = True
- itemid = item['Id']
+ itemid = API.getRatingKey()
+ if not itemid:
+ self.logMsg('Error processing Album, skipping', -1)
+ return
emby_dbitem = emby_db.getItem_byId(itemid)
try:
albumid = emby_dbitem[0]
except TypeError:
+ # Albumid not found
update_item = False
- self.logMsg("albumid: %s not found." % itemid, 2)
- ##### The album details #####
+ # The album details #####
lastScraped = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
dateadded = API.getDateCreated()
userdata = API.getUserData()
checksum = API.getChecksum()
- name = item['Name']
- musicBrainzId = API.getProvider('MusicBrainzAlbum')
- year = item.get('ProductionYear')
- genres = item.get('Genres')
- genre = " / ".join(genres)
- bio = API.getOverview()
+ name, sorttitle = API.getTitle()
+ # musicBrainzId = API.getProvider('MusicBrainzAlbum')
+ musicBrainzId = None
+ year = API.getYear()
+ genres = API.getGenres()
+ genre = API.joinList(genres)
+ bio = API.getPlot()
rating = userdata['UserRating']
- artists = item['AlbumArtists']
- if not artists:
- artists = item['ArtistItems']
- artistname = []
- for artist in artists:
- artistname.append(artist['Name'])
- artistname = " / ".join(artistname)
+ # artists = item['AlbumArtists']
+ # if not artists:
+ # artists = item['ArtistItems']
+ # artistname = []
+ # for artist in artists:
+ # artistname.append(artist['Name'])
+ artistname = item.attrib.get('parentTitle')
+ if not artistname:
+ artistname = item.attrib.get('originalTitle')
# Associate artwork
- artworks = artwork.getAllArtwork(item, parentInfo=True)
+ artworks = API.getAllArtwork(parentInfo=True)
thumb = artworks['Primary']
if thumb:
thumb = "%s" % thumb
- ##### UPDATE THE ALBUM #####
+ # UPDATE THE ALBUM #####
if update_item:
- self.logMsg("UPDATE album itemid: %s - Name: %s" % (itemid, name), 1)
+ self.logMsg("UPDATE album itemid: %s - Name: %s"
+ % (itemid, name), 1)
# Update the checksum in emby table
emby_db.updateReference(itemid, checksum)
- ##### OR ADD THE ALBUM #####
+ # OR ADD THE ALBUM #####
else:
self.logMsg("ADD album itemid: %s - Name: %s" % (itemid, name), 1)
- # safety checks: It looks like Emby supports the same artist multiple times.
- # Kodi doesn't allow that. In case that happens we just merge the artist entries.
+ # safety checks: It looks like Emby supports the same artist
+ # multiple times.
+ # Kodi doesn't allow that. In case that happens we just merge the
+ # artist entries.
albumid = kodi_db.addAlbum(name, musicBrainzId)
# Create the reference in emby table
- emby_db.addReference(itemid, albumid, "MusicAlbum", "album", checksum=checksum)
-
+ emby_db.addReference(
+ itemid, albumid, "MusicAlbum", "album", checksum=checksum)
# Process the album info
if kodiversion == 17:
@@ -1699,8 +1697,8 @@ class Music(Items):
"iUserrating = ?, lastScraped = ?, strReleaseType = ?",
"WHERE idAlbum = ?"
))
- kodicursor.execute(query, (artistname, year, genre, bio, thumb, rating, lastScraped,
- "album", albumid))
+ kodicursor.execute(query, (artistname, year, genre, bio, thumb,
+ rating, lastScraped, "album", albumid))
elif kodiversion == 16:
# Kodi Jarvis
query = ' '.join((
@@ -1710,8 +1708,8 @@ class Music(Items):
"iRating = ?, lastScraped = ?, strReleaseType = ?",
"WHERE idAlbum = ?"
))
- kodicursor.execute(query, (artistname, year, genre, bio, thumb, rating, lastScraped,
- "album", albumid))
+ kodicursor.execute(query, (artistname, year, genre, bio, thumb,
+ rating, lastScraped, "album", albumid))
elif kodiversion == 15:
# Kodi Isengard
query = ' '.join((
@@ -1721,8 +1719,9 @@ class Music(Items):
"iRating = ?, lastScraped = ?, dateAdded = ?, strReleaseType = ?",
"WHERE idAlbum = ?"
))
- kodicursor.execute(query, (artistname, year, genre, bio, thumb, rating, lastScraped,
- dateadded, "album", albumid))
+ kodicursor.execute(query, (artistname, year, genre, bio, thumb,
+ rating, lastScraped, dateadded,
+ "album", albumid))
else:
# Kodi Helix
query = ' '.join((
@@ -1732,92 +1731,104 @@ class Music(Items):
"iRating = ?, lastScraped = ?, dateAdded = ?",
"WHERE idAlbum = ?"
))
- kodicursor.execute(query, (artistname, year, genre, bio, thumb, rating, lastScraped,
- dateadded, albumid))
+ kodicursor.execute(query, (artistname, year, genre, bio, thumb,
+ rating, lastScraped, dateadded,
+ albumid))
# Associate the parentid for emby reference
- parentId = item.get('ParentId')
+ parentId = item.attrib.get('parentRatingKey')
if parentId is not None:
emby_dbartist = emby_db.getItem_byId(parentId)
try:
artistid = emby_dbartist[0]
except TypeError:
- # Artist does not exist in emby database.
- artist = emby.getItem(parentId)
+ self.logMsg('Artist %s does not exist in emby database'
+ % parentId, 1)
+ artist = GetPlexMetadata(parentId)
# Item may not be an artist, verification necessary.
- if artist['Type'] == "MusicArtist":
- # Update with the parentId, for remove reference
- emby_db.addReference(parentId, parentId, "MusicArtist", "artist")
- emby_db.updateParentId(itemid, parentId)
+ if artist:
+ if artist[0].attrib.get('type') == "artist":
+ # Update with the parentId, for remove reference
+ emby_db.addReference(
+ parentId, parentId, "MusicArtist", "artist")
+ emby_db.updateParentId(itemid, parentId)
else:
# Update emby reference with the artistid
emby_db.updateParentId(itemid, artistid)
# Assign main artists to album
- for artist in artists:
- artistname = artist['Name']
- artistId = artist['Id']
- emby_dbartist = emby_db.getItem_byId(artistId)
- try:
- artistid = emby_dbartist[0]
- except TypeError:
- # Artist does not exist in emby database, create the reference
- artist = emby.getItem(artistId)
- self.add_updateArtist(artist, artisttype="AlbumArtist")
+ # Plex unfortunately only supports 1 artist :-(
+ artistId = parentId
+ emby_dbartist = emby_db.getItem_byId(artistId)
+ try:
+ artistid = emby_dbartist[0]
+ except TypeError:
+ # Artist does not exist in emby database, create the reference
+ self.logMsg('Artist %s does not exist in emby database'
+ % artistId, 1)
+ artist = GetPlexMetadata(artistId)
+ if artist:
+ self.add_updateArtist(artist[0], artisttype="AlbumArtist")
emby_dbartist = emby_db.getItem_byId(artistId)
artistid = emby_dbartist[0]
- else:
- # Best take this name over anything else.
- query = "UPDATE artist SET strArtist = ? WHERE idArtist = ?"
- kodicursor.execute(query, (artistname, artistid,))
+ else:
+ # Best take this name over anything else.
+ query = "UPDATE artist SET strArtist = ? WHERE idArtist = ?"
+ kodicursor.execute(query, (artistname, artistid,))
+ self.logMsg("UPDATE artist: strArtist: %s, idArtist: %s"
+ % (artistname, artistid), 1)
- # Add artist to album
- query = (
- '''
- INSERT OR REPLACE INTO album_artist(idArtist, idAlbum, strArtist)
+ # Add artist to album
+ query = (
+ '''
+ INSERT OR REPLACE INTO album_artist(idArtist, idAlbum, strArtist)
- VALUES (?, ?, ?)
- '''
- )
- kodicursor.execute(query, (artistid, albumid, artistname))
- # Update discography
- query = (
- '''
- INSERT OR REPLACE INTO discography(idArtist, strAlbum, strYear)
-
- VALUES (?, ?, ?)
- '''
- )
- kodicursor.execute(query, (artistid, name, year))
- # Update emby reference with parentid
- emby_db.updateParentId(artistId, albumid)
+ VALUES (?, ?, ?)
+ '''
+ )
+ kodicursor.execute(query, (artistid, albumid, artistname))
+ # Update discography
+ query = (
+ '''
+ INSERT OR REPLACE INTO discography(idArtist, strAlbum, strYear)
+ VALUES (?, ?, ?)
+ '''
+ )
+ kodicursor.execute(query, (artistid, name, year))
+ # Update emby reference with parentid
+ emby_db.updateParentId(artistId, albumid)
# Add genres
kodi_db.addMusicGenres(albumid, genres, "album")
# Update artwork
artwork.addArtwork(artworks, albumid, "album", kodicursor)
- def add_updateSong(self, item):
+ def add_updateSong(self, item, viewtag=None, viewid=None):
# Process single song
kodiversion = self.kodiversion
kodicursor = self.kodicursor
emby_db = self.emby_db
kodi_db = self.kodi_db
artwork = self.artwork
- API = api.API(item)
+ API = PlexAPI.API(item)
update_item = True
- itemid = item['Id']
+ itemid = API.getRatingKey()
+ if not itemid:
+ self.logMsg('Error processing Song; skipping', -1)
+ return
emby_dbitem = emby_db.getItem_byId(itemid)
try:
songid = emby_dbitem[0]
pathid = emby_dbitem[2]
albumid = emby_dbitem[3]
except TypeError:
+ # Songid not found
update_item = False
- self.logMsg("songid: %s not found." % itemid, 2)
-
- ##### The song details #####
+ kodicursor.execute("select coalesce(max(idSong),0) from song")
+ songid = kodicursor.fetchone()[0] + 1
+
+ # The song details #####
checksum = API.getChecksum()
dateadded = API.getDateCreated()
userdata = API.getUserData()
@@ -1825,94 +1836,75 @@ class Music(Items):
dateplayed = userdata['LastPlayedDate']
# item details
- title = item['Name']
- musicBrainzId = API.getProvider('MusicBrainzTrackId')
- genres = item.get('Genres')
- genre = " / ".join(genres)
- artists = " / ".join(item['Artists'])
- tracknumber = item.get('IndexNumber', 0)
- disc = item.get('ParentIndexNumber', 1)
+ title, sorttitle = API.getTitle()
+ # musicBrainzId = API.getProvider('MusicBrainzTrackId')
+ musicBrainzId = None
+ genres = API.getGenres()
+ genre = API.joinList(genres)
+ artists = item.attrib.get('grandparentTitle')
+ tracknumber = int(item.attrib.get('index', 0))
+ disc = int(item.attrib.get('parentIndex', 1))
if disc == 1:
track = tracknumber
else:
track = disc*2**16 + tracknumber
- year = item.get('ProductionYear')
- duration = API.getRuntime()
+ year = API.getYear()
+ resume, duration = API.getRuntime()
rating = userdata['UserRating']
- #if enabled, try to get the rating from file and/or emby
- if not self.directstream:
- rating, comment, hasEmbeddedCover = musicutils.getAdditionalSongTags(itemid, rating, API, kodicursor, emby_db, self.enableimportsongrating, self.enableexportsongrating, self.enableupdatesongrating)
- else:
- hasEmbeddedCover = False
- comment = API.getOverview()
-
-
- ##### GET THE FILE AND PATH #####
+ comment = None
+
+ # Plex works a bit differently
if self.directstream:
- path = "%s/emby/Audio/%s/" % (self.server, itemid)
- filename = "stream.mp3"
+ paths = "%s%s" % (self.server, item[0][0][0].attrib.get('key'))
+ paths = paths.rsplit('/', 1)
+ path = paths[0]
+ filename = paths[1]
else:
- playurl = API.getKey()
+ path = "plugin://plugin.video.plexkodiconnect.movies/"
+ filename = API.getKey()
+ params = {
+ 'filename': filename,
+ 'id': itemid,
+ 'dbid': songid,
+ 'mode': "play"
+ }
+ filename = "%s?%s" % (path, urllib.urlencode(params))
- if "\\" in playurl:
- # Local path
- filename = playurl.rsplit("\\", 1)[1]
- else: # Network share
- filename = playurl.rsplit("/", 1)[1]
-
- # Direct paths is set the Kodi way
- if utils.window('emby_pathverified') != "true" and not xbmcvfs.exists(playurl):
- # Validate the path is correct with user intervention
- utils.window('emby_directPath', clear=True)
- resp = xbmcgui.Dialog().yesno(
- heading="Can't validate path",
- line1=(
- "Kodi can't locate file: %s. Verify the path. "
- "You may to verify your network credentials in the "
- "add-on settings or use the emby path substitution "
- "to format your path correctly. Stop syncing?"
- % playurl))
- if resp:
- utils.window('emby_shouldStop', value="true")
- return False
-
- path = playurl.replace(filename, "")
- utils.window('emby_pathverified', value="true")
-
- ##### UPDATE THE SONG #####
+ # UPDATE THE SONG #####
if update_item:
- self.logMsg("UPDATE song itemid: %s - Title: %s" % (itemid, title), 1)
-
+ self.logMsg("UPDATE song itemid: %s - Title: %s"
+ % (itemid, title), 1)
# Update path
query = "UPDATE path SET strPath = ? WHERE idPath = ?"
kodicursor.execute(query, (path, pathid))
# Update the song entry
query = ' '.join((
-
"UPDATE song",
"SET idAlbum = ?, strArtists = ?, strGenres = ?, strTitle = ?, iTrack = ?,",
"iDuration = ?, iYear = ?, strFilename = ?, iTimesPlayed = ?, lastplayed = ?,",
"rating = ?, comment = ?",
"WHERE idSong = ?"
))
- kodicursor.execute(query, (albumid, artists, genre, title, track, duration, year,
- filename, playcount, dateplayed, rating, comment, songid))
+ kodicursor.execute(query, (albumid, artists, genre, title, track,
+ duration, year, filename, playcount,
+ dateplayed, rating, comment, songid))
# Update the checksum in emby table
emby_db.updateReference(itemid, checksum)
-
- ##### OR ADD THE SONG #####
+
+ # OR ADD THE SONG #####
else:
self.logMsg("ADD song itemid: %s - Title: %s" % (itemid, title), 1)
-
+
# Add path
pathid = kodi_db.addPath(path)
try:
# Get the album
- emby_dbalbum = emby_db.getItem_byId(item['AlbumId'])
+ emby_dbalbum = emby_db.getItem_byId(
+ item.attrib.get('parentRatingKey'))
albumid = emby_dbalbum[0]
except KeyError:
# No album Id associated to the song.
@@ -1921,8 +1913,8 @@ class Music(Items):
except TypeError:
# No album found. Let's create it
self.logMsg("Album database entry missing.", 1)
- emby_albumId = item['AlbumId']
- album = self.emby.getItem(emby_albumId)
+ emby_albumId = item.attrib.get('parentRatingKey')
+ album = GetPlexMetadata(emby_albumId)
self.add_updateAlbum(album)
emby_dbalbum = emby_db.getItem_byId(emby_albumId)
try:
@@ -1963,10 +1955,8 @@ class Music(Items):
'''
)
kodicursor.execute(query, (albumid, genre, year, dateadded))
-
+
# Create the song entry
- kodicursor.execute("select coalesce(max(idSong),0) from song")
- songid = kodicursor.fetchone()[0] + 1
query = (
'''
INSERT INTO song(
@@ -1977,25 +1967,27 @@ class Music(Items):
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
'''
)
- kodicursor.execute(query, (songid, albumid, pathid, artists, genre, title, track,
- duration, year, filename, musicBrainzId, playcount, dateplayed, rating))
+ kodicursor.execute(
+ query, (songid, albumid, pathid, artists, genre, title, track,
+ duration, year, filename, musicBrainzId, playcount,
+ dateplayed, rating))
# Create the reference in emby table
- emby_db.addReference(itemid, songid, "Audio", "song", pathid=pathid, parentid=albumid,
+ emby_db.addReference(
+ itemid, songid, "Audio", "song", pathid=pathid,
+ parentid=albumid,
checksum=checksum)
-
# Link song to album
query = (
'''
INSERT OR REPLACE INTO albuminfosong(
idAlbumInfoSong, idAlbumInfo, iTrack, strTitle, iDuration)
-
+
VALUES (?, ?, ?, ?, ?)
'''
)
kodicursor.execute(query, (songid, albumid, track, title, duration))
-
# Verify if album has artists
addArtist = False
query = ' '.join((
@@ -2009,112 +2001,59 @@ class Music(Items):
if result and result[0] == "":
addArtist = True
- if item['AlbumArtists']:
- album_artists = item['AlbumArtists']
- else:
- album_artists = item['ArtistItems']
+ # if item['AlbumArtists']:
+ # album_artists = item['AlbumArtists']
+ # else:
+ # album_artists = item['ArtistItems']
# Link song to artist
- artists_name = []
- for artist in album_artists:
- artist_name = artist['Name']
- artists_name.append(artist_name)
- emby_dbartist = emby_db.getItem_byId(artist['Id'])
- try:
- artistid = emby_dbartist[0]
- except: pass
- else:
+ artist_name = item.attrib.get('grandparentTitle')
+ emby_dbartist = emby_db.getItem_byId(
+ item.attrib.get('grandparentRatingKey'))
+ try:
+ artistid = emby_dbartist[0]
+ except:
+ pass
+ else:
+ query = (
+ '''
+ INSERT OR REPLACE INTO song_artist(idArtist, idSong, strArtist)
+
+ VALUES (?, ?, ?)
+ '''
+ )
+ kodicursor.execute(query, (artistid, songid, artist_name))
+
+ if addArtist:
query = (
'''
- INSERT OR REPLACE INTO song_artist(idArtist, idSong, strArtist)
+ INSERT OR REPLACE INTO album_artist(idArtist, idAlbum, strArtist)
VALUES (?, ?, ?)
'''
)
- kodicursor.execute(query, (artistid, songid, artist_name))
+ kodicursor.execute(query, (artistid, albumid, artist_name))
- if addArtist:
- query = (
- '''
- INSERT OR REPLACE INTO album_artist(idArtist, idAlbum, strArtist)
-
- VALUES (?, ?, ?)
- '''
- )
- kodicursor.execute(query, (artistid, albumid, artist_name))
- else:
- if addArtist:
- artists_onalbum = " / ".join(artists_name)
- if kodiversion in (16, 17):
- # Kodi Jarvis, Krypton
- query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
- kodicursor.execute(query, (artists_onalbum, albumid))
- elif kodiversion == 15:
- # Kodi Isengard
- query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
- kodicursor.execute(query, (artists_onalbum, albumid))
- else:
- # Kodi Helix
- query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
- kodicursor.execute(query, (artists_onalbum, albumid))
+ if addArtist:
+ if kodiversion in (16, 17):
+ # Kodi Jarvis, Krypton
+ query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
+ kodicursor.execute(query, (artist_name, albumid))
+ elif kodiversion == 15:
+ # Kodi Isengard
+ query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
+ kodicursor.execute(query, (artist_name, albumid))
+ else:
+ # Kodi Helix
+ query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
+ kodicursor.execute(query, (artist_name, albumid))
# Add genres
kodi_db.addMusicGenres(songid, genres, "song")
# Update artwork
- allart = artwork.getAllArtwork(item, parentInfo=True)
- if hasEmbeddedCover:
- allart["Primary"] = "image://music@" + artwork.single_urlencode( playurl )
+ allart = API.getAllArtwork(parentInfo=True)
artwork.addArtwork(allart, songid, "song", kodicursor)
- def updateUserdata(self, item):
- # This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
- # Poster with progress bar
- kodicursor = self.kodicursor
- emby_db = self.emby_db
- kodi_db = self.kodi_db
- API = api.API(item)
-
- # Get emby information
- itemid = item['Id']
- checksum = API.getChecksum()
- userdata = API.getUserData()
- runtime = API.getRuntime()
- rating = userdata['UserRating']
-
- # Get Kodi information
- emby_dbitem = emby_db.getItem_byId(itemid)
- try:
- kodiid = emby_dbitem[0]
- mediatype = emby_dbitem[4]
- self.logMsg("Update playstate for %s: %s" % (mediatype, item['Name']), 1)
- except TypeError:
- return
-
- if mediatype == "song":
-
- #should we ignore this item ?
- #happens when userdata updated by ratings method
- if utils.window("ignore-update-%s" %itemid):
- utils.window("ignore-update-%s" %itemid,clear=True)
- return
-
- # Process playstates
- playcount = userdata['PlayCount']
- dateplayed = userdata['LastPlayedDate']
-
- #process item ratings
- rating, comment, hasEmbeddedCover = musicutils.getAdditionalSongTags(itemid, rating, API, kodicursor, emby_db, self.enableimportsongrating, self.enableexportsongrating, self.enableupdatesongrating)
-
- query = "UPDATE song SET iTimesPlayed = ?, lastplayed = ?, rating = ? WHERE idSong = ?"
- kodicursor.execute(query, (playcount, dateplayed, rating, kodiid))
-
- elif mediatype == "album":
- # Process playstates
- query = "UPDATE album SET iRating = ? WHERE idAlbum = ?"
- kodicursor.execute(query, (rating, kodiid))
-
- emby_db.updateReference(itemid, checksum)
-
def remove(self, itemid):
# Remove kodiid, fileid, pathid, emby reference
emby_db = self.emby_db
diff --git a/resources/lib/kodidb_functions.py b/resources/lib/kodidb_functions.py
index 0e0a7ac8..f4697738 100644
--- a/resources/lib/kodidb_functions.py
+++ b/resources/lib/kodidb_functions.py
@@ -740,7 +740,6 @@ class Kodidb_Functions():
cursor.execute(query, (kodiid, mediatype))
# Add tags
- self.logMsg("Adding Tags: %s" % tags, 2)
for tag in tags:
self.addTag(kodiid, tag, mediatype)
diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py
index 8517368f..f5c9d8fa 100644
--- a/resources/lib/librarysync.py
+++ b/resources/lib/librarysync.py
@@ -20,7 +20,6 @@ import read_embyserver as embyserver
import userclient
import videonodes
-import PlexAPI
import PlexFunctions
###############################################################################
@@ -125,9 +124,14 @@ class ThreadedProcessMetadata(Thread):
with lock:
# Get the one child entry in the xml and process
for child in plexitem:
- itemSubFkt(child,
- viewtag=viewName,
- viewid=viewId)
+ if method == 'add_updateAlbum':
+ item.add_updateAlbum(child,
+ viewtag=viewName,
+ viewid=viewId)
+ else:
+ itemSubFkt(child,
+ viewtag=viewName,
+ viewid=viewId)
# Keep track of where we are at
processMetadataCount += 1
processingViewName = title
@@ -219,6 +223,8 @@ class LibrarySync(Thread):
utils.settings('SyncInstallRunDone') == 'true' else False
self.showDbSync = True if \
utils.settings('dbSyncIndicator') == 'true' else False
+ self.enableMusic = True if utils.settings('enableMusic') == "true" \
+ else False
Thread.__init__(self)
@@ -250,6 +256,13 @@ class LibrarySync(Thread):
Using /library/recentlyAdded is NOT working as changes to lib items are
not reflected
+
+ This will NOT remove items from Kodi db that were removed from the PMS
+ (happens only during fullsync)
+
+ Currently, ALL items returned by the PMS (because they've just been
+ edited by the PMS or have been watched) will be processed. This will
+ probably happen several times.
"""
self.compare = True
# Get last sync time
@@ -262,29 +275,22 @@ class LibrarySync(Thread):
# Set new timestamp NOW because sync might take a while
self.saveLastSync()
- # Get all PMS items already saved in Kodi
+ # Original idea: Get all PMS items already saved in Kodi
# Also get checksums of every Plex items already saved in Kodi
- allKodiElementsId = {}
- with embydb.GetEmbyDB() as emby_db:
- for itemtype in PlexFunctions.EmbyItemtypes():
- try:
- allKodiElementsId.update(
- dict(emby_db.getChecksum(itemtype)))
- except ValueError:
- pass
-
- self.allKodiElementsId = allKodiElementsId
+ # NEW idea: process every item returned by the PMS
+ self.allKodiElementsId = {}
# Run through views and get latest changed elements using time diff
- self.updatelist = []
- self.allPlexElementsId = {}
self.updateKodiVideoLib = False
+ self.updateKodiMusicLib = False
for view in self.views:
+ self.updatelist = []
if self.threadStopped():
return True
# Get items per view
items = PlexFunctions.GetAllPlexLeaves(
view['id'], updatedAt=lastSync)
+ # Just skip item if something went wrong
if not items:
continue
# Get one itemtype, because they're the same in the PMS section
@@ -299,21 +305,28 @@ class LibrarySync(Thread):
if self.updatelist:
if self.updatelist[0]['itemType'] in ['Movies', 'TVShows']:
self.updateKodiVideoLib = True
+ elif self.updatelist[0]['itemType'] == 'Music':
+ self.updateKodiMusicLib = True
self.GetAndProcessXMLs(
PlexFunctions.GetItemClassFromType(plexType))
self.updatelist = []
+
# Update userdata
for view in self.views:
self.PlexUpdateWatched(
view['id'],
PlexFunctions.GetItemClassFromType(view['itemtype']),
lastViewedAt=lastSync)
+
# Let Kodi update the library now (artwork and userdata)
if self.updateKodiVideoLib:
self.logMsg("Doing Kodi Video Lib update", 2)
xbmc.executebuiltin('UpdateLibrary(video)')
+ if self.updateKodiMusicLib:
+ self.logMsg("Doing Kodi Music Lib update", 2)
+ xbmc.executebuiltin('UpdateLibrary(music)')
+
# Reset and return
- self.allKodiElementsId = {}
self.allPlexElementsId = {}
return True
@@ -346,7 +359,6 @@ class LibrarySync(Thread):
def fullSync(self, manualrun=False, repair=False):
# Only run once when first setting up. Can be run manually.
self.compare = manualrun or repair
- music_enabled = utils.settings('enableMusic') == "true"
# Add sources
utils.sourcesXML()
@@ -367,18 +379,12 @@ class LibrarySync(Thread):
# Set views
self.maintainViews()
- # Sync video library
- # process = {
-
- # 'movies': self.movies,
- # 'musicvideos': self.musicvideos,
- # 'tvshows': self.tvshows
- # }
-
process = {
'movies': self.PlexMovies,
- 'tvshows': self.PlexTVShows
+ 'tvshows': self.PlexTVShows,
}
+ if self.enableMusic:
+ process['music'] = self.PlexMusic
for itemtype in process:
startTime = datetime.now()
@@ -391,33 +397,12 @@ class LibrarySync(Thread):
"SyncDatabase (finished %s in: %s)"
% (itemtype, str(elapsedTime).split('.')[0]), 1)
- # # sync music
- # if music_enabled:
-
- # musicconn = utils.kodiSQL('music')
- # musiccursor = musicconn.cursor()
-
- # startTime = datetime.now()
- # completed = self.music(embycursor, musiccursor, pDialog)
- # if not completed:
-
- # utils.window('emby_dbScan', clear=True)
-
- # embycursor.close()
- # musiccursor.close()
- # return False
- # else:
- # musicconn.commit()
- # embyconn.commit()
- # elapsedTime = datetime.now() - startTime
- # self.logMsg(
- # "SyncDatabase (finished music in: %s)"
- # % (str(elapsedTime).split('.')[0]), 1)
- # musiccursor.close()
-
+ # Let kodi update the views in any case
xbmc.executebuiltin('UpdateLibrary(video)')
- elapsedtotal = datetime.now() - starttotal
+ if self.enableMusic:
+ xbmc.executebuiltin('UpdateLibrary(music)')
+ elapsedtotal = datetime.now() - starttotal
utils.window('emby_initialScan', clear=True)
self.showKodiNote("%s completed in: %s"
% (message, str(elapsedtotal).split('.')[0]))
@@ -429,7 +414,8 @@ class LibrarySync(Thread):
folder = folderItem.attrib
mediatype = folder['type']
# Only process supported formats
- if mediatype not in ['movie', 'show']:
+ supportedMedia = ['movie', 'show']
+ if mediatype not in supportedMedia:
return
folderid = folder['key']
@@ -565,11 +551,24 @@ class LibrarySync(Thread):
# update views for all:
self.views = emby_db.getAllViewInfo()
+ # Append music views only to self.views (no custom views otherwise)
+ if self.enableMusic:
+ for folderItem in result:
+ if folderItem.attrib['type'] == 'artist':
+ entry = {
+ 'id': folderItem.attrib['key'],
+ 'name': folderItem.attrib['title'],
+ 'itemtype': 'artist'
+ }
+ self.views.append(entry)
+
self.logMsg("views saved: %s" % self.views, 1)
def GetUpdatelist(self, xml, itemType, method, viewName, viewId,
dontCheck=False):
"""
+ THIS METHOD NEEDS TO BE FAST! => e.g. no API calls
+
Adds items to self.updatelist as well as self.allPlexElementsId dict
Input:
@@ -599,13 +598,13 @@ class LibrarySync(Thread):
if self.compare or not dontCheck:
# Manual sync
for item in xml:
+ itemId = item.attrib.get('ratingKey')
# Skipping items 'title=All episodes' without a 'ratingKey'
- if not item.attrib.get('ratingKey', False):
+ if not itemId:
continue
- API = PlexAPI.API(item)
- itemId = API.getRatingKey()
- title, sorttitle = API.getTitle()
- plex_checksum = API.getChecksum()
+ title = item.attrib.get('title', 'Missing Title Name')
+ plex_checksum = ("K%s%s"
+ % (itemId, item.attrib.get('updatedAt', '')))
self.allPlexElementsId[itemId] = plex_checksum
kodi_checksum = self.allKodiElementsId.get(itemId)
if kodi_checksum != plex_checksum:
@@ -620,13 +619,13 @@ class LibrarySync(Thread):
else:
# Initial or repair sync: get all Plex movies
for item in xml:
- # Only look at valid items = Plex library items
- if not item.attrib.get('ratingKey', False):
+ itemId = item.attrib.get('ratingKey')
+ # Skipping items 'title=All episodes' without a 'ratingKey'
+ if not itemId:
continue
- API = PlexAPI.API(item)
- itemId = API.getRatingKey()
- title, sorttitle = API.getTitle()
- plex_checksum = API.getChecksum()
+ title = item.attrib.get('title', 'Missing Title Name')
+ plex_checksum = ("K%s%s"
+ % (itemId, item.attrib.get('updatedAt', '')))
self.allPlexElementsId[itemId] = plex_checksum
self.updatelist.append({'itemId': itemId,
'itemType': itemType,
@@ -856,25 +855,14 @@ class LibrarySync(Thread):
self.allKodiElementsId = {}
if self.compare:
with embydb.GetEmbyDB() as emby_db:
- # Get movies from Plex server
# Pull the list of TV shows already in Kodi
- try:
- all_koditvshows = dict(emby_db.getChecksum('Series'))
- self.allKodiElementsId.update(all_koditvshows)
- except ValueError:
- pass
- # Same for seasons
- try:
- all_kodiseasons = dict(emby_db.getChecksum('Season'))
- self.allKodiElementsId.update(all_kodiseasons)
- except ValueError:
- pass
- # Same for the episodes (sub-element of shows/series)
- try:
- all_kodiepisodes = dict(emby_db.getChecksum('Episode'))
- self.allKodiElementsId.update(all_kodiepisodes)
- except ValueError:
- pass
+ for kind in ('Series', 'Season', 'Episode'):
+ try:
+ elements = dict(emby_db.getChecksum(kind))
+ self.allKodiElementsId.update(elements)
+ # Yet empty/not yet synched
+ except ValueError:
+ pass
##### PROCESS TV Shows #####
self.updatelist = []
@@ -965,51 +953,84 @@ class LibrarySync(Thread):
self.logMsg("%s sync is finished." % itemType, 1)
return True
- def music(self, embycursor, kodicursor, pdialog):
- # Get music from emby
- emby = self.emby
- emby_db = embydb.Embydb_Functions(embycursor)
- music = itemtypes.Music(embycursor, kodicursor)
+ def PlexMusic(self):
+ itemType = 'Music'
- process = {
+ views = [x for x in self.views if x['itemtype'] == 'artist']
+ self.logMsg("Media folders for %s: %s" % (itemType, views), 1)
- 'artists': [emby.getArtists, music.add_updateArtist],
- 'albums': [emby.getAlbums, music.add_updateAlbum],
- 'songs': [emby.getSongs, music.add_updateSong]
+ methods = {
+ 'MusicArtist': 'add_updateArtist',
+ 'MusicAlbum': 'add_updateAlbum',
+ 'Audio': 'add_updateSong'
+ }
+ urlArgs = {
+ 'MusicArtist': {'type': 8},
+ 'MusicAlbum': {'type': 9},
+ 'Audio': {'type': 10}
}
- types = ['artists', 'albums', 'songs']
- for type in types:
- if pdialog:
- pdialog.update(
- heading="Emby for Kodi",
- message="Gathering %s..." % type)
-
- all_embyitems = process[type][0](dialog=pdialog)
- total = all_embyitems['TotalRecordCount']
- embyitems = all_embyitems['Items']
-
- if pdialog:
- pdialog.update(heading="Processing %s / %s items" % (type, total))
-
- count = 0
- for embyitem in embyitems:
- # Process individual item
- if self.threadStopped():
- return False
-
- title = embyitem['Name']
- if pdialog:
- percentage = int((float(count) / float(total))*100)
- pdialog.update(percentage, message=title)
- count += 1
-
- process[type][1](embyitem)
- else:
- self.logMsg("%s finished." % type, 2)
+ # Process artist, then album and tracks last
+ for kind in ('MusicArtist', 'MusicAlbum', 'Audio'):
+ if self.threadStopped():
+ return True
+ self.logMsg("Start processing music %s" % kind, 1)
+ self.ProcessMusic(
+ views, kind, urlArgs[kind], methods[kind])
+ self.logMsg("Processing of music %s done" % kind, 1)
+ self.GetAndProcessXMLs(itemType)
+ self.logMsg("GetAndProcessXMLs for music %s completed" % kind, 1)
+ # reset stuff
+ self.allKodiElementsId = {}
+ self.allPlexElementsId = {}
+ self.updatelist = []
+ self.logMsg("%s sync is finished." % itemType, 1)
return True
+ def ProcessMusic(self, views, kind, urlArgs, method):
+ self.allKodiElementsId = {}
+ self.allPlexElementsId = {}
+ self.updatelist = []
+
+ # Get a list of items already existing in Kodi db
+ if self.compare:
+ with embydb.GetEmbyDB() as emby_db:
+ # Pull the list of items already in Kodi
+ try:
+ elements = dict(emby_db.getChecksum(kind))
+ self.allKodiElementsId.update(elements)
+ # Yet empty/nothing yet synched
+ except ValueError:
+ pass
+
+ for view in views:
+ if self.threadStopped():
+ return True
+ # Get items per view
+ viewId = view['id']
+ viewName = view['name']
+ itemsXML = PlexFunctions.GetPlexSectionResults(
+ viewId, args=urlArgs)
+ if not itemsXML:
+ self.logMsg("Error downloading xml for view %s"
+ % viewId, -1)
+ continue
+ # Populate self.updatelist and self.allPlexElementsId
+ self.GetUpdatelist(itemsXML,
+ 'Music',
+ method,
+ viewName,
+ viewId)
+
+ # Remove items from Kodi db?
+ if self.compare:
+ # Manual sync, process deletes
+ with itemtypes.Music() as Music:
+ for item in self.allKodiElementsId:
+ if item not in self.allPlexElementsId:
+ Music.remove(item)
+
def compareDBVersion(self, current, minimum):
# It returns True is database is up to date. False otherwise.
self.logMsg("current: %s minimum: %s" % (current, minimum), 1)