diff --git a/default.py b/default.py
index 300619d7..cc6bc0bd 100644
--- a/default.py
+++ b/default.py
@@ -2,6 +2,7 @@ import xbmcaddon
 import xbmcplugin
 import xbmc
 import xbmcgui
+import xbmcvfs
 import os
 import threading
 import json
@@ -12,24 +13,80 @@ cwd = addonSettings.getAddonInfo('path')
 BASE_RESOURCE_PATH = xbmc.translatePath( os.path.join( cwd, 'resources', 'lib' ) )
 sys.path.append(BASE_RESOURCE_PATH)
 
-WINDOW = xbmcgui.Window( 10000 )
+
+WINDOW = xbmcgui.Window(10000)
 
 import Utils as utils
 from PlaybackUtils import PlaybackUtils
+from DownloadUtils import DownloadUtils
+from ReadEmbyDB import ReadEmbyDB
+from API import API
 
 try:
-    params=utils.get_params(sys.argv[2])
-    mode = params.get('mode',"")
-    id = params.get('id',"")
+    params = utils.get_params(sys.argv[2])
+    mode = params['mode']
+    id = params['id']
 except:
-    params={}
-    mode=None
-    id=None
+    params = {}
+    mode = None
+
+if  mode == "play":
+    # Play items via plugin://plugin.video.emby/
+    url = "{server}/mediabrowser/Users/{UserId}/Items/%s?format=json&ImageTypeLimit=1" % id
+    result = DownloadUtils().downloadUrl(url)
+    item = PlaybackUtils().PLAY(result, setup="default")
+
+    
+#get extrafanart for listitem - this will only be used for skins that actually call the listitem's path + fanart dir... 
+elif "extrafanart" in sys.argv[0]:
+    itemPath = ""
+    embyId = ""
+    
+    try:
+        #only do this if the listitem has actually changed
+        itemPath = xbmc.getInfoLabel("ListItem.FileNameAndPath")
+            
+        if not itemPath:
+            itemPath = xbmc.getInfoLabel("ListItem.Path")
+        
+        if ("/tvshows/" in itemPath or "/musicvideos/" in itemPath or "/movies/" in itemPath):
+            embyId = itemPath.split("/")[-2]
+
+            #we need to store the images locally for this to work because of the caching system in xbmc
+            fanartDir = xbmc.translatePath("special://thumbnails/emby/" + embyId + "/")
+            
+            if not xbmcvfs.exists(fanartDir):
+                #download the images to the cache directory
+                xbmcvfs.mkdir(fanartDir)
+                item = ReadEmbyDB().getFullItem(embyId)
+                if item != None:
+                    if item.has_key("BackdropImageTags"):
+                        if(len(item["BackdropImageTags"]) > 1):
+                            totalbackdrops = len(item["BackdropImageTags"]) 
+                            for index in range(1,totalbackdrops): 
+                                backgroundUrl = API().getArtwork(item, "Backdrop",str(index))
+                                fanartFile = os.path.join(fanartDir,"fanart" + str(index) + ".jpg")
+                                li = xbmcgui.ListItem(str(index), path=fanartFile)
+                                xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=fanartFile, listitem=li)
+                                xbmcvfs.copy(backgroundUrl,fanartFile) 
+                
+            else:
+                #use existing cached images
+                dirs, files = xbmcvfs.listdir(fanartDir)
+                count = 1
+                for file in files:
+                    count +=1
+                    li = xbmcgui.ListItem(file, path=os.path.join(fanartDir,file))
+                    xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=os.path.join(fanartDir,file), listitem=li)
+    except:
+        pass
+    
+    #always do endofdirectory to prevent errors in the logs
+    xbmcplugin.endOfDirectory(int(sys.argv[1]))
+
 
-if  mode != None and mode == "play":
-    PlaybackUtils().PLAY(id)
 elif sys.argv[1] == "reset":
     utils.reset()
-else:
+else:   
     xbmc.executebuiltin('Addon.OpenSettings(plugin.video.emby)')
 
diff --git a/resources/lib/API.py b/resources/lib/API.py
index 50e5587b..3239f60b 100644
--- a/resources/lib/API.py
+++ b/resources/lib/API.py
@@ -84,6 +84,7 @@ class API():
         width = ''
         aspectratio = '1:1'
         aspectfloat = 1.85
+        Video3DFormat = ''
 
         if mediaSources == True:
             mediaSources = item.get("MediaSources")
@@ -99,9 +100,10 @@ class API():
                 for mediaStream in MediaStreams:
                     if(mediaStream.get("Type") == "Video"):
                         videocodec = mediaStream.get("Codec")
-                        height = str(mediaStream.get("Height"))
-                        width = str(mediaStream.get("Width"))
+                        height = int(mediaStream.get("Height"))
+                        width = int(mediaStream.get("Width"))
                         aspectratio = mediaStream.get("AspectRatio")
+                        Video3DFormat = item.get("Video3DFormat")
                         if aspectratio != None and len(aspectratio) >= 3:
                             try:
                                 aspectwidth,aspectheight = aspectratio.split(':')
@@ -116,9 +118,30 @@ class API():
                 'audiocodec'    : audiocodec, 
                 'height'        : height,
                 'width'         : width,
-                'aspectratio'   : str(aspectfloat)
+                'aspectratio'   : aspectfloat,
+                '3dformat'      : Video3DFormat
                 }
-                
+    
+    def getChecksum(self, item):
+        # use the etags checksum for this if available
+        # AND the userdata
+        checksum = ""
+        
+        if item.get("Etag") != None:
+            checksum = item.get("Etag") 
+            userData = item.get("UserData")
+        if(userData != None):
+            checksum += str(userData.get("Played"))
+            checksum += str(userData.get("IsFavorite"))
+            if userData.get('UnplayedItemCount') != None:
+                checksum += str(userData.get("UnplayedItemCount"))
+            if userData.get('LastPlayedDate') != None:
+                checksum += str(userData.get("LastPlayedDate"))
+            if userData.get('PlaybackPositionTicks') != None:
+                checksum += str(userData.get("PlaybackPositionTicks"))
+            
+        return checksum
+    
     def getUserData(self, item):
         userData = item.get("UserData")
         resumeTime = 0
@@ -128,9 +151,9 @@ class API():
             else:
                 watched="False"
             if userData.get("IsFavorite") == True:
-                favorite="True"
+                favorite=True
             else:
-                favorite="False"
+                favorite=False
             if(userData.get("Played") == True):
                 playcount="1"
             else:
diff --git a/resources/lib/ConnectionManager.py b/resources/lib/ConnectionManager.py
index f91722d2..0d8bb036 100644
--- a/resources/lib/ConnectionManager.py
+++ b/resources/lib/ConnectionManager.py
@@ -116,12 +116,12 @@ class ConnectionManager():
             return
             
         # Option to play from http
-        setPlayback = xbmcgui.Dialog().yesno("Playback option", "Play your files using HTTP?")
-        if setPlayback == 1:
-            self.logMsg("Playback will be set using HTTP.", 1)
-            addon.setSetting("playFromStream", "true")
-        else:
-            self.logMsg("Playback will be set using SMB.", 1)
+        #setPlayback = xbmcgui.Dialog().yesno("Playback option", "Play your files using HTTP?")
+        #if setPlayback == 1:
+            #self.logMsg("Playback will be set using HTTP.", 1)
+            #addon.setSetting("playFromStream", "true")
+        #else:
+            #self.logMsg("Playback will be set using SMB.", 1)
                 
     def getServerDetails(self):
 
diff --git a/resources/lib/DownloadUtils.py b/resources/lib/DownloadUtils.py
index 92410b2c..390a9d2d 100644
--- a/resources/lib/DownloadUtils.py
+++ b/resources/lib/DownloadUtils.py
@@ -11,8 +11,8 @@ from ClientInformation import ClientInformation
 from requests.packages.urllib3.exceptions import InsecureRequestWarning
 
 # Disable requests logging
-requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
-logging.getLogger("requests").setLevel(logging.WARNING)
+# requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
+# logging.getLogger("requests").setLevel(logging.WARNING)
 
 class DownloadUtils():
     
@@ -67,26 +67,22 @@ class DownloadUtils():
 
     def postCapabilities(self, deviceId):
 
-        # Get sessionId
-        url = "{server}/mediabrowser/Sessions?DeviceId=%s&format=json" % deviceId
-        result = self.downloadUrl(url)
-        # sessionId result
-        self.logMsg("Session result: %s" % result, 2)
-        self.sessionId = result[0][u'Id']
-        self.WINDOW.setProperty('sessionId%s' % self.username, self.sessionId)
+        # Post settings to session
+        url = "{server}/mediabrowser/Sessions/Capabilities/Full"
+        data = {
+            'PlayableMediaTypes': "Audio,Video",
+            'SupportedCommands': "Play,Playstate,SendString,DisplayMessage,PlayNext",
+            'SupportsMediaControl': True
+        }
 
-        # Settings for capabilities
-        playableMediaTypes = "Audio,Video"
-        supportedCommands = "Play,Playstate,SendString,DisplayMessage,PlayNext"
-
-        # Post settings to sessionId
-        url = "{server}/mediabrowser/Sessions/Capabilities?Id=%s&PlayableMediaTypes=%s&SupportedCommands=%s&SupportsMediaControl=True" % (self.sessionId, playableMediaTypes, supportedCommands)
-        data = {}
         self.logMsg("Capabilities URL: %s" % url, 2)
         self.logMsg("PostData: %s" % data, 2)
 
-        self.downloadUrl(url, postBody=data, type="POST")
-        self.logMsg("Posted capabilities to sessionId: %s" % self.sessionId, 1)
+        try:
+            self.downloadUrl(url, postBody=data, type="POST")
+            self.logMsg("Posted capabilities to %s" % self.server, 1)
+        except:
+            self.logMsg("Posted capabilities failed.")
 
     def startSession(self):
 
@@ -99,9 +95,11 @@ class DownloadUtils():
         header = self.getHeader()
 
         # If user enabled host certificate verification
-        if self.sslverify:
-            verify = True
+        try:
+            verify = self.sslverify
             cert = self.sslclient
+        except:
+            self.logMsg("Could not load SSL settings.", 1)
         
         # Start session
         self.s = requests.Session()
@@ -153,52 +151,86 @@ class DownloadUtils():
         timeout = self.timeout
         default_link = ""
 
-        # If user is authenticated
-        if (authenticate):
-            # Get requests session
-            s = self.s
-            # Replace for the real values and append api_key
-            url = url.replace("{server}", self.server, 1)
-            url = url.replace("{UserId}", self.userId, 1)
-            #url = "%s&api_key=%s" % (url, self.token)
-            
-            self.logMsg("URL: %s" % url, 2)
-            # Prepare request
-            if type == "GET":
-                r = s.get(url, json=postBody, timeout=timeout)
-            elif type == "POST":
-                r = s.post(url, json=postBody, timeout=timeout)
-            elif type == "DELETE":
-                r = s.delete(url, json=postBody, timeout=timeout)
-
-        # If user is not authenticated
-        elif not authenticate:
-            
-            self.logMsg("URL: %s" % url, 1)
-            header = self.getHeader(authenticate=False)
-            verifyssl = False
-
-            # If user enables ssl verification
-            try:
-                verifyssl = self.sslverify
-            except AttributeError:
-                pass
-            
-            # Prepare request
-            if type == "GET":
-                r = requests.get(url, json=postBody, headers=header, timeout=timeout, verify=verifyssl)
-            elif type == "POST":
-                r = requests.post(url, json=postBody, headers=header, timeout=timeout, verify=verifyssl)
-        
-        # Process the response
         try:
-            r.raise_for_status()
 
+            # If user is authenticated
+            if (authenticate):
+                # Get requests session
+                try: 
+                    s = self.s
+                    # Replace for the real values and append api_key
+                    url = url.replace("{server}", self.server, 1)
+                    url = url.replace("{UserId}", self.userId, 1)
+                    #url = "%s&api_key=%s" % (url, self.token)
+
+                    self.logMsg("URL: %s" % url, 2)
+                    # Prepare request
+                    if type == "GET":
+                        r = s.get(url, json=postBody, timeout=timeout)
+                    elif type == "POST":
+                        r = s.post(url, json=postBody, timeout=timeout)
+                    elif type == "DELETE":
+                        r = s.delete(url, json=postBody, timeout=timeout)
+                
+                except AttributeError:
+                    
+                    # Get user information
+                    self.username = WINDOW.getProperty('currUser')
+                    self.userId = WINDOW.getProperty('userId%s' % self.username)
+                    self.server = WINDOW.getProperty('server%s' % self.username)
+                    self.token = WINDOW.getProperty('accessToken%s' % self.username)
+                    header = self.getHeader()
+                    verifyssl = False
+                    cert = None
+
+                    # IF user enables ssl verification
+                    try:
+                        if self.addon.getSetting('sslverify') == "true":
+                            verifyssl = True
+                        if self.addon.getSetting('sslcert') != "None":
+                            cert = self.addon.getSetting('sslcert')
+                    except:
+                        self.logMsg("Could not load SSL settings.", 1)
+                        pass
+
+                    # Replace for the real values and append api_key
+                    url = url.replace("{server}", self.server, 1)
+                    url = url.replace("{UserId}", self.userId, 1)
+
+                    self.logMsg("URL: %s" % url, 2)
+                    # Prepare request
+                    if type == "GET":
+                        r = requests.get(url, json=postBody, headers=header, timeout=timeout, cert=cert, verify=verifyssl)
+                    elif type == "POST":
+                        r = requests.post(url, json=postBody, headers=header, timeout=timeout, cert=cert, verify=verifyssl)
+                    elif type == "DELETE":
+                        r = requests.delete(url, json=postBody, headers=header, timeout=timeout, cert=cert, verify=verifyssl)
+
+            # If user is not authenticated
+            elif not authenticate:
+                
+                self.logMsg("URL: %s" % url, 2)
+                header = self.getHeader(authenticate=False)
+                verifyssl = False
+
+                # If user enables ssl verification
+                try:
+                    verifyssl = self.sslverify
+                except AttributeError:
+                    pass
+                
+                # Prepare request
+                if type == "GET":
+                    r = requests.get(url, json=postBody, headers=header, timeout=timeout, verify=verifyssl)
+                elif type == "POST":
+                    r = requests.post(url, json=postBody, headers=header, timeout=timeout, verify=verifyssl)
+        
+            # Process the response
             if r.status_code == 204:
-                # No response in body
+                # No body in the response
                 self.logMsg("====== 204 Success ======", 2)
                 return default_link
-            # Response code 200
+
             elif r.status_code == requests.codes.ok:
                 try: 
                     # UTF-8 - JSON object
@@ -207,13 +239,19 @@ class DownloadUtils():
                     return r
                 except:
                     self.logMsg("Unable to convert the response for: %s" % url, 1)
+            else:
+                r.raise_for_status()
 
             return default_link
         
         # TO REVIEW EXCEPTIONS
         except requests.exceptions.ConnectionError as e:
-            self.logMsg("Server unreachable at: %s" % url, 0)
-            self.logMsg(e, 1)
+            # Make the addon aware of status
+            if WINDOW.getProperty("Server_online") != "false":
+                self.logMsg("Server unreachable at: %s" % url, 0)
+                self.logMsg(e, 2)
+                WINDOW.setProperty("Server_online", "false")
+            pass
 
         except requests.exceptions.ConnectTimeout as e:
             self.logMsg("Server timeout at: %s" % url, 0)
@@ -230,6 +268,7 @@ class DownloadUtils():
                     # Tell UserClient token has been revoked.
                     WINDOW.setProperty("Server_status", "401")
                     self.logMsg("HTTP Error: %s" % e, 0)
+                    xbmcgui.Dialog().notification("Error connecting", "Unauthorized.", xbmcgui.NOTIFICATION_ERROR)
 
             elif (r.status_code == 301) or (r.status_code == 302):
                 # Redirects
diff --git a/resources/lib/KodiMonitor.py b/resources/lib/KodiMonitor.py
index 9accd533..be4688ef 100644
--- a/resources/lib/KodiMonitor.py
+++ b/resources/lib/KodiMonitor.py
@@ -11,8 +11,10 @@ import json
 import Utils as utils
 from WriteKodiDB import WriteKodiDB
 from ReadKodiDB import ReadKodiDB
+from LibrarySync import LibrarySync
 from PlayUtils import PlayUtils
 from DownloadUtils import DownloadUtils
+from PlaybackUtils import PlaybackUtils
 
 class Kodi_Monitor(xbmc.Monitor):
     def __init__(self, *args, **kwargs):
@@ -26,65 +28,7 @@ class Kodi_Monitor(xbmc.Monitor):
     def onNotification  (self,sender,method,data):
         addon = xbmcaddon.Addon(id='plugin.video.emby')
         downloadUtils = DownloadUtils()
-        print "onNotification:" + method + ":" + sender + ":" + str(data)
-        #player started playing an item - 
-        if method == "Player.OnPlay":
-            print "playlist onadd is called"
-            jsondata = json.loads(data)
-            if jsondata != None:
-                if jsondata.has_key("item"):
-                    if jsondata.get("item").has_key("id") and jsondata.get("item").has_key("type"):
-                        id = jsondata.get("item").get("id")
-                        type = jsondata.get("item").get("type")
-                        embyid = ReadKodiDB().getEmbyIdByKodiId(id,type)
 
-                        if embyid != None:
-                           
-                            WINDOW = xbmcgui.Window( 10000 )
-                            
-                            username = WINDOW.getProperty('currUser')
-                            userid = WINDOW.getProperty('userId%s' % username)
-                            server = WINDOW.getProperty('server%s' % username)
-
-                            url = "{server}/mediabrowser/Users/{UserId}/Items/%s?format=json&ImageTypeLimit=1" % embyid
-                            result = downloadUtils.downloadUrl(url)     
-                            
-                            userData = result[u'UserData']
-
-                            playurl = PlayUtils().getPlayUrl(server, embyid, result)
-
-                            watchedurl = "%s/mediabrowser/Users/%s/PlayedItems/%s" % (server, userid, embyid)
-                            positionurl = "%s/mediabrowser/Users/%s/PlayingItems/%s" % (server, userid, embyid)
-                            deleteurl = "%s/mediabrowser/Items/%s" % (server, embyid)
-
-                            # set the current playing info
-                            WINDOW.setProperty(playurl+"watchedurl", watchedurl)
-                            WINDOW.setProperty(playurl+"positionurl", positionurl)
-                            WINDOW.setProperty(playurl+"deleteurl", "")
-                            WINDOW.setProperty(playurl+"deleteurl", deleteurl)
-                            if result[u'Type']=="Episode":
-                                WINDOW.setProperty(playurl+"refresh_id", result[u'SeriesId'])
-                            else:
-                                WINDOW.setProperty(playurl+"refresh_id", embyid)
-                                
-                            WINDOW.setProperty(playurl+"runtimeticks", str(result[u'RunTimeTicks']))
-                            WINDOW.setProperty(playurl+"type", result[u'Type'])
-                            WINDOW.setProperty(playurl+"item_id", embyid)
-
-                            if PlayUtils().isDirectPlay(result) == True:
-                                playMethod = "DirectPlay"
-                            else:
-                                playMethod = "Transcode"
-
-                            WINDOW.setProperty(playurl+"playmethod", playMethod)
-                                
-                            mediaSources = result[u'MediaSources']
-                            if(mediaSources != None):
-                                if mediaSources[0].get('DefaultAudioStreamIndex') != None:
-                                    WINDOW.setProperty(playurl+"AudioStreamIndex", str(mediaSources[0][u'DefaultAudioStreamIndex']))  
-                                if mediaSources[0].get('DefaultSubtitleStreamIndex') != None:
-                                    WINDOW.setProperty(playurl+"SubtitleStreamIndex", str(mediaSources[0][u'DefaultSubtitleStreamIndex']))
-        
         if method == "VideoLibrary.OnUpdate":
             jsondata = json.loads(data)
             if jsondata != None:
@@ -97,6 +41,12 @@ class Kodi_Monitor(xbmc.Monitor):
                     utils.logMsg("MB# Sync","Kodi_Monitor--> VideoLibrary.OnUpdate : " + str(data),2)
                     WriteKodiDB().updatePlayCountFromKodi(item, type, playcount)
                     
-                
+        if method == "System.OnWake":
+            xbmc.sleep(10000) #Allow network to wake up
+            utils.logMsg("Doing_Db_Sync Post Resume: syncDatabase (Started)",1)
+            libSync = LibrarySync().FullLibrarySync()
+            utils.logMsg("Doing_Db_Sync Post Resume: syncDatabase (Finished) " + str(libSync),1)
+            
+        
                 
 
diff --git a/resources/lib/LibrarySync.py b/resources/lib/LibrarySync.py
index b6135af4..5e8cb15e 100644
--- a/resources/lib/LibrarySync.py
+++ b/resources/lib/LibrarySync.py
@@ -12,6 +12,7 @@ import inspect
 import threading
 import urllib
 from datetime import datetime, timedelta, time
+from itertools import chain
 import urllib2
 import os
 
@@ -27,18 +28,27 @@ dataPath = os.path.join(addondir,"library")
 movieLibrary = os.path.join(dataPath,'movies')
 tvLibrary = os.path.join(dataPath,'tvshows')
 
+WINDOW = xbmcgui.Window( 10000 )
+
 class LibrarySync():   
         
-    def syncDatabase(self):
+    def FullLibrarySync(self):
         
         #set some variable to check if this is the first run
         addon = xbmcaddon.Addon(id='plugin.video.emby')
-        WINDOW = xbmcgui.Window( 10000 )
-
+        
         startupDone = WINDOW.getProperty("startup") == "done"
         syncInstallRunDone = addon.getSetting("SyncInstallRunDone") == "true"
+        dbSyncIndication = addon.getSetting("dbSyncIndication") == "true"
         WINDOW.setProperty("SyncDatabaseRunning", "true")
         
+        
+        #show the progress dialog
+        pDialog = None
+        if (syncInstallRunDone == False or dbSyncIndication):
+            pDialog = xbmcgui.DialogProgressBG()
+            pDialog.create('Emby for Kodi', 'Performing full sync')
+        
         if(WINDOW.getProperty("SyncDatabaseShouldStop") ==  "true"):
             utils.logMsg("Sync Database", "Can not start SyncDatabaseShouldStop=True", 0)
             return True
@@ -47,947 +57,370 @@ class LibrarySync():
             completed = True
             connection = utils.KodiSQL()
             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()
+            
             # sync movies
-            if(syncInstallRunDone == False): # on first install run do a full sync with model progress dialog
-                completed = completed and self.TvShowsSync(connection, cursor,True, True)
-                completed = completed and self.MoviesSync(connection, cursor,True, True)
-                completed = completed and self.MusicVideosSync(True, True,connection , cursor)
-            elif(startupDone == False): # on first run after startup do a inc then a full sync
-                self.TvShowsSync(connection, cursor,False, False)
-                self.MoviesSync(connection, cursor,False, False)
-                self.MusicVideosSync(False, False, connection,cursor)
-                self.TvShowsSync(connection, cursor,True, False)
-                self.MoviesSync(connection, cursor,True, False)
-                self.MusicVideosSync(True, False,connection,cursor)
-            else: # on scheduled sync do a full sync
-                self.TvShowsSync(connection, cursor,True, False)
-                self.MoviesSync(connection, cursor,True, False)
-                self.MusicVideosSync(True, False,connection,cursor)
-           
+            self.MoviesFullSync(connection,cursor,pDialog)
+            
+            if (self.ShouldStop()):
+                return False
+            
+            #sync Tvshows and episodes
+            self.TvShowsFullSync(connection,cursor,pDialog)
+            
+            if (self.ShouldStop()):
+                return False
+                    
+            # sync musicvideos
+            self.MusicVideosFullSync(connection,cursor,pDialog)
+            
             # set the install done setting
             if(syncInstallRunDone == False and completed):
                 addon = xbmcaddon.Addon(id='plugin.video.emby') #force a new instance of the addon
                 addon.setSetting("SyncInstallRunDone", "true")        
             
+            # Commit all DB changes at once and Force refresh the library
+            xbmc.executebuiltin("UpdateLibrary(video)")
+            
             # set prop to show we have run for the first time
             WINDOW.setProperty("startup", "done")
             
         finally:
             WINDOW.setProperty("SyncDatabaseRunning", "false")
             utils.logMsg("Sync DB", "syncDatabase Exiting", 0)
+            
             cursor.close()
-            
+
+        if(pDialog != None):
+            pDialog.close()
+        
         return True      
-    
-    def MoviesSync(self,connection, cursor, fullsync, installFirstRun,itemList = []):
-
-        WINDOW = xbmcgui.Window( 10000 )
-        pDialog = None
-        startedSync = datetime.today()
-        
-        try:
-            addon = xbmcaddon.Addon(id='plugin.video.emby')
-            dbSyncIndication = addon.getSetting("dbSyncIndication")
-                
-            if(installFirstRun or dbSyncIndication == "Dialog Progress"):
-                pDialog = xbmcgui.DialogProgress()
-            elif(dbSyncIndication == "BG Progress"):
-                pDialog = xbmcgui.DialogProgressBG()
-            
-            if(pDialog != None):
-                pDialog.create('Sync DB', 'Sync DB')
-                
-            totalItemsAdded = 0
-            totalItemsUpdated = 0
-            totalItemsDeleted = 0
-            
-            allEmbyMovieIds = list()
-                
-            views = ReadEmbyDB().getCollections("movies")
-            viewCount = len(views)
-            viewCurrent = 1
-            progressTitle = ""
-            
-            for view in views:
-                
-                #process new movies
-                allMB3Movies = ReadEmbyDB().getMovies(id = view.get('id'), fullinfo=True, fullSync = fullsync, itemList = itemList)
-                allKodiIds = set(ReadKodiDB().getKodiMoviesIds(True))
-            
-                if(self.ShouldStop(pDialog)):
-                    return False            
-            
-                if(allMB3Movies == None):
-                    return False
-            
-                if(pDialog != None):
-                    progressTitle = "Sync DB : Processing " + view.get('title') + " " + str(viewCurrent) + " of " + str(viewCount)
-                    pDialog.update(0, progressTitle)
-                    total = len(allMB3Movies) + 1
-                    count = 1
-                
-                for item in allMB3Movies:
-                    
-                    if not item.get('IsFolder'):                    
-                        allEmbyMovieIds.append(item["Id"])
-                        item['Tag'] = []
-                        item['Tag'].append(view.get('title'))
-                        
-                        if item["Id"] not in allKodiIds:
-                            WriteKodiDB().addMovieToKodiLibrary(item,connection, cursor)
-                            totalItemsAdded += 1
-                        
-                        if(self.ShouldStop(pDialog)):
-                            return False
-                    
-                        # update progress bar
-                        if(pDialog != None):
-                            percentage = int(((float(count) / float(total)) * 100))
-                            pDialog.update(percentage, progressTitle, "Adding Movie: " + str(count))
-                            count += 1
-                
-                if(self.ShouldStop(pDialog)):
-                    return False
-
-                if(pDialog != None):
-                    progressTitle = "Sync DB : Processing " + view.get('title') + " " + str(viewCurrent) + " of " + str(viewCount)
-                    pDialog.update(0, progressTitle, "")
-                    total = len(allMB3Movies) + 1
-                    count = 1                    
-
-                #process updates
-                allKodiMovies = ReadKodiDB().getKodiMovies(True)
-                for item in allMB3Movies:
-                    
-                    if not item.get('IsFolder'):
-                        item['Tag'] = []
-                        item['Tag'].append(view.get('title'))
-                        
-                        if allKodiMovies != None:
-                            kodimovie = allKodiMovies.get(item["Id"], None)
-                        else:
-                            kodimovie = None
-                            
-                        userData = API().getUserData(item)                       
-                        
-                        if(kodimovie != None):
-                            updated = WriteKodiDB().updateMovieToKodiLibrary_Batched(item, kodimovie, connection, cursor)
-                            if(updated):
-                                totalItemsUpdated += 1
-                        
-                        if(self.ShouldStop(pDialog)):
-                            return False
-                    
-                        # update progress bar
-                        if(pDialog != None):
-                            percentage = int(((float(count) / float(total)) * 100))
-                            pDialog.update(percentage, progressTitle, "Updating Movie: " + str(count))
-                            count += 1
-                
-                viewCurrent += 1
-                
-            # process box sets - TODO cope with movies removed from a set
-            if fullsync:
-
-                if(pDialog != None):
-                    progressTitle = "Sync DB : BoxSets"
-                    pDialog.update(0, progressTitle, "Retrieving Boxset List")
-                            
-                utils.logMsg("Sync Movies", "BoxSet Sync Started", 1)
-                boxsets = ReadEmbyDB().getBoxSets()
-                
-                if(pDialog != None):
-                    total = len(boxsets) + 1
-                    count = 1                
-
-                for boxset in boxsets:
-                    if(pDialog != None):
-                        percentage = int(((float(count) / float(total)) * 100))
-                        pDialog.update(percentage, progressTitle, "Updating BoxSet: " + str(count) + " of " + str(total))
-                        count += 1
-                    if(self.ShouldStop(pDialog)):
-                        return False                
-                    boxsetMovies = ReadEmbyDB().getMoviesInBoxSet(boxset["Id"])
-                    WriteKodiDB().addBoxsetToKodiLibrary(boxset,connection, cursor)
-                    
-                    for boxsetMovie in boxsetMovies:
-                        if(self.ShouldStop(pDialog)):
-                            return False
-                        WriteKodiDB().updateBoxsetToKodiLibrary(boxsetMovie,boxset)
-                        
-                utils.logMsg("Sync Movies", "BoxSet Sync Finished", 1)                
-                
-            if(pDialog != None):
-                progressTitle = "Removing Deleted Items"
-                pDialog.update(0, progressTitle, "")
-            
-            if(self.ShouldStop(pDialog)):
-                return False            
-            
-            # process any deletes only at fullsync
-            if fullsync:
-                allKodiIds = ReadKodiDB().getKodiMoviesIds(True)
-                allEmbyMovieIds = set(allEmbyMovieIds)
-                for kodiId in allKodiIds:
-                    if not kodiId in allEmbyMovieIds:
-                        WINDOW.setProperty(kodiId,"deleted")
-                        WriteKodiDB().deleteMovieFromKodiLibrary(kodiId)
-                        totalItemsDeleted += 1
-            
-            if(self.ShouldStop(pDialog)):
-                return False            
-            
-            # display notification if set up
-            notificationString = ""
-            if(totalItemsAdded > 0):
-                notificationString += "Added:" + str(totalItemsAdded) + " "
-            if(totalItemsUpdated > 0):
-                notificationString += "Updated:" + str(totalItemsUpdated) + " "
-            if(totalItemsDeleted > 0):
-                notificationString += "Deleted:" + str(totalItemsDeleted) + " "
-                
-            timeTaken = datetime.today() - startedSync
-            timeTakenString = str(int(timeTaken.seconds / 60)) + ":" + str(timeTaken.seconds % 60)
-            utils.logMsg("Sync Movies", "Finished " + timeTakenString + " " + notificationString, 0)
-            
-            if(dbSyncIndication == "Notify OnChange" and notificationString != ""):
-                notificationString = "(" + timeTakenString + ") " + notificationString
-                xbmc.executebuiltin("XBMC.Notification(Movie Sync: " + notificationString + ",)")
-            elif(dbSyncIndication == "Notify OnFinish"):
-                if(notificationString == ""):
-                    notificationString = "Done"
-                notificationString = "(" + timeTakenString + ") " + notificationString
-                xbmc.executebuiltin("XBMC.Notification(Movie Sync: " + notificationString + ",)")
-
-        finally:
-            if(pDialog != None):
-                pDialog.close()
-        
-        return True
-        
-    def TvShowsSync(self, connection, cursor ,fullsync, installFirstRun, itemList = []):
-
-        addon = xbmcaddon.Addon(id='plugin.video.emby')
-        WINDOW = xbmcgui.Window( 10000 )
-        pDialog = None
-        startedSync = datetime.today()
-        
-        try:
-            dbSyncIndication = addon.getSetting("dbSyncIndication")
-                
-            if(installFirstRun or dbSyncIndication == "Dialog Progress"):
-                pDialog = xbmcgui.DialogProgress()
-            elif(dbSyncIndication == "BG Progress"):
-                pDialog = xbmcgui.DialogProgressBG()
-                
-            if(pDialog != None):
-                pDialog.create('Sync DB', 'Sync DB')
-                
-            totalItemsAdded = 0
-            totalItemsUpdated = 0
-            totalItemsDeleted = 0                
-            allTVShows = list()
-            allMB3EpisodeIds = list() #for use with deletions
-            allKodiEpisodeIds = [] # for use with deletions            
-            
-            views = ReadEmbyDB().getCollections("tvshows")
-            viewCount = len(views)
-            viewCurrent = 1
-            progressTitle = ""
-
-            for view in views:
-            
-                progressTitle = "Sync DB : Processing " + view.get('title') + " " + str(viewCurrent) + " of " + str(viewCount)
-                
-                # incremental sync --> new episodes only
-                if fullsync == False:
-                    
-                    latestMBEpisodes = ReadEmbyDB().getLatestEpisodes(fullinfo = True, itemList = itemList)
-                    utils.logMsg("Sync TV", "Inc Sync Started on : " + str(len(latestMBEpisodes)) + " : " + str(itemList), 1)
-                    
-                    if latestMBEpisodes != None:
-                        allKodiTvShowsIds = set(ReadKodiDB().getKodiTvShowsIds(True))
-                        
-                        # get included TV Shows
-                        showList = []
-                        for episode in latestMBEpisodes:
-                            if(episode["SeriesId"] not in showList):
-                                showList.append(episode["SeriesId"])
-                        
-                        utils.logMsg("Incremental TV Sync", "Included TV Show List : " + str(showList), 0)
-                        
-                        if(pDialog != None):
-                            pDialog.update(0, progressTitle)
-                            total = len(showList) + 1
-                            count = 1                           
-                        
-                        # process included TV Shows
-                        for showID in showList:
-                        
-                            embyTvShow = ReadEmbyDB().getFullItem(showID)
-                        
-                            if(showID not in allKodiTvShowsIds):
-                                utils.logMsg("Incremental TV Sync", "Adding TV Show : " + embyTvShow.get("Name"), 1)
-                                WriteKodiDB().addTVShowToKodiLibrary(embyTvShow, connection, cursor)
-                            
-                            kodiTvShow = ReadKodiDB().getKodiTVShow(showID)
-                            utils.logMsg("Incremental TV Sync", "Updating  TV Show : " + embyTvShow.get("Name"), 1)
-                            WriteKodiDB().updateTVShowToKodiLibrary(embyTvShow, kodiTvShow, connection, cursor)
-
-                            # update progress bar
-                            if(pDialog != None):
-                                percentage = int(((float(count) / float(total)) * 100))
-                                pDialog.update(percentage, progressTitle, "Processing TV Shows : " + str(count))
-                                count += 1
-                        
-                        if(pDialog != None):
-                            pDialog.update(0, progressTitle)
-                            total = len(latestMBEpisodes) + 1
-                            count = 1
-                            
-                        # process new episodes
-                        for episode in latestMBEpisodes:                               
-                            if(self.ShouldStop(pDialog)):
-                                return False                
-
-                            WriteKodiDB().addEpisodeToKodiLibrary(episode, connection, cursor)
-                            progressAction = "Adding"
-                            totalItemsAdded += 1                 
-                            
-                            # update progress bar
-                            if(pDialog != None):
-                                percentage = int(((float(count) / float(total)) * 100))
-                                pDialog.update(percentage, progressTitle, progressAction + " Episode: " + str(count))
-                                count += 1    
-                        
-                        #process updates
-                        if(pDialog != None):
-                            progressTitle = "Sync DB : Processing Episodes"
-                            pDialog.update(0, progressTitle)
-                            total = len(latestMBEpisodes) + 1
-                            count = 1
-                                    
-                        for episode in latestMBEpisodes:
-                            if(self.ShouldStop(pDialog)):
-                                return False                           
-                            allKodiTVShows = ReadKodiDB().getKodiTvShows(False)
-                            kodishow = allKodiTVShows.get(episode["SeriesId"],None)
-                            kodiEpisodes = ReadKodiDB().getKodiEpisodes(kodishow["tvshowid"],True,True)
-                            
-                            if(self.ShouldStop(pDialog)):
-                                return False   
-
-                            userData = API().getUserData(episode)
-
-                            if kodiEpisodes != None:
-                                KodiItem = kodiEpisodes.get(episode.get("Id"), None)
-                                if(KodiItem != None): 
-                                    WriteKodiDB().updateEpisodeToKodiLibrary(episode, KodiItem, connection, cursor)
-                                        
-                            if(self.ShouldStop(pDialog)):
-                                return False                        
-
-                            # update progress bar
-                            if(pDialog != None):
-                                percentage = int(((float(count) / float(total)) * 100))
-                                pDialog.update(percentage, progressTitle, "Updating Episode: " + str(count))
-                                count += 1    
-                        
-                
-                # full sync --> Tv shows and Episodes
-                if fullsync:
-                    viewTVShows = list()
-                    tvShowData = ReadEmbyDB().getTVShows(id = view.get('id') , fullinfo = True, fullSync = True)
-                    allKodiIds = set(ReadKodiDB().getKodiTvShowsIds(True))
-                    
-                    if(self.ShouldStop(pDialog)):
-                        return False            
-                    
-                    if (tvShowData == None):
-                        return False
-                        
-                    if(pDialog != None):
-                        progressTitle = "Sync DB : Processing TV Shows"
-                        pDialog.update(0, progressTitle)
-                        total = len(tvShowData) + 1
-                        count = 1
-                        
-                    # add TV Shows
-                    for item in tvShowData:
-                        if item.get('IsFolder') and item.get('RecursiveItemCount') != 0:
-                            allTVShows.append(item["Id"])
-                            viewTVShows.append(item["Id"])
-                            item['Tag'] = []
-                            item['Tag'].append(view.get('title'))                            
-                            progMessage = "Processing"
-                            if item["Id"] not in allKodiIds:
-                                WriteKodiDB().addTVShowToKodiLibrary(item,connection, cursor)
-                                totalItemsAdded += 1
-                                
-                            if(self.ShouldStop(pDialog)):
-                                return False
-                                
-                            # update progress bar
-                            if(pDialog != None):
-                                percentage = int(((float(count) / float(total)) * 100))
-                                pDialog.update(percentage, progressTitle, "Adding Tv Show: " + str(count))
-                                count += 1                        
-                            
-                    if(pDialog != None):
-                        progressTitle = "Sync DB : Processing TV Shows"
-                        pDialog.update(0, progressTitle, "")
-                        total = len(viewTVShows) + 1
-                        count = 1                    
-                    
-                    # update TV Shows
-                    allKodiTVShows = ReadKodiDB().getKodiTvShows(True)
-                    for item in tvShowData:
-                        if item.get('IsFolder'):
-                            item['Tag'] = []
-                            item['Tag'].append(view.get('title'))
-                            if allKodiTVShows != None:
-                                kodishow = allKodiTVShows.get(item["Id"],None)
-                            else:
-                                kodishow = None
-                            
-                            if(kodishow != None):
-                                updated = WriteKodiDB().updateTVShowToKodiLibrary(item,kodishow,connection, cursor)
-                                if(updated):
-                                    totalItemsUpdated += 1
-                                
-                            if(self.ShouldStop(pDialog)):
-                                return False
-                                
-                            # update progress bar
-                            if(pDialog != None):
-                                percentage = int(((float(count) / float(total)) * 100))
-                                pDialog.update(percentage, progressTitle, "Updating Tv Show: " + str(count))
-                                count += 1                              
-
-                                
-                    # do episode adds
-                    allEpisodes = list()
-                    showTotal = len(viewTVShows)
-                    showCurrent = 1                    
-                    for tvshow in viewTVShows:
-                        
-                        episodeData = ReadEmbyDB().getEpisodes(tvshow,True)                       
-                        if episodeData != None:
-                            
-                            if(self.ShouldStop(pDialog)):
-                                return False                
-                            
-                            if(pDialog != None):
-                                progressTitle = "Sync DB : Processing Tv Show " + str(showCurrent) + " of " + str(showTotal)
-                                pDialog.update(0, progressTitle)
-                                total = len(episodeData) + 1
-                                count = 0         
-    
-                            for item in episodeData:
-                            
-                                if(self.ShouldStop(pDialog)):
-                                    return False        
-                                    
-                                progressAction = "Adding"
-                                WriteKodiDB().addEpisodeToKodiLibrary(item, connection, cursor)
-                                
-                                # update progress bar
-                                if(pDialog != None):
-                                    percentage = int(((float(count) / float(total)) * 100))
-                                    pDialog.update(percentage, progressTitle, progressAction + " Episode: " + str(count))
-                                    count += 1
-                                    
-                            showCurrent += 1
-                                            
-                    # do episode updates
-                    showCurrent = 1
-                    for tvshow in viewTVShows:
-                        episodeData = ReadEmbyDB().getEpisodes(tvshow,True)
-                        
-                        kodiEpisodes = None
-                        allKodiTVShows = ReadKodiDB().getKodiTvShows(False)
-                        if allKodiTVShows != None:
-                            kodishow = allKodiTVShows.get(tvshow,None)
-                            if kodishow != None:
-                                kodiEpisodes = ReadKodiDB().getKodiEpisodes(kodishow["tvshowid"],True,True)
-                        
-                        if(self.ShouldStop(pDialog)):
-                            return False                
-                        
-                        if(pDialog != None):
-                            progressTitle = "Sync DB : Processing Tv Show " + str(showCurrent) + " of " + str(showTotal)
-                            pDialog.update(0, progressTitle)
-                            total = len(episodeData) + 1
-                            count = 0         
-    
-                        #we have to compare the lists somehow
-                        for item in episodeData:
-                            #add episodeId to the list of all episodes for use later on the deletes
-                            allMB3EpisodeIds.append(item["Id"])
-                            
-                            matchFound = False
-    
-                            userData = API().getUserData(item)
-                            
-                            if kodiEpisodes != None:
-                                KodiItem = kodiEpisodes.get(item.get("Id"), None)
-                                if(KodiItem != None):
-                                    updated = WriteKodiDB().updateEpisodeToKodiLibrary(item, KodiItem, connection, cursor)
-                                    if(updated):
-                                        totalItemsUpdated += 1                                
-                            
-                            if(self.ShouldStop(pDialog)):
-                                return False                        
-                                
-                            # update progress bar
-                            if(pDialog != None):
-                                percentage = int(((float(count) / float(total)) * 100))
-                                pDialog.update(percentage, progressTitle, "Updating Episode: " + str(count))
-                                count += 1
-                        
-                        
-                        #add all kodi episodes to a list with episodes for use later on to delete episodes
-                        #the mediabrowser ID is set as uniqueID in the NFO... for some reason this has key 'unknown' in the json response
-                        if kodishow != None:
-                            show = ReadKodiDB().getKodiEpisodes(kodishow["tvshowid"],False,False)
-                            if show != None:
-                                for episode in show:
-                                    dict = {'episodeid': str(episode["uniqueid"]["unknown"]),'tvshowid': tvshow}
-                                    allKodiEpisodeIds.append(dict)
-                        
-                        showCurrent += 1                  
-                    
-            if(pDialog != None):
-                progressTitle = "Removing Deleted Items"
-                pDialog.update(0, progressTitle)
+      
+    def MoviesFullSync(self,connection,cursor, pDialog):
                
-            if(self.ShouldStop(pDialog)):
-                return False            
+        views = ReadEmbyDB().getCollections("movies")
+        
+        allKodiMovieIds = list()
+        allEmbyMovieIds = list()
+        
+        for view in views:
+            
+            allEmbyMovies = ReadEmbyDB().getMovies(view.get('id'))
+            allKodiMovies = ReadKodiDB().getKodiMovies(connection, cursor)
+            
+            for kodimovie in allKodiMovies:
+                allKodiMovieIds.append(kodimovie[1])
+            
+            total = len(allEmbyMovies) + 1
+            count = 1
+            
+            #### PROCESS ADDS AND UPDATES ###
+            for item in allEmbyMovies:
                 
-            # DELETES -- EPISODES
-            # process any deletes only at fullsync
-            allMB3EpisodeIdsSet = set(allMB3EpisodeIds)
-            for episode in allKodiEpisodeIds:
-                if episode.get('episodeid') not in allMB3EpisodeIdsSet:
-                    WINDOW.setProperty("embyid" + str(episode.get('episodeid')),"deleted")
-                    WriteKodiDB().deleteEpisodeFromKodiLibrary(episode.get('episodeid'),episode.get('tvshowid'))
-                    totalItemsDeleted += 1
-            
-            # DELETES -- TV SHOWS
-            if fullsync:
-                allKodiShows = ReadKodiDB().getKodiTvShowsIds(True)
-                allMB3TVShows = set(allTVShows)
-                for show in allKodiShows:
-                    if not show in allMB3TVShows:
-                        WriteKodiDB().deleteTVShowFromKodiLibrary(show)
-                        totalItemsDeleted += 1
-            
-            if(self.ShouldStop(pDialog)):
-                return False            
-    
-            # display notification if set up
-            notificationString = ""
-            if(totalItemsAdded > 0):
-                notificationString += "Added:" + str(totalItemsAdded) + " "
-            if(totalItemsUpdated > 0):
-                notificationString += "Updated:" + str(totalItemsUpdated) + " "
-            if(totalItemsDeleted > 0):
-                notificationString += "Deleted:" + str(totalItemsDeleted) + " "
+                if (self.ShouldStop()):
+                    return False
                 
-            timeTaken = datetime.today() - startedSync
-            timeTakenString = str(int(timeTaken.seconds / 60)) + ":" + str(timeTaken.seconds % 60)
-            utils.logMsg("Sync Episodes", "Finished " + timeTakenString + " " + notificationString, 0)
-            
-            if(dbSyncIndication == "Notify OnChange" and notificationString != ""):
-                notificationString = "(" + timeTakenString + ") " + notificationString
-                xbmc.executebuiltin("XBMC.Notification(Episode Sync: " + notificationString + ",)")
-            elif(dbSyncIndication == "Notify OnFinish"):
-                if(notificationString == ""):
-                    notificationString = "Done"
-                notificationString = "(" + timeTakenString + ") " + notificationString
-                xbmc.executebuiltin("XBMC.Notification(Episode Sync: " + notificationString + ",)")
-
-        finally:
-            if(pDialog != None):
-                pDialog.close()
-        
-        return True
-    
-    def MusicVideosSync(self, fullsync, installFirstRun,connection, cursor):
-        
-        addon = xbmcaddon.Addon(id='plugin.video.emby')
-        WINDOW = xbmcgui.Window( 10000 )
-        pDialog = None
-        
-        try:
-            dbSyncIndication = addon.getSetting("dbSyncIndication")
-                
-            if(installFirstRun or dbSyncIndication == "Dialog Progress"):
-                pDialog = xbmcgui.DialogProgress()
-            elif(dbSyncIndication == "BG Progress"):
-                pDialog = xbmcgui.DialogProgressBG()
-            
-            if(pDialog != None):
-                pDialog.create('Sync DB', 'Sync DB')
-                
-            allEmbyMusicVideoIds = list()
-
-            progressTitle = ""
-            
-            #process new musicvideos
-            allMB3MusicVideos = ReadEmbyDB().getMusicVideos(True, fullsync)
-            allKodiIds = set(ReadKodiDB().getKodiMusicVideoIds(True))
-        
-            if(self.ShouldStop(pDialog)):
-                return False            
-        
-            if(allMB3MusicVideos == None):
-                return False
-        
-            if(pDialog != None):
-                progressTitle = "Sync DB : Processing Musicvideos"
-                pDialog.update(0, progressTitle)
-                total = len(allMB3MusicVideos) + 1
-                count = 1
-            
-            for item in allMB3MusicVideos:
-                
-                if not item.get('IsFolder'):
-                    allEmbyMusicVideoIds.append(item["Id"])
+                if not item.get('IsFolder'):                    
+                    allEmbyMovieIds.append(item["Id"])
                     
-                    if item["Id"] not in allKodiIds:
-                        WriteKodiDB().addMusicVideoToKodiLibrary(item, connection, cursor)
-                    
-                    if(self.ShouldStop(pDialog)):
-                        return False
-                
-                    # update progress bar
                     if(pDialog != None):
-                        percentage = int(((float(count) / float(total)) * 100))
-                        pDialog.update(percentage, progressTitle, "Adding Musicvideo: " + str(count))
-                        count += 1
-            
-            if(self.ShouldStop(pDialog)):
-                return False
-
-            if(pDialog != None):
-                progressTitle = "Sync DB : Processing musicvideos"
-                pDialog.update(0, progressTitle, "")
-                total = len(allMB3MusicVideos) + 1
-                count = 1                    
-            
-            #process updates
-            allKodiMusicVideos = ReadKodiDB().getKodiMusicVideos(True)
-            for item in allMB3MusicVideos:
-                
-                if not item.get('IsFolder'):
+                        progressTitle = "Processing " + view.get('title') + " (" + str(count) + " of " + str(total) + ")"
+                        pDialog.update(0, "Emby for Kodi - Running Sync", progressTitle)
+                        count += 1        
                     
-                    if allKodiMusicVideos != None:
-                        kodimusicvideo = allKodiMusicVideos.get(item["Id"], None)
+                    kodiMovie = None
+                    for kodimovie in allKodiMovies:
+                        if kodimovie[1] == item["Id"]:
+                            kodiMovie = kodimovie
+                          
+                    if kodiMovie == None:
+                        WriteKodiDB().addOrUpdateMovieToKodiLibrary(item["Id"],connection, cursor, view.get('title'))
                     else:
-                        kodimusicvideo = None
+                        if kodiMovie[2] != API().getChecksum(item):
+                            WriteKodiDB().addOrUpdateMovieToKodiLibrary(item["Id"],connection, cursor, view.get('title'))
+          
+          
+       
+        #### PROCESS BOX SETS #####
+        if(pDialog != None):
+            utils.logMsg("Sync Movies", "BoxSet Sync Started", 1)
+            boxsets = ReadEmbyDB().getBoxSets()
+            
+            total = len(boxsets) + 1
+            count = 1
+            for boxset in boxsets:
+                progressTitle = "Processing BoxSets"+ " (" + str(count) + " of " + str(total) + ")"                
+                pDialog.update(0, "Emby for Kodi - Running Sync", progressTitle)
+                count += 1
+                if(self.ShouldStop()):
+                    return False                
+                boxsetMovies = ReadEmbyDB().getMoviesInBoxSet(boxset["Id"])
+                WriteKodiDB().addBoxsetToKodiLibrary(boxset,connection, cursor)
                     
-                    if(kodimusicvideo != None):
-                        WriteKodiDB().updateMusicVideoToKodiLibrary_Batched(item, kodimusicvideo)
-                    
-                    if(self.ShouldStop(pDialog)):
+                for boxsetMovie in boxsetMovies:
+                    if(self.ShouldStop()):
                         return False
+                    WriteKodiDB().updateBoxsetToKodiLibrary(boxsetMovie,boxset, connection, cursor)
+                        
+            utils.logMsg("Sync Movies", "BoxSet Sync Finished", 1)    
+            
+        #### PROCESS DELETES #####
+        allEmbyMovieIds = set(allEmbyMovieIds)
+        for kodiId in allKodiMovieIds:
+            if not kodiId in allEmbyMovieIds:
+                WINDOW.setProperty(kodiId,"deleted")
+                WriteKodiDB().deleteItemFromKodiLibrary(kodiId, connection, cursor)
                 
-                    # update progress bar
-                    if(pDialog != None):
-                        percentage = int(((float(count) / float(total)) * 100))
-                        pDialog.update(percentage, progressTitle, "Updating MusicVideo: " + str(count))
-                        count += 1
+        ### commit all changes to database ###
+        connection.commit()
 
+    def MusicVideosFullSync(self,connection,cursor, pDialog):
+               
+        allKodiMusicvideoIds = list()
+        allEmbyMusicvideoIds = list()
+            
+        allEmbyMusicvideos = ReadEmbyDB().getMusicVideos()
+        allKodiMusicvideos = ReadKodiDB().getKodiMusicVideos(connection, cursor)
+        
+        for kodivideo in allKodiMusicvideos:
+            allKodiMusicvideoIds.append(kodivideo[1])
+        
+        total = len(allEmbyMusicvideos) + 1
+        count = 1
+        
+        #### PROCESS ADDS AND UPDATES ###
+        for item in allEmbyMusicvideos:
+            
+            if (self.ShouldStop()):
+                return False
+            
+            if not item.get('IsFolder'):                    
+                allEmbyMusicvideoIds.append(item["Id"])
                 
-            if(pDialog != None):
-                progressTitle = "Removing Deleted Items"
-                pDialog.update(0, progressTitle, "")
+                if(pDialog != None):
+                    progressTitle = "Processing MusicVideos (" + str(count) + " of " + str(total) + ")"
+                    pDialog.update(0, "Emby for Kodi - Running Sync", progressTitle)
+                    count += 1        
+                
+                kodiVideo = None
+                for kodivideo in allKodiMusicvideos:
+                    if kodivideo[1] == item["Id"]:
+                        kodiVideo = kodivideo
+                      
+                if kodiVideo == None:
+                    WriteKodiDB().addOrUpdateMusicVideoToKodiLibrary(item["Id"],connection, cursor)
+                else:
+                    if kodiVideo[2] != API().getChecksum(item):
+                        WriteKodiDB().addOrUpdateMusicVideoToKodiLibrary(item["Id"],connection, cursor)
             
-            if(self.ShouldStop(pDialog)):
-                return False            
-            
-            # process any deletes only at fullsync
-            if fullsync:
-                allKodiIds = ReadKodiDB().getKodiMusicVideoIds(True)
-                allEmbyMusicVideoIds = set(allEmbyMusicVideoIds)
-                for kodiId in allKodiIds:
-                    if not kodiId in allEmbyMusicVideoIds:
-                        WriteKodiDB().deleteMusicVideoFromKodiLibrary(kodiId)
-            
-            if(self.ShouldStop(pDialog)):
-                return False            
-            
-        finally:
-            if(pDialog != None):
-                pDialog.close()
+        #### PROCESS DELETES #####
+        allEmbyMusicvideoIds = set(allEmbyMusicvideoIds)
+        for kodiId in allKodiMusicvideoIds:
+            if not kodiId in allEmbyMusicvideoIds:
+                WINDOW.setProperty(kodiId,"deleted")
+                WriteKodiDB().deleteItemFromKodiLibrary(kodiId, connection, cursor)
+                
+        ### commit all changes to database ###
+        connection.commit()
+    
+    def TvShowsFullSync(self,connection,cursor,pDialog):
+               
+        views = ReadEmbyDB().getCollections("tvshows")
         
-        return True  
+        allKodiTvShowIds = list()
+        allEmbyTvShowIds = list()
+                
+        for view in views:
+            
+            allEmbyTvShows = ReadEmbyDB().getTvShows(view.get('id'))
+            allKodiTvShows = ReadKodiDB().getKodiTvShows(connection, cursor)
+            
+            total = len(allEmbyTvShows) + 1
+            count = 1
+            
+            for kodishow in allKodiTvShows:
+                allKodiTvShowIds.append(kodishow[1])
+            
 
-    def updatePlayCounts(self):
-        #update all playcounts from MB3 to Kodi library
+            #### TVSHOW: PROCESS ADDS AND UPDATES ###
+            for item in allEmbyTvShows:
+                
+                if (self.ShouldStop()):
+                    return False
+                
+                if(pDialog != None):
+                    progressTitle = "Processing " + view.get('title') + " (" + str(count) + " of " + str(total) + ")"
+                    pDialog.update(0, "Emby for Kodi - Running Sync", progressTitle)
+                    count += 1                   
+
+                if item.get('IsFolder') and item.get('RecursiveItemCount') != 0:                   
+                    allEmbyTvShowIds.append(item["Id"])
+                    
+                    #build a list with all Id's and get the existing entry (if exists) in Kodi DB
+                    kodiShow = None
+                    for kodishow in allKodiTvShows:
+                        if kodishow[1] == item["Id"]:
+                            kodiShow = kodishow
+                          
+                    if kodiShow == None:
+                        # Tv show doesn't exist in Kodi yet so proceed and add it
+                        WriteKodiDB().addOrUpdateTvShowToKodiLibrary(item["Id"],connection, cursor, view.get('title'))
+                    else:
+                        # If there are changes to the item, perform a full sync of the item
+                        if kodiShow[2] != API().getChecksum(item):
+                            WriteKodiDB().addOrUpdateTvShowToKodiLibrary(item["Id"],connection, cursor, view.get('title'))
+                            
+                    #### PROCESS EPISODES ######
+                    self.EpisodesFullSync(connection,cursor,item["Id"])
+            
+        #### TVSHOW: PROCESS DELETES #####
+        allEmbyTvShowIds = set(allEmbyTvShowIds)
+        for kodiId in allKodiTvShowIds:
+            if not kodiId in allEmbyTvShowIds:
+                WINDOW.setProperty(kodiId,"deleted")
+                WriteKodiDB().deleteItemFromKodiLibrary(kodiId, connection, cursor)
+                
+        ### commit all changes to database ###
+        connection.commit()
+         
+    def EpisodesFullSync(self,connection,cursor,showId):
         
-        addon = xbmcaddon.Addon(id='plugin.video.emby')
         WINDOW = xbmcgui.Window( 10000 )
+        
+        allKodiEpisodeIds = list()
+        allEmbyEpisodeIds = list()
+        
+        #get the kodi parent id
+        cursor.execute("SELECT kodi_id FROM emby WHERE emby_id=?",(showId,))
+        kodiShowId = cursor.fetchone()[0]
+        
+        allEmbyEpisodes = ReadEmbyDB().getEpisodes(showId)
+        allKodiEpisodes = ReadKodiDB().getKodiEpisodes(connection, cursor, kodiShowId)
+        
+        for kodiepisode in allKodiEpisodes:
+            allKodiEpisodeIds.append(kodiepisode[1])
+
+        #### EPISODES: PROCESS ADDS AND UPDATES ###
+        for item in allEmbyEpisodes:
+            
+            if (self.ShouldStop()):
+                    return False    
+            
+            allEmbyEpisodeIds.append(item["Id"])
+            
+            #get the existing entry (if exists) in Kodi DB
+            kodiEpisode = None
+            for kodiepisode in allKodiEpisodes:
+                if kodiepisode[1] == item["Id"]:
+                    kodiEpisode = kodiepisode
+                  
+            if kodiEpisode == None:
+                # Episode doesn't exist in Kodi yet so proceed and add it
+                WriteKodiDB().addOrUpdateEpisodeToKodiLibrary(item["Id"], kodiShowId, connection, cursor)
+            else:
+                # If there are changes to the item, perform a full sync of the item
+                if kodiEpisode[2] != API().getChecksum(item):
+                    print "previous checksum--> " + kodiEpisode[2]
+                    print "new checksum--> " + API().getChecksum(item)
+                    WriteKodiDB().addOrUpdateEpisodeToKodiLibrary(item["Id"], kodiShowId, connection, cursor)
+        
+        #### EPISODES: PROCESS DELETES #####
+        allEmbyEpisodeIds = set(allEmbyEpisodeIds)
+        for kodiId in allKodiEpisodeIds:
+            if (not kodiId in allEmbyEpisodeIds):
+                WINDOW.setProperty(kodiId,"deleted")
+                WriteKodiDB().deleteItemFromKodiLibrary(kodiId, connection, cursor)
+                
+    
+    def IncrementalSync(self, itemList):
+        #this will only perform sync for items received by the websocket
+        addon = xbmcaddon.Addon(id='plugin.video.emby')
+        dbSyncIndication = addon.getSetting("dbSyncIndication") == "true"
+        WINDOW.setProperty("SyncDatabaseRunning", "true")
+        
+        #show the progress dialog
         pDialog = None
-        startedSync = datetime.today()
-        processMovies = True
-        processTvShows = True
+        if (dbSyncIndication):
+            pDialog = xbmcgui.DialogProgressBG()
+            pDialog.create('Emby for Kodi', 'Performing incremental sync...')
         
-        if(WINDOW.getProperty("SyncDatabaseShouldStop") ==  "true"):
-            utils.logMsg("Sync PlayCount", "Can not start SyncDatabaseShouldStop=True", 0)
-            return True        
+        connection = utils.KodiSQL()
+        cursor = connection.cursor()
         
-        if(WINDOW.getProperty("updatePlayCounts_Running") == "true"):
-            utils.logMsg("Sync PlayCount", "updatePlayCounts Already Running", 0)
-            return False
-            
-        WINDOW.setProperty("updatePlayCounts_Running", "true")
-            
         try:
-            playCountSyncIndication = addon.getSetting("playCountSyncIndication")
-            playCountSyncFirstRun = addon.getSetting("SyncFirstCountsRunDone")
-                
-            if(playCountSyncFirstRun != "true" or playCountSyncIndication == "Dialog Progress"):
-                pDialog = xbmcgui.DialogProgress()
-            elif(playCountSyncIndication == "BG Progress"):
-                pDialog = xbmcgui.DialogProgressBG()
-                
-            if(pDialog != None):
-                pDialog.create('Sync PlayCounts', 'Sync PlayCounts')        
-        
-            totalCountsUpdated = 0
-            totalPositionsUpdated = 0
-            
-            #process movies
-            if processMovies:
-                if(pDialog != None):
-                    pDialog.update(0, "Processing Movies", "")
-                    
-                views = ReadEmbyDB().getCollections("movies")
-                viewCount = len(views)
-                viewCurrent = 1
-                for view in views:
-                    allMB3Movies = ReadEmbyDB().getMovies(view.get('id'), fullinfo = False, fullSync = True)
-                    allKodiMovies = ReadKodiDB().getKodiMovies(False)
-                    
-                    if(self.ShouldStop(pDialog)):
-                        return False
-                            
-                    if(allMB3Movies != None and allKodiMovies != None):
+            #### PROCESS MOVIES ####
+            views = ReadEmbyDB().getCollections("movies")
+            for view in views:
+                allEmbyMovies = ReadEmbyDB().getMovies(view.get('id'), itemList)
+                for item in allEmbyMovies:
                         
-                        if(pDialog != None):
-                            progressTitle = "Sync PlayCounts: Processing " + view.get('title') + " " + str(viewCurrent) + " of " + str(viewCount)
-                            pDialog.update(0, progressTitle)
-                            totalCount = len(allMB3Movies) + 1
-                            count = 1
+                    if not item.get('IsFolder'):                    
+                        WriteKodiDB().addOrUpdateMovieToKodiLibrary(item["Id"],connection, cursor, view.get('title'))
+           
+           
+            #### PROCESS BOX SETS #####
+            boxsets = ReadEmbyDB().getBoxSets()
+           
+            for boxset in boxsets:
+                boxsetMovies = ReadEmbyDB().getMoviesInBoxSet(boxset["Id"])
+                WriteKodiDB().addBoxsetToKodiLibrary(boxset,connection, cursor)
                     
-                        for item in allMB3Movies:
-                            
-                            if not item.get('IsFolder'):                           
-                                kodiItem = allKodiMovies.get(item["Id"], None)
-                                
-                                userData = API().getUserData(item)
-                                timeInfo = API().getTimeInfo(item)
-                                
-                                if kodiItem != None:
-                                    kodiresume = int(round(kodiItem['resume'].get("position")))
-                                    resume = int(round(float(timeInfo.get("ResumeTime"))))*60
-                                    total = int(round(float(timeInfo.get("TotalTime"))))*60
-                                    if kodiresume != resume:
-                                        WriteKodiDB().setKodiResumePoint(kodiItem['movieid'],resume,total,"movie")
-                                        totalPositionsUpdated += 1
-                                    updated = WriteKodiDB().updateProperty(kodiItem,"playcount",int(userData.get("PlayCount")), "movie")
-                                    updated |= WriteKodiDB().updateProperty(kodiItem,"lastplayed",userData.get("LastPlayedDate"), "movie")
-                                    if(updated):
-                                        totalCountsUpdated += 1
-                                        
-                                if(self.ShouldStop(pDialog)):
-                                    return False
-                                
-                                # update progress bar
-                                if(pDialog != None):
-                                    percentage = int(((float(count) / float(totalCount)) * 100))
-                                    pDialog.update(percentage, progressTitle, "Updating Movie: " + str(count))
-                                    count += 1   
-                                
-                    viewCurrent += 1
-                    
-            #process Tv shows
-            if processTvShows:
-                if(pDialog != None):
-                    pDialog.update(0, "Processing TV Episodes", "")
-                views = ReadEmbyDB().getCollections("tvshows")
-                viewCount = len(views)
-                viewCurrent = 1
-                progressTitle = ""
-                for view in views:            
-            
-                    tvshowData = ReadEmbyDB().getTVShows(id = view.get('id'), fullinfo = False, fullSync = True)
-                    
-                    if(self.ShouldStop(pDialog)):
-                        return False
-                                
-                    if (tvshowData != None):
+                for boxsetMovie in boxsetMovies:
+                    WriteKodiDB().updateBoxsetToKodiLibrary(boxsetMovie,boxset, connection, cursor)
                         
-                        showTotal = len(tvshowData)
-                        showCurrent = 1                    
+                     
+            #### PROCESS TV SHOWS ####
+            views = ReadEmbyDB().getCollections("tvshows")              
+            for view in views:
+                allEmbyTvShows = ReadEmbyDB().getTvShows(view.get('id'),itemList)
+                for item in allEmbyTvShows:
+                    if item.get('IsFolder') and item.get('RecursiveItemCount') != 0:                   
+                        kodiId = WriteKodiDB().addOrUpdateTvShowToKodiLibrary(item["Id"],connection, cursor, view.get('title'))
                         
-                        for item in tvshowData:
-                            
-                            episodeData = ReadEmbyDB().getEpisodes(item["Id"], False)
-                            allKodiTVShows = ReadKodiDB().getKodiTvShows(False)
-                            kodishow = allKodiTVShows.get(item["Id"],None)
-                            if kodishow != None:
-                                kodiEpisodes = ReadKodiDB().getKodiEpisodes(kodishow["tvshowid"],False,True)
-                            else:
-                                kodiEpisodes = None
-                            
-                            if (episodeData != None):
-                                if(pDialog != None):
-                                    progressTitle = "Sync PlayCounts: Processing TV Show " + str(showCurrent) + " of " + str(showTotal)
-                                    pDialog.update(0, progressTitle)
-                                    totalCount = len(episodeData) + 1
-                                    count = 1                  
-                            
-                                for episode in episodeData:
-    
-                                    kodiItem = None
-                                    matchFound = False
-                                    if kodiEpisodes != None:
-                                        kodiItem = kodiEpisodes.get(episode.get("Id"), None)
-    
-                                    userData=API().getUserData(episode)
-                                    timeInfo = API().getTimeInfo(episode)
-                                    
-                                    
-                                    if kodiItem != None:
-                                        WINDOW = xbmcgui.Window( 10000 )
-                                        WINDOW.setProperty("episodeid" + str(kodiItem['episodeid']), episode.get('Name') + ";;" + episode.get('Id'))
-                                        WINDOW.setProperty(episode.get('Id'), "episode;;" + str(kodishow["tvshowid"]) + ";;" +str(kodiItem['episodeid']))
-                                        kodiresume = int(round(kodiItem['resume'].get("position")))
-                                        resume = int(round(float(timeInfo.get("ResumeTime"))))*60
-                                        total = int(round(float(timeInfo.get("TotalTime"))))*60
-                                        if kodiresume != resume:
-                                            WriteKodiDB().setKodiResumePoint(kodiItem['episodeid'],resume,total,"episode")
-                                            totalPositionsUpdated += 1
-                                        
-                                        updated = WriteKodiDB().updateProperty(kodiItem,"playcount",int(userData.get("PlayCount")),"episode")
-                                        updated |= WriteKodiDB().updateProperty(kodiItem,"lastplayed",userData.get("LastPlayedDate"), "episode")
-                                        if(updated):
-                                            totalCountsUpdated += 1 
-                                            
-                                    if(self.ShouldStop(pDialog)):
-                                        return False
-                                    
-                                    # update progress bar
-                                    if(pDialog != None):
-                                        percentage = int(((float(count) / float(totalCount)) * 100))
-                                        pDialog.update(percentage, progressTitle, "Updating Episode: " + str(count))
-                                        count += 1
-                                        
-                                showCurrent += 1
-             
-            if(playCountSyncFirstRun != "true"):
-                addon = xbmcaddon.Addon(id='plugin.video.emby')                  
-                addon.setSetting("SyncFirstCountsRunDone", "true")
-                
-            # display notification if set up
-            notificationString = ""
-            if(totalPositionsUpdated > 0):
-                notificationString += "Pos:" + str(totalPositionsUpdated) + " "
-            if(totalCountsUpdated > 0):
-                notificationString += "Counts:" + str(totalCountsUpdated) + " "
-                
-            timeTaken = datetime.today() - startedSync
-            timeTakenString = str(int(timeTaken.seconds / 60)) + ":" + str(timeTaken.seconds % 60)
-            utils.logMsg("Sync PlayCount", "Finished " + timeTakenString + " " + notificationString, 0)
-            
-            if(playCountSyncIndication == "Notify OnChange" and notificationString != ""):
-                notificationString = "(" + timeTakenString + ") " + notificationString
-                xbmc.executebuiltin("XBMC.Notification(PlayCount Sync: " + notificationString + ",)")
-            elif(playCountSyncIndication == "Notify OnFinish"):
-                if(notificationString == ""):
-                    notificationString = "Done"
-                notificationString = "(" + timeTakenString + ") " + notificationString
-                xbmc.executebuiltin("XBMC.Notification(PlayCount Sync: " + notificationString + ",)")
+            #### PROCESS EPISODES ######
+            for item in itemList:
+                    
+                MBitem = ReadEmbyDB().getItem(item)
+                if MBitem["Type"] == "Episode":
 
+                    #get the tv show
+                    cursor.execute("SELECT kodi_id FROM emby WHERE media_type='tvshow' AND emby_id=?", (MBitem["SeriesId"],))
+                    result = cursor.fetchone()
+                    if result:
+                        kodi_show_id = result[0]
+                    else:
+                        kodi_show_id = None
+
+                    if kodi_show_id:
+                        WriteKodiDB().addOrUpdateEpisodeToKodiLibrary(MBitem["Id"], kodi_show_id, connection, cursor)
+        
+            #### PROCESS MUSICVIDEOS ####
+            allEmbyMusicvideos = ReadEmbyDB().getMusicVideos(itemList)
+            for item in allEmbyMusicvideos:
+                if not item.get('IsFolder'):                    
+                    WriteKodiDB().addOrUpdateMusicVideoToKodiLibrary(item["Id"],connection, cursor)
+                    
+            ### commit all changes to database ###
+            connection.commit()
+        
         finally:
-            WINDOW.setProperty("updatePlayCounts_Running", "false")
-            if(pDialog != None):
-                pDialog.close()            
+            cursor.close()
+            xbmc.executebuiltin("UpdateLibrary(video)")
+            WINDOW.setProperty("SyncDatabaseRunning", "false")
         
-        return True
+        #close the progress dialog
+        if(pDialog != None):
+            pDialog.close()
     
-    def updatePlayCount(self, itemID):
-        #update playcount of the itemID from MB3 to Kodi library
-        
-        addon = xbmcaddon.Addon(id='plugin.video.emby')
-        WINDOW = xbmcgui.Window( 10000 )
-        
-        embyItem = ReadEmbyDB().getItem(itemID)
-        if(embyItem == None):
-            return False
-        
-        type = embyItem.get("Type")
-        
-        #process movie
-        if type == 'Movie':
-            kodiItem = ReadKodiDB().getKodiMovie(itemID)     
-
-            if(kodiItem == None):
-                return False
-                
-            if(self.ShouldStop(None)):
-                return False
- 
-            userData = API().getUserData(embyItem)
-            timeInfo = API().getTimeInfo(embyItem)
-                
-            kodiresume = int(round(kodiItem['resume'].get("position")))
-            resume = int(round(float(timeInfo.get("ResumeTime"))))*60
-            total = int(round(float(timeInfo.get("TotalTime"))))*60
-            if kodiresume != resume:
-                WriteKodiDB().setKodiResumePoint(kodiItem['movieid'],resume,total,"movie")
-            #write property forced will refresh the item in the list so playcount change is immediately visible
-            WriteKodiDB().updateProperty(kodiItem,"playcount",int(userData.get("PlayCount")),"movie",True)
-            WriteKodiDB().updateProperty(kodiItem,"lastplayed",userData.get("LastPlayedDate"), "movie")
-                
-            if(self.ShouldStop(None)):
-                return False 
-                    
-        #process episode
-        elif type == 'Episode':
-            if(self.ShouldStop(None)):
-                return False                   
-                    
-            kodiItem = ReadKodiDB().getKodiEpisodeByMbItem(embyItem["Id"], embyItem["SeriesId"])
-
-            userData = API().getUserData(embyItem)
-            timeInfo = API().getTimeInfo(embyItem)
+    def ShouldStop(self):
             
-            if kodiItem != None:
-                kodiresume = int(round(kodiItem['resume'].get("position")))
-                resume = int(round(float(timeInfo.get("ResumeTime"))))*60
-                total = int(round(float(timeInfo.get("TotalTime"))))*60
-                if kodiresume != resume:
-                    WriteKodiDB().setKodiResumePoint(kodiItem['episodeid'],resume,total,"episode")
-                #write property forced will refresh the item in the list so playcount change is immediately visible
-                WriteKodiDB().updateProperty(kodiItem,"playcount",int(userData.get("PlayCount")),"episode",True)
-                WriteKodiDB().updateProperty(kodiItem,"lastplayed",userData.get("LastPlayedDate"), "episode")       
-        
-        return True
-    
-    def ShouldStop(self, prog):
-        
-        if(prog != None and type(prog) == xbmcgui.DialogProgress):
-            if(prog.iscanceled() == True):
-                return True
-    
-        if(xbmc.Player().isPlaying() or xbmc.abortRequested):
+        if(xbmc.abortRequested):
             return True
 
-        WINDOW = xbmcgui.Window( 10000 )
         if(WINDOW.getProperty("SyncDatabaseShouldStop") == "true"):
             return True
 
diff --git a/resources/lib/PlaybackUtils.py b/resources/lib/PlaybackUtils.py
index bad30609..4dae984a 100644
--- a/resources/lib/PlaybackUtils.py
+++ b/resources/lib/PlaybackUtils.py
@@ -35,7 +35,7 @@ class PlaybackUtils():
     def __init__(self, *args):
         pass    
 
-    def PLAY(self, id):
+    def PLAY(self, result, setup="service"):
         xbmc.log("PLAY Called")
         WINDOW = xbmcgui.Window(10000)
 
@@ -43,43 +43,22 @@ class PlaybackUtils():
         userid = WINDOW.getProperty('userId%s' % username)
         server = WINDOW.getProperty('server%s' % username)
         
-        url = "{server}/mediabrowser/Users/{UserId}/Items/%s?format=json&ImageTypeLimit=1" % id
-        result = self.downloadUtils.downloadUrl(url)     
-        
+        try:
+            id = result["Id"]
+        except:
+            return
 
-        userData = result[u'UserData']
+        userData = result['UserData']
         resume_result = 0
         seekTime = 0
         
-        #get the resume point from Kodi DB for a Movie
-        kodiItem = ReadKodiDB().getKodiMovie(id)
-        if kodiItem != None:
-            seekTime = int(round(kodiItem['resume'].get("position")))
-        else:
-            #get the resume point from Kodi DB for an episode
-            episodeItem = ReadEmbyDB().getItem(id)
-            if episodeItem != None and str(episodeItem["Type"]) == "Episode":
-                kodiItem = ReadKodiDB().getKodiEpisodeByMbItem(id,episodeItem["SeriesId"])
-                if kodiItem != None:
-                    seekTime = int(round(kodiItem['resume'].get("position")))                  
-        
+        if userData.get("PlaybackPositionTicks") != 0:
+            reasonableTicks = int(userData.get("PlaybackPositionTicks")) / 1000
+            seekTime = reasonableTicks / 10000
+
         playurl = PlayUtils().getPlayUrl(server, id, result)
-        
-        isStrmFile = False
         thumbPath = API().getArtwork(result, "Primary")
         
-        #workaround for when the file to play is a strm file itself
-        if playurl.endswith(".strm"):
-            isStrmFile = True
-            tempPath = os.path.join(addondir,"library","temp.strm")
-            xbmcvfs.copy(playurl, tempPath)
-            sfile = open(tempPath, 'r')
-            playurl = sfile.readline()
-            sfile.close()
-            xbmcvfs.delete(tempPath)
-            WINDOW.setProperty("virtualstrm", id)
-            WINDOW.setProperty("virtualstrmtype", result.get("Type"))
-
         listItem = xbmcgui.ListItem(path=playurl, iconImage=thumbPath, thumbnailImage=thumbPath)
         self.setListItemProps(server, id, listItem, result)    
 
@@ -97,17 +76,19 @@ class PlaybackUtils():
         WINDOW.setProperty(playurl+"deleteurl", "")
         WINDOW.setProperty(playurl+"deleteurl", deleteurl)
         
-        if seekTime != 0:
-            displayTime = str(datetime.timedelta(seconds=seekTime))
-            display_list = [ self.language(30106) + ' ' + displayTime, self.language(30107)]
-            resumeScreen = xbmcgui.Dialog()
-            resume_result = resumeScreen.select(self.language(30105), display_list)
-            if resume_result == 0:
-                WINDOW.setProperty(playurl+"seektime", str(seekTime))
+        #show the additional resume dialog if launched from a widget
+        if xbmc.getCondVisibility("Window.IsActive(home)"):
+            if seekTime != 0:
+                displayTime = str(datetime.timedelta(seconds=seekTime))
+                display_list = [ self.language(30106) + ' ' + displayTime, self.language(30107)]
+                resumeScreen = xbmcgui.Dialog()
+                resume_result = resumeScreen.select(self.language(30105), display_list)
+                if resume_result == 0:
+                    WINDOW.setProperty(playurl+"seektime", str(seekTime))
+                else:
+                    WINDOW.clearProperty(playurl+"seektime")
             else:
                 WINDOW.clearProperty(playurl+"seektime")
-        else:
-            WINDOW.clearProperty(playurl+"seektime")
 
         if result.get("Type")=="Episode":
             WINDOW.setProperty(playurl+"refresh_id", result.get("SeriesId"))
@@ -132,15 +113,15 @@ class PlaybackUtils():
             if mediaSources[0].get('DefaultSubtitleStreamIndex') != None:
                 WINDOW.setProperty(playurl+"SubtitleStreamIndex", str(mediaSources[0].get('DefaultSubtitleStreamIndex')))
 
-        #this launches the playback
-        #artwork only works with both resolvedurl and player command
-        if isStrmFile:
-            xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem)
-        else:
-            xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem)
-            if(addon.getSetting("addExtraPlaybackArt") == "true"):
-                utils.logMsg("PLAY", "Doing second xbmc.Player().play to add extra art")
+        #launch the playback
+        if setup == "service":
+            xbmc.Player().play(playurl,listItem)
+        elif setup == "default":
+            #artwork only works from widgets (home screen) with player command as there is no listitem selected
+            if xbmc.getCondVisibility("Window.IsActive(home)"):
                 xbmc.Player().play(playurl,listItem)
+            else:
+               xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem)                
 
     def setArt(self, list,name,path):
         if name=='thumb' or name=='fanart_image' or name=='small_poster' or name=='tiny_poster'  or name == "medium_landscape" or name=='medium_poster' or name=='small_fanartimage' or name=='medium_fanartimage' or name=='fanart_noindicators':
diff --git a/resources/lib/Player.py b/resources/lib/Player.py
index e7526cb2..56d0838f 100644
--- a/resources/lib/Player.py
+++ b/resources/lib/Player.py
@@ -90,9 +90,9 @@ class Player( xbmc.Player ):
                     self.logMsg("emby Service -> Percent Complete:" + str(percentComplete) + " Mark Played At:" + str(markPlayedAt))
                     self.stopPlayback(data)
                     
-                if(refresh_id != None):
+                #if(refresh_id != None):
                     #report updates playcount and resume status to Kodi and MB3
-                    librarySync.updatePlayCount(item_id)
+                    #librarySync.updatePlayCount(item_id)
                     
                 
         self.played_information.clear()
@@ -138,6 +138,10 @@ class Player( xbmc.Player ):
         
         self.logMsg("reportPlayback Called", 2)
         xbmcplayer = self.xbmcplayer
+        
+        if not xbmcplayer.isPlaying():
+            self.logMsg("reportPlayback: Not playing anything so returning", 0)
+            return
 
         currentFile = xbmcplayer.getPlayingFile()
         data = self.played_information.get(currentFile)
@@ -176,7 +180,7 @@ class Player( xbmc.Player ):
                 postdata['SubtitleStreamIndex'] = subtitleindex
 
             postdata = json.dumps(postdata)
-            self.logMsg("Report: %s" % postdata)
+            self.logMsg("Report: %s" % postdata, 2)
             self.ws.sendProgressUpdate(postdata)
     
     def onPlayBackPaused( self ):
@@ -204,7 +208,11 @@ class Player( xbmc.Player ):
         self.stopAll()
         
         if xbmcplayer.isPlaying():
-            currentFile = xbmcplayer.getPlayingFile()
+            
+            currentFile = ""
+            try:
+                currentFile = xbmcplayer.getPlayingFile()
+            except: pass
             self.logMsg("onPlayBackStarted: %s" % currentFile, 0)
             
             # we may need to wait until the info is available
@@ -321,14 +329,11 @@ class Player( xbmc.Player ):
     def autoPlayPlayback(self):
         currentFile = xbmc.Player().getPlayingFile()
         data = self.played_information.get(currentFile)
-        
         # only report playback if emby has initiated the playback (item_id has value)
         if(data != None and data.get("item_id") != None):
             addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
-            
             item_id = data.get("item_id")
             type = data.get("Type")
-          
             # if its an episode see if autoplay is enabled
             if addonSettings.getSetting("autoPlaySeason")=="true" and type=="Episode":
                     WINDOW = xbmcgui.Window( 10000 )
@@ -343,8 +348,10 @@ class Player( xbmc.Player ):
                         seasonId = MB3Episode["SeasonId"]
                         url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s&ImageTypeLimit=1&Limit=1&SortBy=SortName&SortOrder=Ascending&Filters=IsUnPlayed&IncludeItemTypes=Episode&IsVirtualUnaired=false&Recursive=true&IsMissing=False&format=json" % seasonId
                         jsonData = self.doUtils.downloadUrl(url)     
+                    
                         if(jsonData != ""):
-                            seasonData = json.loads(jsonData)
+                            seasonData = jsonData
+                    
                             if seasonData.get("Items") != None:
                                 item = seasonData.get("Items")[0]
                                 pDialog.create("Auto Play next episode", str(item.get("ParentIndexNumber")) + "x" + str(item.get("IndexNumber")) + ". " + item["Name"] + " found","Cancel to stop automatic play")
@@ -365,5 +372,5 @@ class Player( xbmc.Player ):
                                     xbmc.sleep(500)
                                     playTime = xbmc.Player().getTime()
                                     totalTime = xbmc.Player().getTotalTime()
-                                
+        
                                 PlaybackUtils().PLAYAllEpisodes(seasonData.get("Items"))  
\ No newline at end of file
diff --git a/resources/lib/ReadEmbyDB.py b/resources/lib/ReadEmbyDB.py
index 4d80455c..20577e20 100644
--- a/resources/lib/ReadEmbyDB.py
+++ b/resources/lib/ReadEmbyDB.py
@@ -6,30 +6,22 @@ import xbmc
 import xbmcgui
 import xbmcaddon
 
+
+
 from DownloadUtils import DownloadUtils
 
 addon = xbmcaddon.Addon(id='plugin.video.emby')
 
 class ReadEmbyDB():   
     
-    def getMovies(self, id, fullinfo = False, fullSync = True, itemList = []):
+    def getMovies(self, id, itemList = []):
         
         result = None
         doUtils = DownloadUtils()
-
-        if fullSync:
-            sortstring = "&SortBy=SortName"
-        else:
-            if(len(itemList) > 0): # if we want a certain list specify it
-                #sortstring = "&Ids=" + ",".join(itemList)
-                sortstring = "" # work around for now until ParetnId and Id work together
-            else: # just get the last 20 created items
-                sortstring = "&Limit=20&SortBy=DateCreated"
-            
-        if fullinfo:
-            url = "{server}/mediabrowser/Users/{UserId}/items?ParentId=%s%s&Fields=Path,Genres,SortName,Studios,Writer,ProductionYear,Taglines,CommunityRating,OfficialRating,CumulativeRunTimeTicks,Metascore,AirTime,DateCreated,MediaStreams,People,Overview&Recursive=true&SortOrder=Descending&IncludeItemTypes=Movie&CollapseBoxSetItems=false&format=json&ImageTypeLimit=1" % (id, sortstring)
-        else:
-            url = "{server}/mediabrowser/Users/{UserId}/items?ParentId=%s%s&Fields=CumulativeRunTimeTicks&Recursive=true&SortOrder=Descending&IncludeItemTypes=Movie&CollapseBoxSetItems=false&format=json&ImageTypeLimit=1" % (id, sortstring)
+        
+        #only get basic info for our sync-compares
+        sortstring = "&SortBy=SortName"
+        url = "{server}/mediabrowser/Users/{UserId}/items?ParentId=%s%s&Fields=CumulativeRunTimeTicks,Etag&Recursive=true&SortOrder=Descending&IncludeItemTypes=Movie&CollapseBoxSetItems=false&format=json&ImageTypeLimit=1" % (id, sortstring)
 
         jsonData = doUtils.downloadUrl(url)
         if (jsonData == ""):
@@ -37,8 +29,8 @@ class ReadEmbyDB():
 
         if (jsonData[u'Items'] != ""):
             result = jsonData[u'Items']
-
-        # work around for now until ParetnId and Id work together
+            
+        # 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:
@@ -48,20 +40,14 @@ class ReadEmbyDB():
             
         return result
 
-    def getMusicVideos(self, fullinfo = False, fullSync = True):
+    def getMusicVideos(self, itemList = []):
         
         result = None
         doUtils = DownloadUtils()
 
-        if not fullSync:
-            sortstring = "&Limit=20&SortBy=DateCreated"
-        else:
-            sortstring = "&SortBy=SortName"
-        
-        if fullinfo:
-            url = "{server}/mediabrowser/Users/{UserId}/items?%s&Fields=Path,Genres,SortName,Studios,Writer,ProductionYear,Taglines,CommunityRating,OfficialRating,CumulativeRunTimeTicks,Metascore,AirTime,DateCreated,MediaStreams,People,Overview&Recursive=true&SortOrder=Descending&IncludeItemTypes=MusicVideo&format=json&ImageTypeLimit=1" % sortstring
-        else:
-            url = "{server}/mediabrowser/Users/{UserId}/items?%s&Fields=CumulativeRunTimeTicks&Recursive=true&SortOrder=Descending&IncludeItemTypes=MusicVideo&CollapseBoxSetItems=false&format=json&ImageTypeLimit=1" % sortstring
+        #only get basic info for our sync-compares
+        sortstring = "&SortBy=SortName"
+        url = "{server}/mediabrowser/Users/{UserId}/items?%s&Fields=CumulativeRunTimeTicks,Etag&Recursive=true&SortOrder=Descending&IncludeItemTypes=MusicVideo&CollapseBoxSetItems=false&format=json&ImageTypeLimit=1" % sortstring
         
         jsonData = doUtils.downloadUrl(url)
         if (jsonData == ""):
@@ -69,6 +55,14 @@ class ReadEmbyDB():
 
         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
         
@@ -98,20 +92,14 @@ class ReadEmbyDB():
 
         return result
     
-    def getTVShows(self, id, fullinfo = False, fullSync = False):
+    def getTvShows(self, id, itemList = []):
         
         result = None
         doUtils = DownloadUtils()
-
-        if not fullSync:
-            sortstring = "&Limit=20&SortBy=DateCreated"
-        else:
-            sortstring = "&SortBy=SortName"
         
-        if fullinfo:
-            url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s%s&Fields=Path,Genres,SortName,Studios,Writer,ProductionYear,Taglines,CommunityRating,OfficialRating,CumulativeRunTimeTicks,Metascore,AirTime,DateCreated,MediaStreams,People,Overview&Recursive=true&SortOrder=Descending&IncludeItemTypes=Series&format=json&ImageTypeLimit=1" % (id, sortstring)
-        else:
-            url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s%s&Fields=CumulativeRunTimeTicks&Recursive=true&SortOrder=Descending&IncludeItemTypes=Series&format=json&ImageTypeLimit=1" % (id, sortstring)
+        #only get basic info for our sync-compares
+        sortstring = "&SortBy=SortName"
+        url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s%s&Fields=CumulativeRunTimeTicks,Etag&Recursive=true&SortOrder=Descending&IncludeItemTypes=Series&format=json&ImageTypeLimit=1" % (id, sortstring)
         
         jsonData = doUtils.downloadUrl(url)
         if (jsonData == ""):
@@ -119,6 +107,14 @@ class ReadEmbyDB():
 
         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
     
@@ -138,15 +134,12 @@ class ReadEmbyDB():
 
         return result
     
-    def getEpisodes(self, showId, fullinfo = False):
+    def getEpisodes(self, showId, itemList = []):
         
         result = None
         doUtils = DownloadUtils()  
         
-        if fullinfo:
-            url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s&IsVirtualUnaired=false&IsMissing=False&SortBy=SortName&Fields=Path,Genres,SortName,Studios,Writer,ProductionYear,Taglines,CommunityRating,OfficialRating,CumulativeRunTimeTicks,Metascore,AirTime,DateCreated,MediaStreams,People,Overview&Recursive=true&SortOrder=Ascending&IncludeItemTypes=Episode&format=json&ImageTypeLimit=1" % showId
-        else:
-            url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s&IsVirtualUnaired=false&IsMissing=False&SortBy=SortName&Fields=Name,SortName,CumulativeRunTimeTicks&Recursive=true&SortOrder=Ascending&IncludeItemTypes=Episode&format=json&ImageTypeLimit=1" % showId
+        url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s&IsVirtualUnaired=false&IsMissing=False&SortBy=SortName&Fields=Name,SortName,CumulativeRunTimeTicks,Etag&Recursive=true&SortOrder=Ascending&IncludeItemTypes=Episode&format=json&ImageTypeLimit=1" % showId
         
         jsonData = doUtils.downloadUrl(url)
         if (jsonData == ""):
@@ -154,6 +147,14 @@ class ReadEmbyDB():
 
         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
     
@@ -167,9 +168,9 @@ class ReadEmbyDB():
             limitString = "Ids=" + ",".join(itemList) + "&"
         
         if fullinfo:
-            url = "{server}/mediabrowser/Users/{UserId}/Items?%sIsVirtualUnaired=false&IsMissing=False&Fields=ParentId,Path,Genres,SortName,Studios,Writer,ProductionYear,Taglines,CommunityRating,OfficialRating,CumulativeRunTimeTicks,Metascore,AirTime,DateCreated,MediaStreams,People,Overview&Recursive=true&SortOrder=Descending&IncludeItemTypes=Episode&format=json&ImageTypeLimit=1" % limitString
+            url = "{server}/mediabrowser/Users/{UserId}/Items?%sIsVirtualUnaired=false&IsMissing=False&Fields=ParentId,Path,Genres,SortName,Studios,Writer,ProductionYear,Taglines,CommunityRating,OfficialRating,CumulativeRunTimeTicks,Metascore,AirTime,DateCreated,MediaStreams,People,Overview,Etag&Recursive=true&SortOrder=Descending&IncludeItemTypes=Episode&format=json&ImageTypeLimit=1" % limitString
         else:
-            url = "{server}/mediabrowser/Users/{UserId}/Items?%sIsVirtualUnaired=false&IsMissing=False&Fields=ParentId,Name,SortName,CumulativeRunTimeTicks&Recursive=true&SortOrder=Descending&IncludeItemTypes=Episode&format=json&ImageTypeLimit=1" % limitString
+            url = "{server}/mediabrowser/Users/{UserId}/Items?%sIsVirtualUnaired=false&IsMissing=False&Fields=ParentId,Name,SortName,CumulativeRunTimeTicks,Etag&Recursive=true&SortOrder=Descending&IncludeItemTypes=Episode&format=json&ImageTypeLimit=1" % limitString
         
         jsonData = doUtils.downloadUrl(url)
         if (jsonData == ""):
@@ -225,33 +226,43 @@ class ReadEmbyDB():
         doUtils = DownloadUtils()
 
         viewsUrl = "{server}/mediabrowser/Users/{UserId}/Views?format=json&ImageTypeLimit=1"
-        jsonData = doUtils.downloadUrl(viewsUrl)
+        result = doUtils.downloadUrl(viewsUrl)
         collections=[]
         
-        if (jsonData != ""):
-            views = views[u'Items']
+        if (result == ""):
+            return []
+            
+        result = result[u'Items']
 
-            for view in views:
-                if (view[u'Type'] == 'UserView'): # Need to grab the real main node
-                    newViewsUrl = "{server}/mediabrowser/Users/{UserId}/items?ParentId=%s&SortBy=SortName&SortOrder=Ascending&format=json&ImageTypeLimit=1" % view[u'Id']
-                    jsonData = doUtils.downloadUrl(newViewsUrl)
-                    if (jsonData != ""):
-                        newViews = newViews[u'Items']
-                        for newView in newViews:
-                            # There are multiple nodes in here like 'Latest', 'NextUp' - below we grab the full node.
-                            if newView[u'CollectionType'] == "MovieMovies" or newView[u'CollectionType'] == "TvShowSeries":
-                                view=newView
-                if (view[u'ChildCount'] != 0):
-                    Name = view[u'Name'] 
-                    
-                total = str(view[u'ChildCount'])
-                type = view[u'CollectionType']
-                if type == None:
-                    type = "None" # User may not have declared the type
-                if type == type:
-                    collections.append( {'title'      : Name,
-                            'type'           : type,
-                            'id'             : view[u'Id']})
+        for view in result:
+            if (view[u'Type'] == 'UserView'): # Need to grab the real main node
+                newViewsUrl = "{server}/mediabrowser/Users/{UserId}/items?ParentId=%s&SortBy=SortName&SortOrder=Ascending&format=json&ImageTypeLimit=1" % view[u'Id']
+                newViews = doUtils.downloadUrl(newViewsUrl)
+                if (result == ""):
+                    return []
+                newViews = newViews[u'Items']
+                print str(newViews)
+                for newView in newViews:
+                    # There are multiple nodes in here like 'Latest', 'NextUp' - below we grab the full node.
+                    if newView[u'CollectionType'] != None:
+                        if newView[u'CollectionType'] == "MovieMovies" or newView[u'CollectionType'] == "TvShowSeries":
+                            view=newView
+            if (view[u'ChildCount'] != 0):
+                Name = view[u'Name'] 
+                
+            total = str(view[u'ChildCount'])
+            try:
+                itemtype = view[u'CollectionType']
+            except:
+                itemtype = "movies"
+            if itemtype == "MovieMovies":
+                itemtype = "movies"
+            if itemtype == "TvShowSeries":
+                itemtype = "tvshows"
+            if itemtype == type:
+                collections.append( {'title'      : Name,
+                                     'type'           : type,
+                                     'id'             : view[u'Id']})
         return collections
     
     def getBoxSets(self):
@@ -259,7 +270,7 @@ class ReadEmbyDB():
         result = None
         doUtils = DownloadUtils()  
         
-        url = "{server}/mediabrowser/Users/{UserId}/Items?SortBy=SortName&IsVirtualUnaired=false&IsMissing=False&Fields=Name,SortName,CumulativeRunTimeTicks&Recursive=true&SortOrder=Ascending&IncludeItemTypes=BoxSet&format=json&ImageTypeLimit=1"
+        url = "{server}/mediabrowser/Users/{UserId}/Items?SortBy=SortName&IsVirtualUnaired=false&IsMissing=False&Fields=Name,SortName,CumulativeRunTimeTicks,Etag&Recursive=true&SortOrder=Ascending&IncludeItemTypes=BoxSet&format=json&ImageTypeLimit=1"
         
         jsonData = doUtils.downloadUrl(url)
         if (jsonData == ""):
@@ -275,7 +286,7 @@ class ReadEmbyDB():
         result = None
         doUtils = DownloadUtils()
         
-        url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s&Fields=ItemCounts&format=json&ImageTypeLimit=1" % boxsetId
+        url = "{server}/mediabrowser/Users/{UserId}/Items?ParentId=%s&Fields=ItemCounts,Etag&format=json&ImageTypeLimit=1" % boxsetId
         
         jsonData = doUtils.downloadUrl(url)
         if (jsonData == ""):
diff --git a/resources/lib/ReadKodiDB.py b/resources/lib/ReadKodiDB.py
index f5acdb26..ff41ae02 100644
--- a/resources/lib/ReadKodiDB.py
+++ b/resources/lib/ReadKodiDB.py
@@ -11,302 +11,49 @@ import os
 
 import Utils as utils
 
-
-#sleepval is used to throttle the calls to the xbmc json API
-sleepVal = 15
-
 class ReadKodiDB():   
-    
-    def getKodiMovie(self, id):
-        #returns a single movie from Kodi db selected on MB item ID
-        xbmc.sleep(sleepVal)
-        json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovies", "params": { "properties" : ["art", "rating", "thumbnail", "fanart", "resume", "runtime", "year", "genre", "cast", "trailer", "country", "studio", "set", "imdbnumber", "mpaa", "tagline", "plotoutline","plot", "sorttitle", "director", "lastplayed", "writer", "playcount", "tag", "file"], "sort": { "order": "ascending", "method": "label", "ignorearticle": true } }, "id": "libMovies"}')
-        jsonobject = json.loads(json_response.decode('utf-8','replace'))  
-        movie = None
        
-        if(jsonobject.has_key('result')):
-            result = jsonobject['result']
-            if(result.has_key('movies')):
-                movies = result['movies']
-                movie = movies[0]
-                for item in movies:
-                    if item["imdbnumber"] == id:
-                        movie = item
-                        break
-        return movie
-    
-    def getEmbyIdByKodiId(self, kodiid, type):
-        #returns the emby id by search on kodi id
-        xbmc.sleep(sleepVal)
-        
-        embyId = None
-        json_response = None
-        
-        if type == "movie":
-            json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovieDetails", "params": { "movieid": %d, "properties" : ["imdbnumber","file"] }, "id": "libMovies"}' %kodiid)
-        if type == "episode":
-            json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodeDetails", "params": {"episodeid": %d, "properties": ["file","uniqueid"]}, "id": 1}' %kodiid)
-        if type == "musicvideo":
-            connection = utils.KodiSQL()
-            cursor = connection.cursor()
-            cursor.execute("SELECT c23 as MBid FROM musicvideo WHERE idMVideo = ?",(kodiid,))
-            result = cursor.fetchone()
-            cursor.close()
-            if result != None:
-                embyId = result[0]
-        
-        if json_response != None:
-            jsonobject = json.loads(json_response.decode('utf-8','replace'))  
-            if(jsonobject.has_key('result')):
-                result = jsonobject['result']
-                resulttype = type + "details"
-                if(result.has_key(resulttype)):
-                    item = result[resulttype]
-                    if type == "movie":
-                        if item.has_key('imdbnumber'):
-                            embyId = item['imdbnumber']
-                    if type == "episode":
-                        if item.has_key('uniqueid'):
-                            if item['uniqueid'].has_key('unknown'):
-                                embyId = item["uniqueid"]["unknown"]
-
-        return embyId
-    
-    def getKodiMovies(self,fullInfo = False):
+   
+    def getKodiMovies(self, connection, cursor):
         #returns all movies in Kodi db
-        xbmc.sleep(sleepVal)
-        if fullInfo:
-            json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovies", "params": { "properties" : ["art", "rating", "thumbnail", "fanart", "resume", "runtime", "year", "genre", "cast", "trailer", "country", "lastplayed", "studio", "set", "imdbnumber", "mpaa", "tagline", "plotoutline","plot", "sorttitle", "director", "writer", "playcount", "tag", "file"] }, "id": "libMovies"}')
-        else:
-            json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovies", "params": { "properties" : ["resume", "playcount", "imdbnumber", "lastplayed", "file"] }, "id": "libMovies"}')
-        jsonobject = json.loads(json_response.decode('utf-8','replace'))  
-        movies = None
-       
-        if(jsonobject.has_key('result')):
-            result = jsonobject['result']
-            if(result.has_key('movies')):
-                movies = result['movies']
-
-        kodiMovieMap = None
-        if(movies != None and len(movies) > 0):
-            kodiMovieMap = {}
-            for kodimovie in movies:
-                key = kodimovie["imdbnumber"] #extract the id from the imdbnumber 
-                kodiMovieMap[key] = kodimovie
-                
-        return kodiMovieMap
+        cursor.execute("SELECT kodi_id, emby_id, checksum FROM emby WHERE media_type='movie'")
+        allmovies = cursor.fetchall()
+        #this will return a list with tuples of all items returned from the database
+        return allmovies
     
-    def getKodiMoviesIds(self,returnMB3Ids = False):
-        # returns a list of movieIds or MB3 Id's from all movies currently in the Kodi library
-        allKodiMovies = self.getKodiMovies(False)
-        
-        if(allKodiMovies == None):
-            return list()
-        
-        if(returnMB3Ids):
-            allKodiMovieIds = list(allKodiMovies.keys())
-            return allKodiMovieIds
-        else:
-            allKodiMovieIds = list()
-            for kodimovie in allKodiMovies.values():
-                id = str(kodimovie["movieid"])
-                allKodiMovieIds.append(id)
-        
-            return allKodiMovieIds
+    def getKodiMusicVideos(self, connection, cursor):
+        #returns all musicvideos in Kodi db
+        cursor.execute("SELECT kodi_id, emby_id, checksum FROM emby WHERE media_type='musicvideo'")
+        allvideos = cursor.fetchall()
+        #this will return a list with tuples of all items returned from the database
+        return allvideos
     
-    def getKodiTvShowsIds(self,returnMB3Ids = False):
-        # returns a list of tvshowIds or MB3 Id's from all tvshows currently in the Kodi library
-        allKodiTvShows = self.getKodiTvShows(False)
-        
-        if allKodiTvShows == None:
-            return list()
-        
-        if(returnMB3Ids):
-            allKodiTvShowsIds = list(allKodiTvShows.keys())
-            return allKodiTvShowsIds
-        else:
-            allKodiTvShowsIds = list()
-            for kodishow in allKodiTvShows.values():
-                id = str(kodishow["tvshowid"])
-                allKodiTvShowsIds.append(id)
-        
-            return allKodiTvShowsIds
-        
-    def getKodiTvShows(self,fullInfo = False):
-        #returns all tvshows in Kodi db inserted by MB
-        xbmc.sleep(sleepVal)
-        if fullInfo:
-            json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": { "properties": ["art", "genre", "plot", "mpaa", "cast", "studio", "sorttitle", "title", "originaltitle", "imdbnumber", "year", "premiered", "rating", "thumbnail", "playcount", "lastplayed", "file", "fanart", "tag"], "sort": { "order": "ascending", "method": "label", "ignorearticle": true } }, "id": "libTvShows"}')
-        else:
-            json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": { "properties": ["sorttitle", "title", "playcount", "lastplayed", "imdbnumber", "file"], "sort": { "order": "ascending", "method": "label", "ignorearticle": true } }, "id": "libTvShows"}')
-        jsonobject = json.loads(json_response.decode('utf-8','replace'))  
-        tvshows = None
+    def getKodiTvShows(self, connection, cursor):
+        cursor.execute("SELECT kodi_id, emby_id, checksum FROM emby WHERE media_type='tvshow'")
+        allshows = cursor.fetchall()
+        #this will return a list with tuples of all items returned from the database
+        return allshows
 
-        if(jsonobject.has_key('result')):
-            result = jsonobject['result']
-            if(result.has_key('tvshows')):
-                tvshows = result['tvshows']
-
-        kodiShowMap = None
-        if(tvshows != None and len(tvshows) > 0):
-            kodiShowMap = {}
-            for kodishow in tvshows:
-                key = kodishow["imdbnumber"] #extract the id from the imdb number
-                kodiShowMap[key] = kodishow
-                
-        return kodiShowMap
-    
-    def getKodiTVShow(self, id):
-        xbmc.sleep(sleepVal)
-        json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": { "properties": ["art", "genre", "plot", "mpaa", "cast", "studio", "sorttitle", "title", "originaltitle", "imdbnumber", "year", "lastplayed", "premiered", "rating", "thumbnail", "playcount", "file", "fanart", "tag"], "sort": { "order": "ascending", "method": "label", "ignorearticle": true } }, "id": "libTvShows"}')
-        jsonobject = json.loads(json_response.decode('utf-8','replace'))  
-        tvshow = None
-        if(jsonobject.has_key('result')):
-            result = jsonobject['result']
-            if(result.has_key('tvshows')):
-                tvshows = result['tvshows']
-                for show in tvshows:
-                    if show["imdbnumber"] == id:
-                        tvshow = show
-                        break
-        return tvshow
-    
-    def getKodiEpisodes(self, KodiTvShowId, fullInfo = True, returnmap = True):
-        xbmc.sleep(sleepVal)
-        episodes = None
-        if fullInfo:
-            json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodes", "params": {"tvshowid": %d, "properties": ["title", "playcount", "plot", "season", "episode", "showtitle", "file", "lastplayed", "rating", "resume", "art", "streamdetails", "firstaired", "runtime", "writer", "cast", "director", "dateadded", "uniqueid", "thumbnail", "fanart"], "sort": {"method": "episode"}}, "id": 1}' %KodiTvShowId)
+    def getKodiEpisodes(self, connection, cursor, showid=None):
+        
+        if showid == None:
+            cursor.execute("SELECT kodi_id, emby_id, checksum FROM emby WHERE media_type=?",("episode",))
         else:
-            json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodes", "params": {"tvshowid": %d, "properties": ["title", "playcount", "season", "episode", "lastplayed", "resume","file","uniqueid"], "sort": {"method": "episode"}}, "id": 1}' %KodiTvShowId)
-        jsonobject = json.loads(json_response.decode('utf-8','replace'))  
-        episodes = None
-        if(jsonobject.has_key('result')):
-            result = jsonobject['result']
-            if(result.has_key('episodes')):
-                episodes = result['episodes']
-        if returnmap:                 
-            episodeMap = None
-            if(episodes != None):
-                episodeMap = {}
-                for KodiItem in episodes:
-                    episodeMap[KodiItem["uniqueid"]["unknown"]] = KodiItem    
-            return episodeMap
-        else:
-            return episodes
+            cursor.execute("SELECT kodi_id, emby_id, checksum FROM emby WHERE media_type=? AND parent_id=?",("episode", showid))
         
-    def getKodiEpisodeByMbItem(self, episodeid, tvshowid):
-        episode = None
-        tvshow = self.getKodiTVShow(tvshowid)
+        allepisodes = cursor.fetchall()
+        #this will return a list with tuples of all items returned from the database
+        return allepisodes
         
-        if tvshow != None:
-            json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodes", "params": {"tvshowid": ' + str(tvshow['tvshowid']) + ', "properties": ["playcount","season", "resume", "episode", "lastplayed", "uniqueid", "file"], "sort": {"method": "episode"}}, "id": 1}')
-            jsonobject = json.loads(json_response.decode('utf-8','replace'))  
-            if(jsonobject.has_key('result')):
-                result = jsonobject['result']
-                if(result.has_key('episodes')):
-                    episodes = result['episodes']
-                    for ep in episodes:
-                        if ep["uniqueid"]["unknown"] == episodeid:
-                            episode = ep
-                            break
-
-        return episode
-        
-    def getKodiEpisodeByMbItemEx(self, id):        
-        connection = utils.KodiSQL()
-        cursor = connection.cursor()
-        cursor.execute("SELECT idEpisode FROM episode WHERE c20 = ?", (id,))
-        result = cursor.fetchone()
-        kodiId = None
-        if result != None:
-            kodiId = result[0]
-        cursor.close()
-        
-        episode = None
-        if(kodiId != None):
-            print "Kodi Episode ID : " + str(kodiId)
-            json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodeDetails", "params": {"episodeid": %d, "properties": ["playcount", "season", "resume", "episode", "lastplayed", "uniqueid", "file"]}, "id": 1}' %kodiId)
-            #json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetEpisodeDetails", "params": {"episodeid": ' + str(kodiId) + ', "properties": ["playcount", "season", "resume", "episode", "lastplayed", "uniqueid", "file"], "sort": {"method": "episode"}}, "id": 1}')
-            jsonobject = json.loads(json_response.decode('utf-8','replace')) 
-            print "Kodi_Item: " + str(jsonobject)
-            if(jsonobject.has_key("result")):
-                result = jsonobject["result"]
-                if(result.has_key("episodedetails")):
-                    episode = result["episodedetails"]
-        
-        return episode
-        
-    def getKodiMusicVideo(self, id):
-        #returns a single musicvideo from Kodi db selected on MB item ID
-        xbmc.sleep(sleepVal)
-        #get the mediabrowser ID from DB
-        connection = utils.KodiSQL()
-        cursor = connection.cursor()
-        cursor.execute("SELECT idMVideo as musicvideoid FROM musicvideo WHERE c23 = ?",(id,))
-        result = cursor.fetchone()
-        musicvideoid = None
-        if result != None:
-            musicvideoid = result[0]
-        cursor.close()
-        
-        musicvideo = None
-        
-        if musicvideoid != None:
-            json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMusicVideosDetails", "params": { "musicvideoid": ' + musicvideoid + ', "properties" : ["art", "thumbnail", "fanart", "resume", "runtime", "year", "genre", "studio", "artist", "album", "track","plot", "director", "playcount", "lastplayed", "tag", "file"], "sort": { "order": "ascending", "method": "label", "ignorearticle": true } }, "id": "libMusicVideos"}')
-            jsonobject = json.loads(json_response.decode('utf-8','replace'))  
-            musicvideo = None
-           
-            if(jsonobject.has_key('result')):
-                result = jsonobject['result']
-                if(result.has_key('musicvideodetails')):
-                    musicvideo = result['musicvideodetails']
-
-        return musicvideo
-    
-    def getKodiMusicVideos(self,fullInfo = False):
-        #returns all musicvideos in Kodi db inserted by MB
-        xbmc.sleep(sleepVal)
-        if fullInfo:
-            json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMusicVideos", "params": { "properties" : ["art", "thumbnail", "fanart", "resume", "runtime", "year", "genre", "studio", "artist", "album", "track", "lastplayed", "plot", "director", "playcount", "tag", "file"] }, "id": "libMusicVideos"}')
-        else:
-            json_response = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetMusicVideos", "params": { "properties" : ["resume", "playcount", "lastplayed", "file", "track"] }, "id": "libMusicVideos"}')
-        jsonobject = json.loads(json_response.decode('utf-8','replace'))  
-        musicvideos = None
-        if(jsonobject.has_key('result')):
-            result = jsonobject['result']
-            if(result.has_key('musicvideos')):
-                musicvideos = result['musicvideos']
-
-        kodiMusicVideoMap = None
-        if(musicvideos != None and len(musicvideos) > 0):
-            kodiMusicVideoMap = {}
+    def getEmbyIdByKodiId(self, id, type, connection=None, cursor=None):
+        if not connection:
             connection = utils.KodiSQL()
             cursor = connection.cursor()
-            for kodivideo in musicvideos:
-                cursor.execute("SELECT c23 as MBid FROM musicvideo WHERE idMVideo = ?",(kodivideo["musicvideoid"],))
-                result = cursor.fetchone()
-                if result != None:
-                    key = result[0]
-                    kodiMusicVideoMap[key] = kodivideo
-            
-            cursor.close()    
-        return kodiMusicVideoMap
-    
-    def getKodiMusicVideoIds(self,returnMB3Ids = False):
-        # returns a list of movieIds or MB3 Id's from all movies currently in the Kodi library
-        allKodiMusicVideos = self.getKodiMusicVideos(False)
-        
-        if(allKodiMusicVideos == None):
-            return list()
-        
-        if(returnMB3Ids):
-            allKodiMusicVideoIds = list(allKodiMusicVideos.keys())
-            return allKodiMusicVideoIds
+        cursor.execute("SELECT emby_id FROM emby WHERE media_type=? AND kodi_id=?",(type,id))
+        result = cursor.fetchone()
+        if result:
+            return result[0]
         else:
-            allKodiMusicVideoIds = list()
-            for kodivideo in allKodiMusicVideos.values():
-                id = str(kodivideo["musicvideoid"])
-                allKodiMusicVideoIds.append(id)
-        
-            return allKodiMusicVideoIds
+            return None
+       
         
\ No newline at end of file
diff --git a/resources/lib/UserClient.py b/resources/lib/UserClient.py
index 31a78f64..2bef61f0 100644
--- a/resources/lib/UserClient.py
+++ b/resources/lib/UserClient.py
@@ -45,17 +45,17 @@ class UserClient(threading.Thread):
     def __init__(self, *args):
 
         self.__dict__ = self._shared_state
-        self.className = self.__class__.__name__
-
         threading.Thread.__init__(self, *args)
 
     def logMsg(self, msg, lvl=1):
         
-        utils.logMsg("%s %s" % (self.addonName, self.className), str(msg), int(lvl))
+        className = self.__class__.__name__
+        utils.logMsg("%s %s" % (self.addonName, className), str(msg), int(lvl))
 
     def getUsername(self):
 
-        username = self.addon.getSetting('username')
+        addon = xbmcaddon.Addon(id=self.addonId)
+        username = addon.getSetting('username')
 
         if (username == ""):
             self.logMsg("No username saved.", 2)
@@ -90,7 +90,7 @@ class UserClient(threading.Thread):
     def getServer(self, prefix=True):
 
         # For https support
-        addon = self.addon
+        addon = xbmcaddon.Addon(id=self.addonId)
         HTTPS = addon.getSetting('https')
         host = addon.getSetting('ipaddress')
         port = addon.getSetting('port')
@@ -161,6 +161,9 @@ class UserClient(threading.Thread):
         
         if (result != ""):
             users = result
+        else:
+            # Server connection failed
+            return False
 
         return users
 
@@ -226,9 +229,6 @@ class UserClient(threading.Thread):
         users = self.getPublicUsers()
         password = ""
         
-        '''if users == "":
-            self.WINDOW.setProperty("Server_status", "Stop")
-            return'''
         # Find user in list
         for user in users:
             name = user[u'Name']
diff --git a/resources/lib/Utils.py b/resources/lib/Utils.py
index 4f47b77f..578a5cae 100644
--- a/resources/lib/Utils.py
+++ b/resources/lib/Utils.py
@@ -53,7 +53,7 @@ def convertEncoding(data):
           
 def KodiSQL():
     connection = sqlite3.connect(getKodiDBPath())
-
+    
     return connection
 
 def getKodiDBPath():
@@ -62,7 +62,7 @@ def getKodiDBPath():
         dbVersion = "78"
     if xbmc.getInfoLabel("System.BuildVersion").startswith("15"):
         #isengard
-        dbVersion = "91"
+        dbVersion = "92"
     else: 
         #helix
         dbVersion = "90"
diff --git a/resources/lib/WebSocketClient.py b/resources/lib/WebSocketClient.py
index e09e105a..53667181 100644
--- a/resources/lib/WebSocketClient.py
+++ b/resources/lib/WebSocketClient.py
@@ -20,6 +20,7 @@ from DownloadUtils import DownloadUtils
 from PlaybackUtils import PlaybackUtils
 from LibrarySync import LibrarySync
 from WriteKodiDB import WriteKodiDB
+from ReadEmbyDB import ReadEmbyDB
 
 pendingUserDataList = []
 pendingItemsToRemove = []
@@ -179,39 +180,40 @@ class WebSocketThread(threading.Thread):
                 self.update_items(itemsToUpdate)
 
     def remove_items(self, itemsRemoved):
+        connection = utils.KodiSQL()
+        cursor = connection.cursor()
         for item in itemsRemoved:
             self.logMsg("Message : Doing LibraryChanged : Items Removed : Calling deleteEpisodeFromKodiLibraryByMbId: " + item, 0)
-            WriteKodiDB().deleteEpisodeFromKodiLibraryByMbId(item)
-            self.logMsg("Message : Doing LibraryChanged : Items Removed : Calling deleteMovieFromKodiLibrary: " + item, 0)
-            WriteKodiDB().deleteMovieFromKodiLibrary(item)
-            self.logMsg("Message : Doing LibraryChanged : Items Removed : Calling deleteMusicVideoFromKodiLibrary: " + item, 0)
-            WriteKodiDB().deleteMusicVideoFromKodiLibrary(item)
+            WriteKodiDB().deleteItemFromKodiLibrary(item, connection, cursor)
+        connection.commit()
+        cursor.close()
 
     def update_items(self, itemsToUpdate):
         # doing adds and updates
         if(len(itemsToUpdate) > 0):
             self.logMsg("Message : Doing LibraryChanged : Processing Added and Updated : " + str(itemsToUpdate), 0)
-            connection = utils.KodiSQL()
-            cursor = connection.cursor()
-            LibrarySync().MoviesSync(connection, cursor, fullsync = False, installFirstRun = False, itemList = itemsToUpdate)
-            LibrarySync().TvShowsSync(connection, cursor, fullsync = False, installFirstRun = False, itemList = itemsToUpdate)
-            cursor.close()
+            LibrarySync().IncrementalSync(itemsToUpdate)
 
     def user_data_update(self, userDataList):
-    
+        itemsToUpdate = list()
         for userData in userDataList:
-            self.logMsg("Message : Doing UserDataChanged : UserData : " + str(userData), 0)
             itemId = userData.get("ItemId")
             if(itemId != None):
-                self.logMsg("Message : Doing UserDataChanged : calling updatePlayCount with ID : " + str(itemId), 0)
-                LibrarySync().updatePlayCount(itemId)
+                itemsToUpdate.append(itemId)
+        if(len(itemsToUpdate) > 0):
+            self.logMsg("Message : Doing UserDataChanged : Processing Updated : " + str(itemsToUpdate), 0)
+            LibrarySync().IncrementalSync(itemsToUpdate)
                 
     def on_error(self, ws, error):
-        self.logMsg("Error : " + str(error))
+        if "10061" in str(error):
+            # Server is offline
+            pass
+        else:
+            self.logMsg("Error: %s" % error, 1)
         #raise
 
     def on_close(self, ws):
-        self.logMsg("Closed")
+        self.logMsg("Closed", 2)
 
     def on_open(self, ws):
         pass
@@ -245,12 +247,19 @@ class WebSocketThread(threading.Thread):
         self.client.on_open = self.on_open
         
         while not self.KodiMonitor.abortRequested():
-            self.logMsg("Client Starting")
+            
             self.client.run_forever()
-            if(self.keepRunning):
-                self.logMsg("Client Needs To Restart")
+
+            if (self.keepRunning):
+                # Server is not online
+                if WINDOW.getProperty("Server_online") == "true":
+                    self.logMsg("Server is unreachable.", 1)
+                    WINDOW.setProperty("Server_online", "false")
+                    xbmcgui.Dialog().notification("Error connecting", "Server is unreachable.")
+                
                 if self.KodiMonitor.waitForAbort(5):
                     break
+
         self.logMsg("Thread Exited")
         
         
diff --git a/resources/lib/WriteKodiDB.py b/resources/lib/WriteKodiDB.py
index b46ccb44..7ce70520 100644
--- a/resources/lib/WriteKodiDB.py
+++ b/resources/lib/WriteKodiDB.py
@@ -20,649 +20,77 @@ from ReadEmbyDB import ReadEmbyDB
 from API import API
 import Utils as utils
 
-sleepVal = 20
+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
 
 class WriteKodiDB():
 
     def updatePlayCountFromKodi(self, id, type, playcount=0):
-        #when user marks item watched from kodi interface update this in MB3
-        xbmc.sleep(sleepVal)
+        #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))
         
-        mb3Id = ReadKodiDB().getEmbyIdByKodiId(id, type)
+        emby_id = cursor.fetchone()[0]
+        cursor.close
 
-        if(mb3Id != None):
+        if(emby_id != None):
             addon = xbmcaddon.Addon(id='plugin.video.emby')   
-            
             downloadUtils = DownloadUtils()       
-        
-            watchedurl = "{server}/mediabrowser/Users/{UserId}/PlayedItems/%s" % mb3Id
-            utils.logMsg("Emby","watchedurl -->" + watchedurl)
+            watchedurl = "{server}/mediabrowser/Users/{UserId}/PlayedItems/%s" % emby_id
             if playcount != 0:
-                downloadUtils.downloadUrl(watchedurl, postBody="", type="POST")
+                downloadUtils.downloadUrl(watchedurl, type="POST")
             else:
                 downloadUtils.downloadUrl(watchedurl, type="DELETE")
         
-    def updateMovieToKodiLibrary_Batched(self, MBitem, KodiItem,connection, cursor):
-        addon = xbmcaddon.Addon(id='plugin.video.emby')
-        WINDOW = xbmcgui.Window(10000)
-        username = WINDOW.getProperty('currUser')
-        server = WINDOW.getProperty('server%s' % username)
-        
-        downloadUtils = DownloadUtils()
-        
-        timeInfo = API().getTimeInfo(MBitem)
-        userData=API().getUserData(MBitem)
-        people = API().getPeople(MBitem)
-        genre = API().getGenre(MBitem)
-        studios = API().getStudios(MBitem)
-        mediaStreams=API().getMediaStreams(MBitem)
-        
-        thumbPath = API().getArtwork(MBitem, "Primary")
-        
-        params = list()
-        
-        self.getArtworkParam_Batched(KodiItem, MBitem, params)
-        
-        #set Filename
-        playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
-        self.setKodiFilename(KodiItem["movieid"], KodiItem["file"], playurl, "movie", MBitem["Id"], connection, cursor)
-        
-        #update common properties
-        if KodiItem["runtime"] == 0:
-            self.getPropertyParam_Batched(KodiItem, "runtime", (int(timeInfo.get('Duration'))*60), params)
-        self.getPropertyParam_Batched(KodiItem, "year", MBitem.get("ProductionYear"), params)
-        self.getPropertyParam_Batched(KodiItem, "mpaa", MBitem.get("OfficialRating"), params)
-        self.getPropertyParam_Batched(KodiItem, "lastplayed", userData.get("LastPlayedDate"), params)
-
-        self.getPropertyParamArray_Batched(KodiItem, "tag", MBitem.get("Tag"), params)
-        
-        if MBitem.get("CommunityRating") != None:
-            self.getPropertyParam_Batched(KodiItem, "rating", Decimal(format(MBitem.get("CommunityRating"),'.1f')), params)
-
-        self.getPropertyParam_Batched(KodiItem, "plot", MBitem.get("Overview"), params)
-        self.getPropertyParam_Batched(KodiItem, "plotoutline", MBitem.get("ShortOverview"), params)
-        self.getPropertyParam_Batched(KodiItem, "set", MBitem.get("TmdbCollectionName"), params)
-        self.getPropertyParam_Batched(KodiItem, "sorttitle", MBitem.get("SortName"), params)
-
-        if MBitem.get("ProviderIds") != None:
-            if MBitem.get("ProviderIds").get("Imdb") != None:
-                self.getPropertyParam_Batched(KodiItem, "imdbnumber", MBitem.get("ProviderIds").get("Imdb"), params)
-
-        # FIXME --> Taglines not returned by MB3 server !?
-        if MBitem.get("TagLines") != None:
-            self.getPropertyParam_Batched(KodiItem, "tagline", MBitem.get("TagLines")[0], params)      
-        
-        self.getPropertyParamArray_Batched(KodiItem, "writer", people.get("Writer"), params)
-        self.getPropertyParamArray_Batched(KodiItem, "director", people.get("Director"), params)
-        self.getPropertyParamArray_Batched(KodiItem, "genre", MBitem.get("Genres"), params)
-
-        if(studios != None):
-            for x in range(0, len(studios)):
-                studios[x] = studios[x].replace("/", "&")
-            self.getPropertyParamArray_Batched(KodiItem, "studio", studios, params)
-            
-        # FIXME --> ProductionLocations not returned by MB3 server !?
-        self.getPropertyParamArray_Batched(KodiItem, "country", MBitem.get("ProductionLocations"), params)
-
-        #trailer link
-        trailerUrl = None
-        if MBitem.get("LocalTrailerCount") != None and MBitem.get("LocalTrailerCount") > 0:
-            itemTrailerUrl = "{server}/mediabrowser/Users/{UserId}/Items/%s/LocalTrailers?format=json" % MBitem.get("Id")
-            jsonData = downloadUtils.downloadUrl(itemTrailerUrl)
-            if (jsonData != ""):
-                trailerItem = jsonData
-                if trailerItem[0][u'LocationType'] == "FileSystem":
-                    trailerUrl = PlayUtils().getPlayUrl(server, trailerItem[0][u'Id'], trailerItem[0])
-                    trailerUrl = utils.convertEncoding(trailerUrl)
-                    self.getPropertyParam_Batched(KodiItem, "trailer", trailerUrl, params)
-                
-
-        changes = False
-        # if there were movies changes then send the update via JSONRPC
-        if(len(params) > 0):
-            changes |= True
-            utils.logMsg("UpdateMovieParams", str(params), level = 2)
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": { "movieid": %i, %s}, "id": 1 }'
-            paramString = ""
-            paramLen = len(params)
-            for x in range(0, paramLen):
-                param = params[x]
-                paramString += param
-                if(x < paramLen-1):
-                    paramString += ", "
-            jsoncommand = jsoncommand %(KodiItem['movieid'], paramString)
-            utils.logMsg("executeJSONRPC : ", jsoncommand, level = 2)
-            xbmc.sleep(sleepVal)
-            result = xbmc.executeJSONRPC(jsoncommand.encode("utf-8"))
-            
-        #add actors
-        changes |= self.AddActorsToMedia(KodiItem,MBitem.get("People"), "movie", connection, cursor)
-        
-        if(changes):
-            utils.logMsg("Updated item to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"], level=0)
-            
-        return changes
-        
-    def updateMusicVideoToKodiLibrary_Batched(self, MBitem, KodiItem):
-        addon = xbmcaddon.Addon(id='plugin.video.emby')
-        port = addon.getSetting('port')
-        host = addon.getSetting('ipaddress')
-        server = host + ":" + port
-        #downloadUtils = DownloadUtils()
-        #userid = downloadUtils.getUserId()
-        
-        timeInfo = API().getTimeInfo(MBitem)
-        userData=API().getUserData(MBitem)
-        people = API().getPeople(MBitem)
-        genre = API().getGenre(MBitem)
-        studios = API().getStudios(MBitem)
-        mediaStreams=API().getMediaStreams(MBitem)
-        
-        thumbPath = API().getArtwork(MBitem, "Primary")
-        
-        params = list()
-        
-        self.getArtworkParam_Batched(KodiItem, MBitem, params)
-
-        #update common properties
-        if KodiItem["runtime"] == None:
-            self.getPropertyParam_Batched(KodiItem, "runtime", (int(timeInfo.get('Duration'))*60), params)
-        self.getPropertyParam_Batched(KodiItem, "year", MBitem.get("ProductionYear"), params)
-        self.getPropertyParamArray_Batched(KodiItem, "director", people.get("Director"), params)
-        self.getPropertyParamArray_Batched(KodiItem, "genre", MBitem.get("Genres"), params)
-        self.getPropertyParamArray_Batched(KodiItem, "artist", MBitem.get("Artist"), params)
-        self.getPropertyParamArray_Batched(KodiItem, "album", MBitem.get("Album"), params)
-        self.getPropertyParam_Batched(KodiItem, "lastplayed", userData.get("LastPlayedDate"), params)
-
-        if(studios != None):
-            for x in range(0, len(studios)):
-                studios[x] = studios[x].replace("/", "&")
-            self.getPropertyParamArray_Batched(KodiItem, "studio", studios, params)
-
-        changes = False
-        # if there were movies changes then send the update via JSONRPC
-        if(len(params) > 0):
-            changes |= True
-            utils.logMsg("UpdateMovieParams", str(params), level = 2)
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMusicVideoDetails", "params": { "musicvideoid": %i, %s}, "id": 1 }'
-            paramString = ""
-            paramLen = len(params)
-            for x in range(0, paramLen):
-                param = params[x]
-                paramString += param
-                if(x < paramLen-1):
-                    paramString += ", "
-            jsoncommand = jsoncommand %(KodiItem['musicvideoid'], paramString)
-            utils.logMsg("executeJSONRPC : ", jsoncommand, level = 2)
-            xbmc.sleep(sleepVal)
-            result = xbmc.executeJSONRPC(jsoncommand.encode("utf-8"))
-        
-        if(changes):
-            utils.logMsg("Updated musicvideo to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"], level=0)
-                   
-    def updateTVShowToKodiLibrary( self, MBitem, KodiItem,connection, cursor ):
-
-        addon = xbmcaddon.Addon(id='plugin.video.emby')
-        port = addon.getSetting('port')
-        host = addon.getSetting('ipaddress')
-        server = host + ":" + port        
-        downloadUtils = DownloadUtils()
-        
-        timeInfo = API().getTimeInfo(MBitem)
-        userData=API().getUserData(MBitem)
-        people = API().getPeople(MBitem)
-        genre = API().getGenre(MBitem)
-        studios = API().getStudios(MBitem)
-        mediaStreams=API().getMediaStreams(MBitem)
-        
-        thumbPath = API().getArtwork(MBitem, "Primary")
-        
-        changes = False
-      
-        #set Filename
-        playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
-        #make sure that the path always ends with a slash
-        playurl = playurl + "/"
-        self.setKodiFilename(KodiItem["tvshowid"], KodiItem["file"], playurl, "tvshow", MBitem["Id"], connection, cursor)
-   
-        #update/check all artwork
-        changes |= self.updateArtWork(KodiItem,MBitem)
-
-        #update common properties
-        if MBitem.get("PremiereDate") != None:
-            premieredatelist = (MBitem.get("PremiereDate")).split("T")
-            premieredate = premieredatelist[0]
-            changes |= self.updateProperty(KodiItem,"premiered",premieredate,"tvshow")
-
-        changes |= self.updatePropertyArray(KodiItem,"tag",MBitem.get("Tag"),"tvshow")        
-        changes |= self.updateProperty(KodiItem,"mpaa",MBitem.get("OfficialRating"),"tvshow")
-        changes |= self.updateProperty(KodiItem,"lastplayed",MBitem.get("LastPlayedDate"),"tvshow")
-        
-        if MBitem.get("CommunityRating") != None:
-            changes |= self.updateProperty(KodiItem,"rating",Decimal(format(MBitem.get("CommunityRating"),'.1f')),"tvshow")
-        
-        changes |= self.updateProperty(KodiItem,"sorttitle",utils.convertEncoding(MBitem["SortName"]),"tvshow")
-        changes |= self.updateProperty(KodiItem,"title",utils.convertEncoding(MBitem["Name"]),"tvshow")
-        changes |= self.updateProperty(KodiItem,"plot",utils.convertEncoding(API().getOverview(MBitem)),"tvshow")
-        
-        # we use this to store the Emby ID so make sure we use that
-        changes |= self.updateProperty(KodiItem, "imdbnumber", MBitem.get("Id"), "tvshow")
-        
-        changes |= self.updatePropertyArray(KodiItem,"genre",MBitem.get("Genres"),"tvshow")
-        
-        if(studios != None):
-            for x in range(0, len(studios)):
-                studios[x] = studios[x].replace("/", "&")
-            changes |= self.updatePropertyArray(KodiItem,"studio",studios,"tvshow")
-        
-        # FIXME --> ProductionLocations not returned by MB3 server !?
-        changes |= self.updatePropertyArray(KodiItem, "country", MBitem.get("ProductionLocations"), "tvshow")
-        
-        #add actors
-        changes |= self.AddActorsToMedia(KodiItem,MBitem.get("People"),"tvshow", connection, cursor)
-        
-        #update season details
-        self.updateSeasons(MBitem, KodiItem,connection, cursor)
-        
-        if changes:
-            utils.logMsg("Updated item to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"])
-        
-        return changes
-                  
-    def updateEpisodeToKodiLibrary( self, MBitem, KodiItem, connection, cursor ):       
-        addon = xbmcaddon.Addon(id='plugin.video.emby')
-        port = addon.getSetting('port')
-        host = addon.getSetting('ipaddress')
-        server = host + ":" + port        
-        
-        timeInfo = API().getTimeInfo(MBitem)
-        people = API().getPeople(MBitem)
-        genre = API().getGenre(MBitem)
-        studios = API().getStudios(MBitem)
-        mediaStreams=API().getMediaStreams(MBitem)
-        userData=API().getUserData(MBitem)
-        
-        changes = False
-
-        #update/check all artwork
-        changes |= self.updateArtWork(KodiItem,MBitem)
-        
-        #set Filename (will update the filename in db if changed)
-        playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
-        changes |= self.setKodiFilename(KodiItem["episodeid"], KodiItem["file"], playurl, "episode", MBitem["Id"], connection, cursor)
-        
-        #update common properties
-        if KodiItem["runtime"] == 0:
-            changes |= self.updateProperty(KodiItem,"runtime",(int(timeInfo.get('Duration'))*60),"episode")
-        changes |= self.updateProperty(KodiItem,"lastplayed",userData.get("LastPlayedDate"),"episode")
-
-        if MBitem.get("PremiereDate") != None:
-            premieredatelist = (MBitem.get("PremiereDate")).split("T")
-            premieredate = premieredatelist[0]
-            premieretime = premieredatelist[1].split(".")[0]
-            firstaired = premieredate + " " + premieretime
-            # for Helix we use the whole time string, for kodi 15 we have to change to only the datestring
-            # see: http://forum.kodi.tv/showthread.php?tid=218743
-            if KodiItem["firstaired"] != premieredate:
-                changes |= self.updateProperty(KodiItem,"firstaired",firstaired,"episode")
-        
-        if MBitem.get("CommunityRating") != None:
-            changes |= self.updateProperty(KodiItem,"rating",Decimal(format(MBitem.get("CommunityRating"),'.1f')),"episode")
-            
-        if MBitem.get("ParentIndexNumber") != None:
-            season = int(MBitem.get("ParentIndexNumber"))
-            changes |= self.updateProperty(KodiItem,"season",season,"episode")
-            # removed for now as setting c15 and c16 to -1 just shows specials in the special folder only
-            #if(season == 0):
-            #    changes |= self.setSpecialAirsDetails(MBitem, KodiItem, connection, cursor)
-        
-        if MBitem.get("IndexNumber") != None:
-            episode = int(MBitem.get("IndexNumber"))
-            changes |= self.updateProperty(KodiItem,"episode",episode,"episode")
-
-        #plot = utils.convertEncoding(API().getOverview(MBitem))
-        plot = MBitem.get("Overview")
-        if(plot != None):
-            changes |= self.updateProperty(KodiItem,"plot",plot,"episode")
-            
-        title = utils.convertEncoding(MBitem["Name"])
-        changes |= self.updateProperty(KodiItem,"title",title,"episode")
-        changes |= self.updatePropertyArray(KodiItem,"writer",people.get("Writer"),"episode")
-        changes |= self.updatePropertyArray(KodiItem,"director",people.get("Director"),"episode")
-
-        #add actors
-        changes |= self.AddActorsToMedia(KodiItem,MBitem.get("People"),"episode", connection, cursor)
-        
-        if changes:
-            utils.logMsg("Updated item to Kodi Library", MBitem["Id"] + " - " + MBitem["Name"])
-    
-        return changes
-        
-    def getArtworkParam_Batched(self, KodiItem, MBitem, params):
-
-        
-        item_type=str(MBitem.get("Type"))
-        
-        '''
-        if item_type == "Series":
-            id = KodiItem['tvshowid']
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetTVShowDetails", "params": { "tvshowid": %i, "art": %s}, "id": 1 }'
-        elif item_type == "Episode":
-            # episodes don't have any artwork - they derrive this from the tv show
-            return False
-        elif item_type == "MusicVideo":
-            id = KodiItem['musicvideoid']
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMusicVideoDetails", "params": { musicvideoid": %i, "art": %s}, "id": 1 }'
-        elif item_type == "Movie":
-            id = KodiItem['movieid']
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": { "movieid": %i, "art": %s}, "id": 1 }'
-        '''
-        
-        #update artwork
-        changes = False
-        
-        artwork = {}
-        artwork["poster"] = API().getArtwork(MBitem, "Primary")
-        
-        if(item_type != "Episode"):        
-            artwork["banner"] = API().getArtwork(MBitem, "Banner")
-            artwork["clearlogo"] = API().getArtwork(MBitem, "Logo")
-            artwork["clearart"] = API().getArtwork(MBitem, "Art")
-            artwork["landscape"] = API().getArtwork(MBitem, "Thumb")
-            artwork["discart"] = API().getArtwork(MBitem, "Disc")
-            artwork["fanart"] = API().getArtwork(MBitem, "Backdrop")
-        
-        for art in artwork:
-            if artwork.get(art) != "":
-                if KodiItem["art"].has_key(art):
-                    curValue = urllib.unquote(KodiItem['art'][art]).decode('utf8')
-                    if not artwork.get(art) in curValue:
-                        KodiItem["art"][art] = artwork.get(art)
-                        changes = True
-                else:
-                    KodiItem["art"][art] = artwork.get(art)
-                    changes = True
-        
-        if len(KodiItem["art"]) == 0:
-            changes = False
-        
-        if changes:
-            json_array = json.dumps(KodiItem["art"])
-            params.append("\"art\": " + json_array)
-            #result = xbmc.executeJSONRPC(jsoncommand %(id, json_array))
-        return changes
-        
-    # adds or updates artwork to the given Kodi file in database
-    def updateArtWork(self,KodiItem,MBitem):
-        item_type=str(MBitem.get("Type"))
-        
-        if item_type == "Series":
-            id = KodiItem['tvshowid']
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetTVShowDetails", "params": { "tvshowid": %i, "art": %s}, "id": 1 }'
-        elif item_type == "Episode":
-            id = KodiItem['episodeid']
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetEpisodeDetails", "params": { "episodeid": %i, "art": %s}, "id": 1 }'
-        elif item_type == "MusicVideo":
-            id = KodiItem['musicvideoid']
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMusicVideoDetails", "params": { musicvideoid": %i, "art": %s}, "id": 1 }'
-        elif item_type == "Movie":
-            id = KodiItem['movieid']
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": { "movieid": %i, "art": %s}, "id": 1 }'
-
-        #update artwork
-        changes = False
-        
-        artwork = {}
-        artwork["thumb"] = API().getArtwork(MBitem, "Primary")
-        
-        if(item_type != "Episode"):
-            artwork["poster"] = API().getArtwork(MBitem, "Primary")
-            artwork["banner"] = API().getArtwork(MBitem, "Banner")
-            artwork["clearlogo"] = API().getArtwork(MBitem, "Logo")
-            artwork["clearart"] = API().getArtwork(MBitem, "Art")
-            artwork["landscape"] = API().getArtwork(MBitem, "Thumb")
-            artwork["discart"] = API().getArtwork(MBitem, "Disc")
-            artwork["fanart"] = API().getArtwork(MBitem, "Backdrop")
-        
-        for art in artwork:
-            if artwork.get(art) != "":
-                if KodiItem["art"].has_key(art):
-                    curValue = urllib.unquote(KodiItem['art'][art]).decode('utf8')
-                    if not artwork.get(art) in curValue:
-                        KodiItem["art"][art] = artwork.get(art)
-                        changes = True
-                else:
-                    KodiItem["art"][art] = artwork.get(art)
-                    changes = True
-        
-        if len(KodiItem["art"]) == 0:
-            changes = False
-        
-        if changes:
-            json_array = json.dumps(KodiItem["art"])
-            result = xbmc.executeJSONRPC(jsoncommand %(id, json_array))
-        return changes
-    
-    def getPropertyParam_Batched(self,KodiItem, propertyName, propertyValue, params, forced = False):
-    
-        '''
-        if fileType == "tvshow":
-            id = KodiItem['tvshowid']
-            jsoncommand_i = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetTVShowDetails", "params": { "tvshowid": %i, "%s": %i}, "id": 1 }'
-            jsoncommand_s = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetTVShowDetails", "params": { "tvshowid": %i, "%s": "%s"}, "id": 1 }'
-        elif fileType == "episode":
-            id = KodiItem['episodeid']  
-            jsoncommand_i = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetEpisodeDetails", "params": { "episodeid": %i, "%s": %i}, "id": 1 }'            
-            jsoncommand_s = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetEpisodeDetails", "params": { "episodeid": %i, "%s": "%s"}, "id": 1 }'
-        elif fileType == "musicvideo":
-            id = KodiItem['musicvideoid']
-            jsoncommand_i = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMusicVideoDetails", "params": { "musicvideoid": %i, "%s": %i}, "id": 1 }'
-            jsoncommand_s = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMusicVideoDetails", "params": { "musicvideoid": %i, "%s": "%s"}, "id": 1 }'
-        elif fileType == "movie":
-            id = KodiItem['movieid']
-            jsoncommand_i = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": { "movieid": %i, "%s": %i}, "id": 1 }'
-            jsoncommand_s = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": { "movieid": %i, "%s": "%s"}, "id": 1 }'
-        '''
-        
-        changes = False
-        if ((propertyValue != KodiItem[propertyName]) or forced):
-            if propertyValue != None:
-                if type(propertyValue) is int:
-                    #xbmc.sleep(sleepVal)
-                    utils.logMsg("Emby","updating property..." + str(propertyName))
-                    utils.logMsg("Emby","kodi value:" + str(KodiItem[propertyName]) + " MB value: " + str(propertyValue))
-                    params.append("\"" + propertyName + "\": " + str(propertyValue))
-                    #xbmc.executeJSONRPC(jsoncommand_i %(id, propertyName, propertyValue))
-                    changes = True
-                elif type(propertyValue) is Decimal:
-                    #extra compare decimals as int (rounded)
-                    if int(propertyValue) != int(KodiItem[propertyName]):
-                        utils.logMsg("Emby","updating property..." + str(propertyName))
-                        utils.logMsg("Emby","kodi value:" + str(KodiItem[propertyName]) + " MB value: " + str(propertyValue))
-                        params.append("\"" + propertyName + "\": " + str(propertyValue))
-                        changes = True
-                else:
-                    #xbmc.sleep(sleepVal)
-                    propValue = json.dumps(propertyValue)
-                    utils.logMsg("Emby","updating property..." + str(propertyName))
-                    utils.logMsg("Emby","kodi value:" + KodiItem[propertyName] + " MB value: " + propValue)
-                    params.append("\"" + propertyName + "\": " + propValue)
-                    #xbmc.executeJSONRPC(jsoncommand_s %(id, propertyName, propertyValue.encode('utf-8')))
-                    changes = True
-                    
-        return changes
-        
-    # adds or updates the given property on the videofile in Kodi database
-    def updateProperty(self,KodiItem,propertyName,propertyValue,fileType,forced=False):
-        if fileType == "tvshow":
-            id = KodiItem['tvshowid']
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetTVShowDetails", "params": { "tvshowid": %i, "%s": %s}, "id": 1 }'
-        elif fileType == "episode":
-            id = KodiItem['episodeid']  
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetEpisodeDetails", "params": { "episodeid": %i, "%s": %s}, "id": 1 }'            
-        elif fileType == "musicvideo":
-            id = KodiItem['musicvideoid']
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMusicVideoDetails", "params": { "musicvideoid": %i, "%s": %s}, "id": 1 }'
-        elif fileType == "movie":
-            id = KodiItem['movieid']
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": { "movieid": %i, "%s": %s}, "id": 1 }'
-        
-        changes = False
-        if ((propertyValue != KodiItem[propertyName]) or forced):
-            if propertyValue != None:
-                if type(propertyValue) is int:
-                    xbmc.sleep(sleepVal)
-                    utils.logMsg("Emby","updating property..." + str(propertyName))
-                    utils.logMsg("Emby","kodi value:" + str(KodiItem[propertyName]) + " MB value: " + str(propertyValue))
-                    xbmc.executeJSONRPC(jsoncommand %(id, propertyName, propertyValue))
-                    changes = True
-                elif type(propertyValue) is Decimal:
-                    #extra compare decimals as int (rounded)
-                    if int(propertyValue) != int(KodiItem[propertyName]):
-                        xbmc.sleep(sleepVal)
-                        utils.logMsg("Emby","updating property..." + str(propertyName))
-                        utils.logMsg("Emby","kodi value:" + str(KodiItem[propertyName]) + " MB value: " + str(propertyValue))
-                        xbmc.executeJSONRPC(jsoncommand %(id, propertyName, propertyValue))
-                        changes = True
-                else:
-                    xbmc.sleep(sleepVal)
-                    propValue = json.dumps(propertyValue)
-                    utils.logMsg("Emby","updating property..." + str(propertyName))
-                    utils.logMsg("Emby","kodi value:" + KodiItem[propertyName] + " MB value: " + propValue)
-                    xbmc.executeJSONRPC(jsoncommand %(id, propertyName, propValue))
-                    changes = True
-                    
-        return changes
-
-    def getPropertyParamArray_Batched(self, KodiItem, propertyName, propertyCollection, params):
-        '''
-        if fileType == "tvshow":
-            id = KodiItem['tvshowid']   
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetTVShowDetails", "params": { "tvshowid": %i, "%s": %s}, "id": 1 }'
-        elif fileType == "episode":
-            id = KodiItem['episodeid']   
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetEpisodeDetails", "params": { "episodeid": %i, "%s": %s}, "id": 1 }'
-        elif fileType == "musicvideo":
-            id = KodiItem['musicvideoid']   
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMusicVideoDetails", "params": { "musicvideoid": %i, "%s": %s}, "id": 1 }'
-        elif fileType == "movie":
-            id = KodiItem['movieid']   
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": { "movieid": %i, "%s": %s}, "id": 1 }'
-        '''
-        
-        pendingChanges = False
-        if propertyCollection != None:   
-            currentvalues = set(KodiItem[propertyName])
-            for item in propertyCollection:
-                if not item in currentvalues:
-                    pendingChanges = True
-                    json_array = json.dumps(propertyCollection)
-            
-            if pendingChanges:
-                #xbmc.sleep(sleepVal)
-                utils.logMsg("Emby","updating propertyarray... Name:" + str(propertyName) + " Current:" + str(currentvalues) + " New:" + str(json_array))
-                params.append("\"" + propertyName + "\": " + json_array)
-                #xbmc.executeJSONRPC(jsoncommand %(id,propertyName,json_array))
-
-        return pendingChanges        
-        
-    # adds or updates the property-array on the videofile in Kodi database
-    def updatePropertyArray(self,KodiItem,propertyName,propertyCollection,fileType):
-        if fileType == "tvshow":
-            id = KodiItem['tvshowid']   
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetTVShowDetails", "params": { "tvshowid": %i, "%s": %s}, "id": 1 }'
-        elif fileType == "episode":
-            id = KodiItem['episodeid']   
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetEpisodeDetails", "params": { "episodeid": %i, "%s": %s}, "id": 1 }'
-        elif fileType == "musicvideo":
-            id = KodiItem['musicvideoid']   
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMusicVideoDetails", "params": { "musicvideoid": %i, "%s": %s}, "id": 1 }'
-        elif fileType == "movie":
-            id = KodiItem['movieid']   
-            jsoncommand = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": { "movieid": %i, "%s": %s}, "id": 1 }'
-
-        pendingChanges = False
-        if (propertyCollection != None and KodiItem.get(propertyName) != None):   
-            currentvalues = set(KodiItem[propertyName])
-            for item in propertyCollection:
-                if not item in currentvalues:
-                    pendingChanges = True
-                    json_array = json.dumps(propertyCollection)
-            
-            if pendingChanges:
-                xbmc.sleep(sleepVal)
-                utils.logMsg("Emby","updating propertyarray... Name:" + str(propertyName) + " Current:" + str(currentvalues) + " New:" + str(json_array))
-                xbmc.executeJSONRPC(jsoncommand %(id,propertyName,json_array))
-
-        return pendingChanges
-    
-    def addMovieToKodiLibrary( self, MBitem ,connection, cursor):
-        #adds a movie to Kodi by directly inserting it to the DB while there is no addmovie available on the json API
-        #TODO: PR at Kodi team for a addMovie endpoint on their API
+    def addOrUpdateMovieToKodiLibrary( self, embyId ,connection, cursor, viewTag):
         
         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:
+            movieid = result[0]
+        else:
+            movieid = None
+        
         timeInfo = API().getTimeInfo(MBitem)
         userData=API().getUserData(MBitem)
+        people = API().getPeople(MBitem)
 
-        playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
-        playurl = utils.convertEncoding(playurl)
-        
-        if MBitem.get("DateCreated") != None:
-            dateadded = MBitem["DateCreated"].replace("T"," ")
-            dateadded = dateadded.replace(".0000000Z","")
-        else:
-            dateadded = None
-        
-        # we need to store both the path and the filename seperately in the kodi db so we split them up
-        if "\\" in playurl:
-            filename = playurl.rsplit("\\",1)[-1]
-            path = playurl.replace(filename,"")
-        elif "/" in playurl:
-            filename = playurl.rsplit("/",1)[-1]
-            path = playurl.replace(filename,"")
-                    
-        #create 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, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)"
-            cursor.execute(pathsql, (pathid,path,"movies","metadata.local",1))
-        
-        playcount = None
-        if userData.get("PlayCount") == "1":
-            playcount = 1
-            
-        #create the file if not exists
-        cursor.execute("SELECT idFile as fileid FROM files WHERE strFilename = ? and idPath = ?",(filename,pathid,))
-        result = cursor.fetchone()
-        if result != None:
-            fileid = result[0]
-        if result == None:
-            cursor.execute("select coalesce(max(idFile),0) as fileid from files")
-            fileid = cursor.fetchone()[0]
-            fileid = fileid + 1
-            pathsql="insert into files(idFile, idPath, strFilename, playCount, lastPlayed, dateAdded) values(?, ?, ?, ?, ?, ?)"
-            cursor.execute(pathsql, (fileid,pathid,filename,playcount,userData.get("LastPlayedDate"),dateadded))
-        
+        #### The movie details #########
         runtime = int(timeInfo.get('Duration'))*60
         plot = utils.convertEncoding(API().getOverview(MBitem))
         title = utils.convertEncoding(MBitem["Name"])
         sorttitle = utils.convertEncoding(MBitem["SortName"])
         year = MBitem.get("ProductionYear")
         rating = MBitem.get("CommunityRating")
+        mpaa = MBitem.get("OfficialRating")
+        genres = MBitem.get("Genres")
+        genre = " / ".join(genres)
+        studios = API().getStudios(MBitem)
+        studio = " / ".join(studios)
+        writer = " / ".join(people.get("Writer"))
+        director = " / ".join(people.get("Director"))
+        
+        imdb = None
+        if MBitem.get("ProviderIds"):
+            if MBitem.get("ProviderIds").get("Imdb"):
+                imdb = MBitem.get("ProviderIds").get("Imdb")
 
         if MBitem.get("ShortOverview") != None:
             shortplot = utils.convertEncoding(MBitem.get("ShortOverview"))
@@ -675,55 +103,22 @@ class WriteKodiDB():
             jsonData = downloadUtils.downloadUrl(itemTrailerUrl)
             if(jsonData != ""):
                 trailerItem = jsonData
-                if trailerItem[0][u'LocationType'] == "FileSystem":
-                    trailerUrl = PlayUtils().getPlayUrl(server, trailerItem[0][u'Id'], trailerItem[0])
-                    trailerUrl = utils.convertEncoding(trailerUrl)
-        
-        #create the movie
-        cursor.execute("select coalesce(max(idMovie),0) as movieid from movie")
-        movieid = cursor.fetchone()[0]
-        movieid = movieid + 1
-        pathsql="insert into movie(idMovie, idFile, c00, c01, c02, c05, c07, c09, c10, c11, c16, c19) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
-        
-        cursor.execute(pathsql, (movieid, fileid, title, plot, shortplot, rating, year, MBitem["Id"], sorttitle, runtime, title, trailerUrl))
-        
-        try:
-            connection.commit()
-            utils.logMsg("Emby","Added movie to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"])
-        except:
-            utils.logMsg("Emby","Error adding movie to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"])
-            actionPerformed = False
-    
-    def addMusicVideoToKodiLibrary( self, MBitem, connection, cursor  ):
-
-        #adds a musicvideo to Kodi by directly inserting it to connectionthe DB while there is no addMusicVideo available on the json API
-        #TODO: PR at Kodi team for a addMusicVideo endpoint on their API
-        
-        addon = xbmcaddon.Addon(id='plugin.video.emby')
-        port = addon.getSetting('port')
-        host = addon.getSetting('ipaddress')
-        server = host + ":" + port
-        
-        timeInfo = API().getTimeInfo(MBitem)
-        userData=API().getUserData(MBitem)
-        
-        playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
-        playurl = utils.convertEncoding(playurl)
+                trailerUrl = "plugin://plugin.video.emby/trailer/?id=%s&mode=play" % trailerItem[0][u'Id']
         
         if MBitem.get("DateCreated") != None:
-            dateadded = MBitem["DateCreated"].replace("T"," ")
-            dateadded = dateadded.replace(".0000000Z","")
+            dateadded = MBitem["DateCreated"].split('.')[0].replace('T', " ")
         else:
             dateadded = None
-
-        # we need to store both the path and the filename seperately in the kodi db so we split them up
-        if "\\" in playurl:
-            filename = playurl.rsplit("\\",1)[-1]
-            path = playurl.replace(filename,"")
-        elif "/" in playurl:
-            filename = playurl.rsplit("/",1)[-1]
-            path = playurl.replace(filename,"")
-                    
+        
+        playcount = 0
+        if userData.get("PlayCount") == "1":
+            playcount = 1
+            
+        #### ADD OR UPDATE THE FILE AND PATH ###########
+        #### NOTE THAT LASTPLAYED AND PLAYCOUNT ARE STORED AT THE FILE ENTRY
+        path = "plugin://plugin.video.emby/movies/%s/" % MBitem["Id"]
+        filename = "plugin://plugin.video.emby/movies/%s/?id=%s&mode=play" % (MBitem["Id"],MBitem["Id"])
+        
         #create the path
         cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?",(path,))
         result = cursor.fetchone()
@@ -735,13 +130,9 @@ class WriteKodiDB():
             pathid = pathid + 1
             pathsql = "insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)"
             cursor.execute(pathsql, (pathid,path,"movies","metadata.local",1))
-        
-        playcount = None
-        if userData.get("PlayCount") == "1":
-            playcount = 1
-            
+
         #create the file if not exists
-        cursor.execute("SELECT idFile as fileid FROM files WHERE strFilename = ?",(filename,))
+        cursor.execute("SELECT idFile as fileid FROM files WHERE strFilename = ? and idPath = ?",(filename,pathid,))
         result = cursor.fetchone()
         if result != None:
             fileid = result[0]
@@ -751,36 +142,345 @@ class WriteKodiDB():
             fileid = fileid + 1
             pathsql="insert into files(idFile, idPath, strFilename, playCount, lastPlayed, dateAdded) values(?, ?, ?, ?, ?, ?)"
             cursor.execute(pathsql, (fileid,pathid,filename,playcount,userData.get("LastPlayedDate"),dateadded))
+        else:
+            pathsql="update files SET playCount = ?, lastPlayed = ? WHERE idFile = ?"
+            cursor.execute(pathsql, (playcount,userData.get("LastPlayedDate"), fileid))
         
+        ##### ADD THE MOVIE ############
+        if movieid == None:
+            
+            utils.logMsg("ADD movie to Kodi library","Id: %s - Title: %s" % (embyId, title))
+            
+            #create the movie
+            cursor.execute("select coalesce(max(idMovie),0) as movieid from movie")
+            movieid = cursor.fetchone()[0]
+            movieid = movieid + 1
+            pathsql="insert into movie(idMovie, idFile, c00, c01, c02, c05, c06, c07, c09, c10, c11, c12, c14, c15, c16, c18, c19) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
+            cursor.execute(pathsql, (movieid, fileid, title, plot, shortplot, rating, writer, year, imdb, sorttitle, runtime, mpaa, genre, director, title, studio, trailerUrl))
+            
+            #add the viewtag
+            self.AddTagToMedia(movieid, viewTag, "movie", cursor)
+            
+            #create the reference in emby table
+            pathsql = "INSERT into emby(emby_id, kodi_id, media_type, checksum) values(?, ?, ?, ?)"
+            cursor.execute(pathsql, (MBitem["Id"], movieid, "movie", API().getChecksum(MBitem)))
+                        
+        #### UPDATE THE MOVIE #####
+        else:
+            utils.logMsg("UPDATE movie to Kodi library","Id: %s - Title: %s" % (embyId, title))
+            pathsql="update movie SET c00 = ?, c01 = ?, c02 = ?, c05 = ?, c06 = ?, c07 = ?, c09 = ?, c10 = ?, c11 = ?, c12 = ?, c14 = ?, c15 = ?, c16 = ?, c18 = ?, c19 = ? WHERE idMovie = ?"
+            cursor.execute(pathsql, (title, plot, shortplot, rating, writer, year, imdb, sorttitle, runtime, mpaa, genre, director, title, studio, trailerUrl, movieid))
+            
+            #update the checksum in emby table
+            cursor.execute("UPDATE emby SET checksum = ? WHERE emby_id = ?", (API().getChecksum(MBitem),MBitem["Id"]))
+        
+        #update or insert actors
+        self.AddPeopleToMedia(movieid,MBitem.get("People"),"movie", connection, cursor)
+        
+        #update artwork
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), movieid, "movie", "thumb", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), movieid, "movie", "poster", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Banner"), movieid, "movie", "banner", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Logo"), movieid, "movie", "clearlogo", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Art"), movieid, "movie", "clearart", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Thumb"), movieid, "movie", "landscape", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Disc"), movieid, "movie", "discart", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Backdrop"), movieid, "movie", "fanart", cursor)
+        
+        #update genres
+        self.AddGenresToMedia(movieid, genres, "movie", cursor)
+               
+        #update studios
+        self.AddStudiosToMedia(movieid, studios, "movie", cursor)
+        
+        #add streamdetails
+        self.AddStreamDetailsToMedia(API().getMediaStreams(MBitem), fileid, cursor)
+        
+        #add to favorites tag --> todo translated label for favorites ?
+        if userData.get("Favorite"):
+            self.AddTagToMedia(movieid, "Favorite movies", "movie", cursor)
+        else:
+            self.AddTagToMedia(movieid, "Favorite movies", "movie", cursor, True)
+        
+        #set resume point
+        resume = int(round(float(timeInfo.get("ResumeTime"))))*60
+        total = int(round(float(timeInfo.get("TotalTime"))))*60
+        self.setKodiResumePoint(fileid, resume, total, cursor)
+        
+
+    def addOrUpdateMusicVideoToKodiLibrary( 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:
+            idMVideo = result[0]
+        else:
+            idMVideo = None
+        
+        timeInfo = API().getTimeInfo(MBitem)
+        userData=API().getUserData(MBitem)
+        people = API().getPeople(MBitem)
+
+        #### The video details #########
         runtime = int(timeInfo.get('Duration'))*60
         plot = utils.convertEncoding(API().getOverview(MBitem))
         title = utils.convertEncoding(MBitem["Name"])
-                
-        #create the musicvideo
-        cursor.execute("select coalesce(max(idMVideo),0) as musicvideoid from musicvideo")
-        musicvideoid = cursor.fetchone()[0]
-        musicvideoid = musicvideoid + 1
-        pathsql="insert into musicvideo(idMVideo, idFile, c00, c04, c08, c23) values(?, ?, ?, ?, ?, ?)"
-        cursor.execute(pathsql, (musicvideoid, fileid, title, runtime, plot, MBitem["Id"]))
+        year = MBitem.get("ProductionYear")
+        genres = MBitem.get("Genres")
+        genre = " / ".join(genres)
+        studios = API().getStudios(MBitem)
+        studio = " / ".join(studios)
+        director = " / ".join(people.get("Director"))
+        artist = " / ".join(MBitem.get("Artists"))
+        album = MBitem.get("Album")
+        track = MBitem.get("Track")
         
-        try:
-            connection.commit()
-            utils.logMsg("Emby","Added musicvideo to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"])
-        except:
-            utils.logMsg("Emby","Error adding musicvideo to Kodi Library",MBitem["Id"] + " - " + MBitem["Name"])
-            actionPerformed = False
-    
-    def addEpisodeToKodiLibrary(self, MBitem, connection, cursor):
+        if MBitem.get("DateCreated") != None:
+            dateadded = MBitem["DateCreated"].split('.')[0].replace('T', " ")
+        else:
+            dateadded = None
         
-        #adds a Episode to Kodi by directly inserting it to the DB while there is no addEpisode available on the json API
-        #TODO: PR at Kodi team for a addEpisode endpoint on their API
+        playcount = 0
+        if userData.get("PlayCount") == "1":
+            playcount = 1
+            
+        #### ADD OR UPDATE THE FILE AND PATH ###########
+        #### NOTE THAT LASTPLAYED AND PLAYCOUNT ARE STORED AT THE FILE ENTRY
+        path = "plugin://plugin.video.emby/musicvideos/%s/" % MBitem["Id"]
+        filename = "plugin://plugin.video.emby/musicvideos/%s/?id=%s&mode=play" % (MBitem["Id"], MBitem["Id"])
         
-        # first check the episode is not already in the DB using the Emby ID which is stored in c20
-        cursor.execute("SELECT idEpisode FROM episode WHERE c20 = ?",(MBitem["Id"],))
+        #create the path
+        cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?",(path,))
         result = cursor.fetchone()
         if result != None:
-            utils.logMsg("Emby", "Episode already exists in DB : " + MBitem["Id"] + " - " + MBitem["Name"], 2)
-            return
+            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, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)"
+            cursor.execute(pathsql, (pathid,path,"musicvideos","metadata.local",1))
+
+        #create the file if not exists
+        cursor.execute("SELECT idFile as fileid FROM files WHERE strFilename = ? and idPath = ?",(filename,pathid,))
+        result = cursor.fetchone()
+        if result != None:
+            fileid = result[0]
+        if result == None:
+            cursor.execute("select coalesce(max(idFile),0) as fileid from files")
+            fileid = cursor.fetchone()[0]
+            fileid = fileid + 1
+            pathsql="insert into files(idFile, idPath, strFilename, playCount, lastPlayed, dateAdded) values(?, ?, ?, ?, ?, ?)"
+            cursor.execute(pathsql, (fileid,pathid,filename,playcount,userData.get("LastPlayedDate"),dateadded))
+        else:
+            pathsql="update files SET playCount = ?, lastPlayed = ? WHERE idFile = ?"
+            cursor.execute(pathsql, (playcount,userData.get("LastPlayedDate"), fileid))
+        
+        ##### ADD THE VIDEO ############
+        if idMVideo == None:
+            
+            utils.logMsg("ADD musicvideo to Kodi library","Id: %s - Title: %s" % (embyId, title))
+            
+            #create the video
+            cursor.execute("select coalesce(max(idMVideo),0) as idMVideo from musicvideo")
+            idMVideo = cursor.fetchone()[0]
+            idMVideo = idMVideo + 1
+            pathsql="insert into musicvideo(idMVideo, idFile, c00, c04, c05, c06, c07, c08, c09, c10, c11, c12) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
+            cursor.execute(pathsql, (idMVideo, fileid, title, runtime, director, studio, year, plot, album, artist, genre, track))
+            
+            #create the reference in emby table
+            pathsql = "INSERT into emby(emby_id, kodi_id, media_type, checksum) values(?, ?, ?, ?)"
+            cursor.execute(pathsql, (MBitem["Id"], idMVideo, "musicvideo", API().getChecksum(MBitem)))
+            
+        #### UPDATE THE VIDEO #####
+        else:
+            utils.logMsg("UPDATE musicvideo to Kodi library","Id: %s - Title: %s" % (embyId, title))
+            pathsql="update musicvideo SET c00 = ?, c04 = ?, c05 = ?, c06 = ?, c07 = ?, c08 = ?, c09 = ?, c10 = ?, c11 = ?, c12 = ? WHERE idMVideo = ?"
+            cursor.execute(pathsql, (title, runtime, director, studio, year, plot, album, artist, genre, track, idMVideo))
+            
+            #update the checksum in emby table
+            cursor.execute("UPDATE emby SET checksum = ? WHERE emby_id = ?", (API().getChecksum(MBitem),MBitem["Id"]))
+        
+        #update or insert actors
+        self.AddPeopleToMedia(idMVideo,MBitem.get("People"),"musicvideo", connection, cursor)
+        
+        #update artwork
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), idMVideo, "musicvideo", "thumb", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), idMVideo, "musicvideo", "poster", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Banner"), idMVideo, "musicvideo", "banner", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Logo"), idMVideo, "musicvideo", "clearlogo", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Art"), idMVideo, "musicvideo", "clearart", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Thumb"), idMVideo, "musicvideo", "landscape", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Disc"), idMVideo, "musicvideo", "discart", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Backdrop"), idMVideo, "musicvideo", "fanart", cursor)
+        
+        #update genres
+        self.AddGenresToMedia(idMVideo, genres, "musicvideo", cursor)
+               
+        #update studios
+        self.AddStudiosToMedia(idMVideo, studios, "musicvideo", cursor)
+        
+        #add streamdetails
+        self.AddStreamDetailsToMedia(API().getMediaStreams(MBitem), fileid, cursor)
+        
+        #set resume point
+        resume = int(round(float(timeInfo.get("ResumeTime"))))*60
+        total = int(round(float(timeInfo.get("TotalTime"))))*60
+        self.setKodiResumePoint(fileid, resume, total, cursor)
+    
+    def addOrUpdateTvShowToKodiLibrary( self, embyId, connection, cursor, viewTag ):
+        
+        addon = xbmcaddon.Addon(id='plugin.video.emby')
+        port = addon.getSetting('port')
+        host = addon.getSetting('ipaddress')
+        server = host + ":" + port
+        
+        MBitem = ReadEmbyDB().getFullItem(embyId)
+        
+        timeInfo = API().getTimeInfo(MBitem)
+        userData=API().getUserData(MBitem)
+        
+        thumbPath = API().getArtwork(MBitem, "Primary")
+        
+        # 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:
+            showid = result[0]
+        else:
+            showid = None
+        
+        #### TV SHOW DETAILS #########
+        
+        genres = MBitem.get("Genres")
+        genre = " / ".join(genres)
+        studios = API().getStudios(MBitem)
+        studio = " / ".join(studios)
+        mpaa = MBitem.get("OfficialRating")
+        runtime = int(timeInfo.get('Duration'))*60
+        plot = utils.convertEncoding(API().getOverview(MBitem))
+        title = utils.convertEncoding(MBitem["Name"])
+        sorttitle = utils.convertEncoding(MBitem["SortName"])
+        rating = MBitem.get("CommunityRating")
+        
+        if MBitem.get("DateCreated") != None:
+            dateadded = MBitem["DateCreated"].split('.')[0].replace('T', " ")
+        else:
+            dateadded = None
+        
+        if MBitem.get("PremiereDate") != None: 
+             premieredatelist = (MBitem.get("PremiereDate")).split("T") 
+             premieredate = premieredatelist[0] 
+        else:
+            premieredate = None
+        
+        path = "plugin://plugin.video.emby/tvshows/" + MBitem["Id"] + "/"       
+            
+        #### ADD THE TV SHOW TO KODI ############## 
+        if showid == None:
+            
+            utils.logMsg("ADD tvshow to Kodi library","Id: %s - Title: %s" % (embyId, title))
+            
+            #create the tv show path
+            cursor.execute("select coalesce(max(idPath),0) as pathid from path")
+            pathid = cursor.fetchone()[0]
+            pathid = pathid + 1
+            pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)"
+            cursor.execute(pathsql, (pathid,path,None,None,1))
+            
+            #create toplevel path as monitored source - needed for things like actors and stuff to work (no clue why)
+            toplevelpath = "plugin://plugin.video.emby/"
+            cursor.execute("SELECT idPath as tlpathid FROM path WHERE strPath = ?",(toplevelpath,))
+            result = cursor.fetchone()
+            if result == None:
+                cursor.execute("select coalesce(max(idPath),0) as tlpathid from path")
+                tlpathid = cursor.fetchone()[0]
+                tlpathid = tlpathid + 1
+                pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)"
+                cursor.execute(pathsql, (tlpathid,toplevelpath,"tvshows","metadata.local",1))
+                
+            #create the tvshow
+            cursor.execute("select coalesce(max(idShow),0) as showid from tvshow")
+            showid = cursor.fetchone()[0]
+            showid = showid + 1
+            pathsql="insert into tvshow(idShow, c00, c01, c04, c05, c08, c09, c13, c14, c15) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
+            cursor.execute(pathsql, (showid, title, plot, rating, premieredate, genre, title, mpaa, studio, sorttitle))
+            
+            #create the reference in emby table
+            pathsql = "INSERT into emby(emby_id, kodi_id, media_type, checksum) values(?, ?, ?, ?)"
+            cursor.execute(pathsql, (MBitem["Id"], showid, "tvshow", API().getChecksum(MBitem)))
+            
+            #link the path
+            pathsql="insert into tvshowlinkpath(idShow,idPath) values(?, ?)"
+            cursor.execute(pathsql, (showid,pathid))
+                        
+            #add the viewtag
+            self.AddTagToMedia(showid, viewTag, "tvshow", cursor)
+        
+        #### UPDATE THE TV SHOW #############
+        else:
+            utils.logMsg("UPDATE tvshow to Kodi library","Id: %s - Title: %s" % (embyId, title))
+            
+            pathsql="UPDATE tvshow SET c00 = ?, c01 = ?, c04 = ?, c05 = ?, c08 = ?, c09 = ?, c13 = ?, c14 = ?, c15 = ? WHERE idShow = ?"
+            cursor.execute(pathsql, (title, plot, rating, premieredate, title, genre, mpaa, studio, sorttitle, showid))
+            
+            #update the checksum in emby table
+            cursor.execute("UPDATE emby SET checksum = ? WHERE emby_id = ?", (API().getChecksum(MBitem), MBitem["Id"]))
+            
+        #update or insert people
+        self.AddPeopleToMedia(showid,MBitem.get("People"),"tvshow", connection, cursor)
+        
+        #update genres
+        self.AddGenresToMedia(showid, genres, "tvshow", cursor)
+        
+        #update studios
+        self.AddStudiosToMedia(showid, studios, "tvshow", cursor)
+        
+        #add to favorites tag --> todo translated label for favorites ?
+        if userData.get("Favorite"):
+            self.AddTagToMedia(showid, "Favorite tvshows", "tvshow", cursor)
+        else:
+            self.AddTagToMedia(showid, "Favorite tvshows", "tvshow", cursor, True)
+                
+        #update artwork
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), showid, "tvshow", "thumb", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), showid, "tvshow", "poster", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Banner"), showid, "tvshow", "banner", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Logo"), showid, "tvshow", "clearlogo", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Art"), showid, "tvshow", "clearart", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Thumb"), showid, "tvshow", "landscape", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Disc"), showid, "tvshow", "discart", cursor)
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Backdrop"), showid, "tvshow", "fanart", cursor)
+        
+        #update season details
+        self.updateSeasons(MBitem["Id"], showid, connection, cursor)
+        
+    def addOrUpdateEpisodeToKodiLibrary(self, embyId, showid, connection, cursor):
+        
+        # If the episode 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
+        
+        MBitem = ReadEmbyDB().getFullItem(embyId)
+        cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?",(MBitem["Id"],))
+        result = cursor.fetchone()
+        if result != None:
+            episodeid = result[0]
+        else:
+            episodeid = None
         
         addon = xbmcaddon.Addon(id='plugin.video.emby')
         port = addon.getSetting('port')
@@ -789,9 +489,25 @@ class WriteKodiDB():
         
         timeInfo = API().getTimeInfo(MBitem)
         userData=API().getUserData(MBitem)
+        people = API().getPeople(MBitem)
 
-        playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
-        playurl = utils.convertEncoding(playurl)
+        ###### episode properties ################
+        episode = 0
+        if MBitem.get("IndexNumber") != None:
+            episode = int(MBitem.get("IndexNumber"))
+
+        runtime = int(timeInfo.get('Duration'))*60
+        plot = utils.convertEncoding(API().getOverview(MBitem))
+        title = utils.convertEncoding(MBitem["Name"])
+        rating = MBitem.get("CommunityRating")
+        writer = " / ".join(people.get("Writer"))
+        director = " / ".join(people.get("Director"))
+        
+        if MBitem.get("PremiereDate") != None:
+            premieredatelist = (MBitem.get("PremiereDate")).split("T")
+            premieredate = premieredatelist[0]
+        else:
+            premieredate = None
         
         if MBitem.get("DateCreated") != None:
             dateadded = MBitem["DateCreated"].replace("T"," ")
@@ -803,15 +519,16 @@ class WriteKodiDB():
             lastplayed = userData.get("LastPlayedDate")
         else:
             lastplayed = None
-                    
-        # we need to store both the path and the filename seperately in the kodi db so we split them up
-        if "\\" in playurl:
-            filename = playurl.rsplit("\\",1)[-1]
-            path = playurl.replace(filename,"")
-        elif "/" in playurl:
-            filename = playurl.rsplit("/",1)[-1]
-            path = playurl.replace(filename,"")
-                    
+        
+        playcount = None
+        if userData.get("PlayCount") == "1":
+            playcount = 1
+        
+        #### ADD OR UPDATE THE FILE AND PATH ###########
+        #### NOTE THAT LASTPLAYED AND PLAYCOUNT ARE STORED AT THE FILE ENTRY        
+        path = "plugin://plugin.video.emby/tvshows/" + MBitem["SeriesId"] + "/"
+        filename = "plugin://plugin.video.emby/tvshows/" + MBitem["SeriesId"] + "/?id=" + MBitem["Id"] + "&mode=play"
+        
         #create the new path - return id if already exists  
         cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?",(path,))
         result = cursor.fetchone()
@@ -823,11 +540,7 @@ class WriteKodiDB():
             pathid = pathid + 1
             pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)"
             cursor.execute(pathsql, (pathid,path,None,None,1))
-        
-        playcount = None
-        if userData.get("PlayCount") == "1":
-            playcount = 1
-        
+
         #create the file if not exists
         cursor.execute("SELECT idFile as fileid FROM files WHERE strFilename = ? and idPath = ?",(filename,pathid,))
         result = cursor.fetchone()
@@ -839,426 +552,139 @@ class WriteKodiDB():
             fileid = fileid + 1
             sql="INSERT OR REPLACE into files(idFile, idPath, strFilename, playCount, lastPlayed, dateAdded) values(?, ?, ?, ?, ?, ?)"
             cursor.execute(sql, (fileid,pathid,filename,playcount,lastplayed,dateadded))
-        
-        #get the showid
-        cursor.execute("SELECT idShow as showid FROM tvshow WHERE c12 = ?",(MBitem["SeriesId"],))
-        result = cursor.fetchone()
-        showid = -1
-        if(result == None):
-            utils.logMsg("Emby","Error adding episode to Kodi Library, couldn't find show - ID: " + MBitem["Id"] + " - " + MBitem["Name"])
-            actionPerformed = False
-            return False
         else:
-            showid = result[0]
-
-        # check season
+            pathsql="update files SET playCount = ?, lastPlayed = ? WHERE idFile = ?"
+            cursor.execute(pathsql, (playcount,userData.get("LastPlayedDate"), fileid))
+        
+        # safety check: check season first
         season = 0
         if MBitem.get("ParentIndexNumber") != None:
             season = int(MBitem.get("ParentIndexNumber"))
         else:
-            utils.logMsg("Emby","Error adding episode to Kodi Library, no ParentIndexNumber - ID: " + MBitem["Id"] + " - " + MBitem["Name"])
+            utils.logMsg("Emby","SKIP adding episode to Kodi Library, no ParentIndexNumber - ID: " + MBitem["Id"] + " - " + MBitem["Name"])
             return False
             
         cursor.execute("SELECT idSeason FROM seasons WHERE idShow = ? and season = ?",(showid, season))
         result = cursor.fetchone()        
         if(result == None):
-            utils.logMsg("Emby","Error adding episode to Kodi Library, season does not exist - ShowId: " + str(showid) + " SeasonNo: " + str(season) + " EmbyId: " + MBitem["Id"] + " Name: " + MBitem["Name"])
-            actionPerformed = False
-            return False
+            #update seasons first
+            self.updateSeasons(MBitem["SeriesId"], showid, connection, cursor)
+                
+        # ADD EPISODE TO KODI
+        if episodeid == None:
+            utils.logMsg("ADD episode to Kodi library","Id: %s - Title: %s" % (embyId, title))
+            #create the episode
+            cursor.execute("select coalesce(max(idEpisode),0) as episodeid from episode")
+            episodeid = cursor.fetchone()[0]
+            episodeid = episodeid + 1
+            pathsql = "INSERT into episode(idEpisode, idFile, c00, c01, c03, c04, c05, c09, c10, c12, c13, c14, idShow, c15, c16) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
+            cursor.execute(pathsql, (episodeid, fileid, title, plot, rating, writer, premieredate, runtime, director, season, episode, title, showid, "-1", "-1"))
+            
+            #create the reference in emby table
+            pathsql = "INSERT into emby(emby_id, kodi_id, media_type, checksum, parent_id) values(?, ?, ?, ?, ?)"
+            cursor.execute(pathsql, (MBitem["Id"], episodeid, "episode", API().getChecksum(MBitem), showid))
         
-        # build info
-        episode = 0
-        if MBitem.get("IndexNumber") != None:
-            episode = int(MBitem.get("IndexNumber"))
+        # UPDATE THE EPISODE IN KODI (for now, we just send in all data)
+        else:
+            utils.logMsg("UPDATE episode to Kodi library","Id: %s - Title: %s" % (embyId, title))
+            
+            pathsql = "UPDATE episode SET c00 = ?, c01 = ?, c03 = ?, c04 = ?, c05 = ?, c09 = ?, c10 = ?, c12 = ?, c13 = ?, c14 = ?, c15 = ?, c16 = ? WHERE idEpisode = ?"
+            cursor.execute(pathsql, (title, plot, rating, writer, premieredate, runtime, director, season, episode, title, "-1", "-1", episodeid))
+            
+            #update the checksum in emby table
+            cursor.execute("UPDATE emby SET checksum = ? WHERE emby_id = ?", (API().getChecksum(MBitem), MBitem["Id"]))
+        
+        #update or insert actors
+        self.AddPeopleToMedia(episodeid,MBitem.get("People"),"episode", connection, cursor)
+        
+        #set resume point
+        resume = int(round(float(timeInfo.get("ResumeTime"))))*60
+        total = int(round(float(timeInfo.get("TotalTime"))))*60
+        self.setKodiResumePoint(fileid, resume, total, cursor)
+        
+        #add streamdetails
+        self.AddStreamDetailsToMedia(API().getMediaStreams(MBitem), fileid, cursor)
+        
+        #update artwork
+        self.addOrUpdateArt(API().getArtwork(MBitem, "Primary"), episodeid, "episode", "thumb", cursor)
 
-        runtime = int(timeInfo.get('Duration'))*60
-        plot = utils.convertEncoding(API().getOverview(MBitem))
-        title = utils.convertEncoding(MBitem["Name"])
-        rating = MBitem.get("CommunityRating")
-        if MBitem.get("PremiereDate") != None:
-            premieredatelist = (MBitem.get("PremiereDate")).split("T")
-            premieredate = premieredatelist[0]
-        else:
-            premieredate = None
+    def deleteItemFromKodiLibrary(self, id, connection, cursor ):
         
-        #create the episode
-        cursor.execute("select coalesce(max(idEpisode),0) as episodeid from episode")
-        episodeid = cursor.fetchone()[0]
-        episodeid = episodeid + 1
-        pathsql = "INSERT into episode(idEpisode, idFile, c00, c01, c03, c05, c09, c20, c12, c13, c14, idShow, c15, c16) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
-        cursor.execute(pathsql, (episodeid, fileid, title, plot, rating, premieredate, runtime, MBitem["Id"], season, episode, title, showid, "-1", "-1"))
-        
-        try:
-            connection.commit()
-            utils.logMsg("Emby","Added episode to Kodi Library - ID: " + MBitem["Id"] + " - " + MBitem["Name"])
-        except:
-            utils.logMsg("Emby","Error adding episode to Kodi Library - ID: " + MBitem["Id"] + " - " + MBitem["Name"])
-            actionPerformed = False
-    
-    def deleteMovieFromKodiLibrary(self, id ):
-        kodiItem = ReadKodiDB().getKodiMovie(id)
-        utils.logMsg("deleting movie from Kodi library",id)
-        if kodiItem != None:
-            xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveMovie", "params": { "movieid": %i}, "id": 1 }' %(kodiItem["movieid"]))
- 
-    def deleteMusicVideoFromKodiLibrary(self, id ):
-        utils.logMsg("deleting musicvideo from Kodi library",id)
-        kodiItem = ReadKodiDB().getKodiMusicVideo(id)
-        if kodiItem != None:
-            xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveMusicVideo", "params": { "musicvideoid": %i}, "id": 1 }' %(kodiItem["musicvideoid"]))
-         
-    def deleteEpisodeFromKodiLibrary(self, episodeid, tvshowid ):
-        utils.logMsg("deleting episode from Kodi library",episodeid)
-        episode = ReadKodiDB().getKodiEpisodeByMbItem(episodeid, tvshowid)
-        if episode != None:
-            WINDOW = xbmcgui.Window( 10000 )
-            xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveEpisode", "params": { "episodeid": %i}, "id": 1 }' %(episode["episodeid"]))
-            
-            utils.logMsg("episode deleted succesfully!",episodeid)
-        else:
-            utils.logMsg("episode not found in kodi DB",episodeid)        
-            
-    def deleteEpisodeFromKodiLibraryByMbId(self, id ):
-        utils.logMsg("deleting episode from Kodi library", id)
-        kodiItem = ReadKodiDB().getKodiEpisodeByMbItemEx(id)
-        if kodiItem != None:
-            xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveEpisode", "params": { "episodeid": %i}, "id": 1 }' %(kodiItem["episodeid"]))            
-            utils.logMsg("episode deleted succesfully!", id)
-        else:
-            utils.logMsg("episode not found in kodi DB", id)  
-            
-    def addTVShowToKodiLibrary( self, MBitem, connection, cursor ):
-        #adds a Tvshow to Kodi by directly inserting it to the DB while there is no addTvShow available on the json API
-        #TODO: PR at Kodi team for a addTvShow endpoint on their API
-        
-        addon = xbmcaddon.Addon(id='plugin.video.emby')
-        port = addon.getSetting('port')
-        host = addon.getSetting('ipaddress')
-        server = host + ":" + port
-        
-        timeInfo = API().getTimeInfo(MBitem)
-        userData=API().getUserData(MBitem)
-        
-        thumbPath = API().getArtwork(MBitem, "Primary")
-        
-        playurl = PlayUtils().getPlayUrl(server, MBitem["Id"], MBitem)
-        #make sure that the path always ends with a slash
-        path = utils.convertEncoding(playurl + "/")
-        
-        if MBitem.get("DateCreated") != None:
-            dateadded = MBitem["DateCreated"].replace("T"," ")
-            dateadded = dateadded.replace(".0000000Z","")
-        else:
-            dateadded = None
-         
-        #create the tv show path
-        cursor.execute("select coalesce(max(idPath),0) as pathid from path")
-        pathid = cursor.fetchone()[0]
-        pathid = pathid + 1
-        pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)"
-        cursor.execute(pathsql, (pathid,path,None,None,1))
-        
-        #create toplevel path as monitored source - needed for things like actors and stuff to work (no clue why)
-        if "\\" in path:
-            toplevelpathstr = path.rsplit("\\",2)[1]
-            toplevelpath = path.replace(toplevelpathstr + "\\","")
-        elif "/" in path:
-            toplevelpathstr = path.rsplit("/",2)[1]
-            toplevelpath = path.replace(toplevelpathstr + "/","")
-        cursor.execute("SELECT idPath as tlpathid FROM path WHERE strPath = ?",(toplevelpath,))
+        cursor.execute("SELECT kodi_id, media_type FROM emby WHERE emby_id=?", (id,))
         result = cursor.fetchone()
-        if result == None:
-            cursor.execute("select coalesce(max(idPath),0) as tlpathid from path")
-            tlpathid = cursor.fetchone()[0]
-            tlpathid = pathid + 1
-            pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)"
-            cursor.execute(pathsql, (tlpathid,toplevelpath,"tvshows","metadata.local",1))
-        
-        
-        runtime = int(timeInfo.get('Duration'))*60
-        plot = utils.convertEncoding(API().getOverview(MBitem))
-        title = utils.convertEncoding(MBitem["Name"])
-        sorttitle = utils.convertEncoding(MBitem["SortName"])
-        rating = MBitem.get("CommunityRating")
+        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,))
             
-        #create the tvshow
-        cursor.execute("select coalesce(max(idShow),0) as showid from tvshow")
-        showid = cursor.fetchone()[0]
-        showid = pathid + 1
-        pathsql="insert into tvshow(idShow, c00, c01, c04, c09, c12, c15) values(?, ?, ?, ?, ?, ?, ?)"
-        cursor.execute(pathsql, (showid, title, plot, rating, title, MBitem["Id"], sorttitle))
+            #delete the record in emby table
+            cursor.execute("DELETE FROM emby WHERE emby_id = ?", (id,))
+     
+    def updateSeasons(self,embyTvShowId, kodiTvShowId, connection, cursor):
         
-        #link the path
-        pathsql="insert into tvshowlinkpath(idShow,idPath) values(?, ?)"
-        cursor.execute(pathsql, (showid,pathid))
-
-        try:
-            connection.commit()
-            utils.logMsg("Emby","Added TV Show to Kodi Library: " + MBitem["Id"] + " - " + MBitem["Name"])
-        except:
-            utils.logMsg("Emby","Error adding tvshow to Kodi Library: " + MBitem["Id"] + " - " + MBitem["Name"])
-            actionPerformed = False
-        
-    def deleteTVShowFromKodiLibrary(self, id):
-        xbmc.sleep(sleepVal)
-        kodiItem = ReadKodiDB().getKodiTVShow(id)
-        utils.logMsg("deleting tvshow from Kodi library ", "Emby ID : " + id)
- 
-        if kodiItem != None:
-            utils.logMsg("deleting tvshow from Kodi library ", str(kodiItem))
-            kodiId = kodiItem["tvshowid"]
-            utils.logMsg("deleting tvshow from Kodi library ", "Kodi ID : " + str(kodiId))
-            xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.RemoveTVShow", "params": { "tvshowid": %i}, "id": 1 }' %(kodiId))
-    
-    def updateSeasons(self,MBitem, KodiItem, connection, cursor):
-        #use sqlite to set the season details because no method in API available for this
-        tvshowid = KodiItem["tvshowid"]
-
-        #connection = utils.KodiSQL()
-        #cursor = connection.cursor()
-        
-        seasonData = ReadEmbyDB().getTVShowSeasons(MBitem["Id"])
+        seasonData = ReadEmbyDB().getTVShowSeasons(embyTvShowId)
         if seasonData != None:
             for season in seasonData:
                 seasonNum = season.get("IndexNumber")
                 if seasonNum != None and seasonNum >= 0 and seasonNum <= 1000:
-                    cursor.execute("SELECT idSeason as seasonid FROM seasons WHERE idShow = ? and season = ?",(tvshowid, seasonNum))
+                    cursor.execute("SELECT idSeason as seasonid FROM seasons WHERE idShow = ? and season = ?",(kodiTvShowId, seasonNum))
                     result = cursor.fetchone()
                     if result == None:
                         #create the season
                         cursor.execute("select coalesce(max(idSeason),0) as seasonid from seasons")
                         seasonid = cursor.fetchone()[0]
                         seasonid = seasonid + 1
-                        cursor.execute("INSERT into seasons(idSeason, idShow, season) values(?, ?, ?)", (seasonid, tvshowid, seasonNum))
+                        cursor.execute("INSERT into seasons(idSeason, idShow, season) values(?, ?, ?)", (seasonid, kodiTvShowId, seasonNum))
                     else:
                         seasonid = result[0]
                         
                     #update artwork
                     imageUrl = API().getArtwork(season, "Thumb")
-                    self.updateSeasonArt(imageUrl, seasonid, "landscape", cursor)
+                    self.addOrUpdateArt(imageUrl, seasonid, "season", "landscape", cursor)
                     
                     imageUrl = API().getArtwork(season, "Primary")
-                    self.updateSeasonArt(imageUrl, seasonid, "poster", cursor)
+                    self.addOrUpdateArt(imageUrl, seasonid, "season", "poster", cursor)
                     
                     imageUrl = API().getArtwork(season, "Banner")
-                    self.updateSeasonArt(imageUrl, seasonid, "banner", cursor)                    
-                    
-        connection.commit()
-        
-    def updateSeasonArt(self, imageUrl, seasonid, imageType, cursor):
+                    self.addOrUpdateArt(imageUrl, seasonid, "season", "banner", cursor)                    
+                            
+    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 = ?", (seasonid, "season", imageType))
+        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("SeasonArt", "Adding Art Link for SeasonId: " + str(seasonid) + " (" + imageUrl + ")")
-                cursor.execute("INSERT INTO art(media_id, media_type, type, url) values(?, ?, ?, ?)", (seasonid, "season", imageType, imageUrl))
-                updateDone = True
+                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("SeasonArt", "Updating Art Link for SeasonId: " + str(seasonid) + " (" + url + ") -> (" + imageUrl + ")")
-                    cursor.execute("UPDATE art set url = ? WHERE media_id = ? AND media_type = ? AND type = ?", (imageUrl, seasonid, "season", imageType))
-                    updateDone = True
-                    
-        return updateDone
+                    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 setKodiResumePoint(self, id, resume_seconds, total_seconds, fileType):
-        #use sqlite to set the resume point while json api doesn't support this yet
-        #todo --> submit PR to kodi team to get this added to the jsonrpc api
-        
-        utils.logMsg("Emby","setting resume point in kodi db..." + fileType + ": " + str(id))
-        xbmc.sleep(sleepVal)
-        connection = utils.KodiSQL()
-        cursor = connection.cursor( )
-        
-        if fileType == "episode":
-            cursor.execute("SELECT idFile as fileidid FROM episode WHERE idEpisode = ?",(id,))
-            result = cursor.fetchone()
-            fileid = result[0]
-        if fileType == "movie":
-            cursor.execute("SELECT idFile as fileidid FROM movie WHERE idMovie = ?",(id,))
-            result = cursor.fetchone()
-            fileid = result[0]       
+    def setKodiResumePoint(self, fileid, resume_seconds, total_seconds, cursor):
         
         cursor.execute("delete FROM bookmark WHERE idFile = ?", (fileid,))
-        cursor.execute("select coalesce(max(idBookmark),0) as bookmarkId from bookmark")
-        bookmarkId =  cursor.fetchone()[0]
-        bookmarkId = bookmarkId + 1
-        bookmarksql="insert into bookmark(idBookmark, idFile, timeInSeconds, totalTimeInSeconds, thumbNailImage, player, playerState, type) values(?, ?, ?, ?, ?, ?, ?, ?)"
-        cursor.execute(bookmarksql, (bookmarkId,fileid,resume_seconds,total_seconds,None,"DVDPlayer",None,1))
-        connection.commit()
-        cursor.close()
-        
-    '''
-    # removed for now as setting c15 and c16 to -1 looks like it just shows specials in the special folder only 
-    def setSpecialAirsDetails(self, MBitem, KodiItem, connection, cursor):
-        
-        changes = False
-        
-        cursor.execute("SELECT c15, c16 FROM episode WHERE idEpisode = ?",(KodiItem["episodeid"],))
-        result = cursor.fetchone()
-        if(result != None):
-        
-            c15 = -1
-            c16 = -1
-            
-            if(result[0] != None and result[0] != "" and result[0] != "None"):
-                c15 = int(result[0])
-            if(result[1] != None and result[1] != "" and result[1] != "None"):
-                c16 = int(result[1])
-
-            airsBeforeSeasonNumber = MBitem.get("AirsBeforeSeasonNumber")
-            airsBeforeEpisodeNumber = MBitem.get("AirsBeforeEpisodeNumber")
-            #AirsAfterSeasonNumber
-            
-            if(airsBeforeSeasonNumber == None):
-                airsBeforeSeasonNumber = 0
-                
-            if(airsBeforeEpisodeNumber == None):
-                airsBeforeEpisodeNumber = 0
-            
-            if(airsBeforeSeasonNumber != None and airsBeforeEpisodeNumber != None):
-                if(airsBeforeSeasonNumber != c15 or airsBeforeEpisodeNumber != c16):
-                    utils.logMsg("Emby","Special_Airs_Info Kodi: " + str(c15) + " " + str(c16))
-                    utils.logMsg("Emby","Special_Airs_Info Emby : " + str(airsBeforeSeasonNumber) + " " + str(airsBeforeEpisodeNumber))
-                    sql = "UPDATE episode set c15 = ?, c16 = ? WHERE idEpisode = ?"
-                    cursor.execute(sql, (airsBeforeSeasonNumber, airsBeforeEpisodeNumber, KodiItem["episodeid"]))
-                    connection.commit()
-                    changes = True
-                
-        return changes
-    '''
-    
-    def setKodiFilename(self, id, oldFileName, newFileName, fileType, mbId, connection, cursor):
-        #use sqlite to set the filename in DB -- needed to avoid problems with resumepoints etc
-        #return True if any action is performed, False if no action is performed
-        #todo --> submit PR to kodi team to get this added to the jsonrpc api
-        #todo --> extend support for musicvideos
-        
-        actionPerformed = False
-        
-        oldFileName = utils.convertEncoding(oldFileName)
-        newFileName = utils.convertEncoding(newFileName)
-        
-        # this is required to make sure the paths match
-        oldFileName = oldFileName.replace("\\", "/")
-        
-        # only perform changes if the path actually differs
-        if oldFileName != newFileName:
-        
-            # xbmc.sleep(sleepVal)
-            #connection = utils.KodiSQL()
-            #cursor = connection.cursor()
-            utils.logMsg("Emby","setting filename in kodi db..." + fileType + ": " + str(id))
-            utils.logMsg("Emby","old filename -->" + oldFileName)
-            utils.logMsg("Emby","new filename -->" + newFileName)
-            
-            ######### PROCESS TV SHOW ############
-            if fileType == "tvshow":
-                
-                if newFileName.startswith("http"):
-                    newFileName = "plugin://plugin.video.emby/"
-                
-                #for tvshows we only store the path in DB
-                cursor.execute("SELECT idPath as pathid FROM tvshowlinkpath WHERE idShow = ?",(id,))
-                result = cursor.fetchone()
-                pathid = result[0]
-                cursor.execute("UPDATE path SET strPath = ?, noUpdate = ?, idParentPath = ? WHERE idPath = ?", (newFileName,1,None,pathid))
-            
-            else:
-                # we need to store both the path and the filename seperately in the kodi db so we split them up
-                
-                if newFileName.startswith("http"):
-                    #transcoding or play from stream
-                    path = "plugin://plugin.video.emby/"
-                    filename = "plugin://plugin.video.emby/?id=" + mbId + "&mode=play"
-                    
-                else:
-                    # direct play
-                    if "\\" in newFileName:
-                        filename = newFileName.rsplit("\\",1)[-1]
-                        path = newFileName.replace(filename,"")
-                    elif "/" in newFileName:
-                        filename = newFileName.rsplit("/",1)[-1]
-                        path = newFileName.replace(filename,"")
-                
-                
-                ######### PROCESS EPISODE ############
-                if fileType == "episode":
-                    
-                    #get the file and the current path id
-                    cursor.execute("SELECT idFile as fileid FROM episode WHERE idEpisode = ?",(id,))
-                    result = cursor.fetchone()
-                    fileid = result[0]
-                    
-                    #create the new path - return id if already exists  
-                    cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?",(path,))
-                    result = cursor.fetchone()
-                    if result != None:
-                        pathid = result[0]
-                    if result == None:
-                        cursor.execute("select coalesce(max(idPath),0) as pathid from path")
-                        pathid = cursor.fetchone()[0]
-                        pathid = pathid + 1
-                        pathsql="insert into path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)"
-                        cursor.execute(pathsql, (pathid,path,None,None,1))
-                    
-                    #set the new path and filename to the episode
-                    cursor.execute("UPDATE files SET idPath = ?, strFilename = ? WHERE idFile = ?", (pathid,filename,fileid))
-
-                    
-                ######### PROCESS MOVIE ############
-                if fileType == "movie":
-                    cursor.execute("SELECT idFile as fileid FROM movie WHERE idMovie = ?",(id,))
-                    result = cursor.fetchone()
-                    fileid = result[0]
-                    #write the new filename to the DB
-                    cursor.execute("UPDATE files SET strFilename = ? WHERE idFile = ?", (filename,fileid))
-                    #set the new path
-                    cursor.execute("SELECT idPath as pathid FROM files WHERE idFile = ?",(fileid,))
-                    result = cursor.fetchone()
-                    pathid = result[0]
-                    cursor.execute("UPDATE path SET strPath = ?, strContent = ?, strScraper = ?, noUpdate = ?, idParentPath = ? WHERE idPath = ?", (path, "movies", "metadata.local", 1, None, pathid))               
-                
-            try:
-                connection.commit()
-                actionPerformed = True
-            except:
-                utils.logMsg("Emby","Error setting filename in kodi db for: " + fileType + ": " + str(id))
-                actionPerformed = False
-            
-        return actionPerformed
-    
-    def AddActorsToMedia(self, KodiItem, people, mediatype, connection, cursor):
-        #use sqlite to set add the actors while json api doesn't support this yet
-        #todo --> submit PR to kodi team to get this added to the jsonrpc api
-        
+        if resume_seconds != 0:
+            cursor.execute("select coalesce(max(idBookmark),0) as bookmarkId from bookmark")
+            bookmarkId =  cursor.fetchone()[0]
+            bookmarkId = bookmarkId + 1
+            bookmarksql="insert into bookmark(idBookmark, idFile, timeInSeconds, totalTimeInSeconds, thumbNailImage, player, playerState, type) values(?, ?, ?, ?, ?, ?, ?, ?)"
+            cursor.execute(bookmarksql, (bookmarkId,fileid,resume_seconds,total_seconds,None,"DVDPlayer",None,1))
+     
+    def AddPeopleToMedia(self, id, people, mediatype, connection, cursor):
         downloadUtils = DownloadUtils()
-        if mediatype == "movie":
-            id = KodiItem["movieid"]
-        if mediatype == "tvshow":
-            id = KodiItem["tvshowid"]
-        if mediatype == "episode":
-            id = KodiItem["episodeid"]
-
-        currentcast = list()
-        if KodiItem["cast"] != None:
-            for cast in KodiItem["cast"]:
-                currentcast.append(cast["name"])
-        
-        needsUpdate = False
-        if(people != None):
-            for person in people:              
-                if(person.get("Type") == "Actor"):
-                    if person.get("Name") not in currentcast:
-                        needsUpdate = True
-                        break
-        
-        if(needsUpdate == False):
-            return False
-        
-        utils.logMsg("AddActorsToMedia", "List needs updating")
         
         kodiVersion = 14
         if xbmc.getInfoLabel("System.BuildVersion").startswith("15"):
@@ -1266,62 +692,270 @@ class WriteKodiDB():
         
         if(people != None):
             for person in people:              
+                
+                Name = person.get("Name")
+                
+                actorid = None
+                Thumb = downloadUtils.imageUrl(person.get("Id"), "Primary", 0, 400, 400)
+                if kodiVersion == 15:
+                    # Kodi Isengard database #
+                    if Thumb != None:
+                        Thumb = "<thumb>" + Thumb + "</thumb>"
+                    cursor.execute("SELECT actor_id as actorid FROM actor WHERE name = ?",(Name,))
+                else:
+                    # Kodi Gotham or Helix database #
+                    cursor.execute("SELECT idActor as actorid FROM actors WHERE strActor = ?",(Name,))
+                result = cursor.fetchone()
+                if result != None:
+                    actorid = result[0]
+                if actorid == None:
+                    if kodiVersion == 15:
+                        # Kodi Isengard database #
+                        cursor.execute("select coalesce(max(actor_id),0) as actorid from actor")
+                        actorid = cursor.fetchone()[0]
+                        actorid = actorid + 1
+                        peoplesql="insert into actor(actor_id, name, art_urls) values(?, ?, ?)"
+                    else:
+                        # Kodi Gotham or Helix database #
+                        cursor.execute("select coalesce(max(idActor),0) as actorid from actors")
+                        actorid = cursor.fetchone()[0]
+                        actorid = actorid + 1
+                        peoplesql="insert into actors(idActor, strActor, strThumb) values(?, ?, ?)"
+                    utils.logMsg("AddPeopleToMedia", "Processing : " + person.get("Name"))
+                    cursor.execute(peoplesql, (actorid,Name,Thumb))
+                
+                #### ACTORS ######
                 if(person.get("Type") == "Actor"):
-                    if person.get("Name") not in currentcast:
-                        utils.logMsg("AddActorsToMedia", "Processing : " + person.get("Name"))
-                        Name = person.get("Name")
-                        Role = person.get("Role")
-                        actorid = None
-                        Thumb = downloadUtils.imageUrl(person.get("Id"), "Primary", 0, 400, 400)
-                        if kodiVersion == 15:
-                            # Kodi Isengard database #
-                            if Thumb != None:
-                                Thumb = "<thumb>" + Thumb + "</thumb>"
-                            cursor.execute("SELECT actor_id as actorid FROM actor WHERE name = ?",(Name,))
-                        else:
-                            # Kodi Gotham or Helix database #
-                            cursor.execute("SELECT idActor as actorid FROM actors WHERE strActor = ?",(Name,))
-                        result = cursor.fetchone()
-                        if result != None:
-                            actorid = result[0]
-                        if actorid == None:
-                            if kodiVersion == 15:
-                                # Kodi Isengard database #
-                                cursor.execute("select coalesce(max(actor_id),0) as actorid from actor")
-                                actorid = cursor.fetchone()[0]
-                                actorid = actorid + 1
-                                peoplesql="insert into actor(actor_id, name, art_urls) values(?, ?, ?)"
-                            else:
-                                # Kodi Gotham or Helix database #
-                                cursor.execute("select coalesce(max(idActor),0) as actorid from actors")
-                                actorid = cursor.fetchone()[0]
-                                actorid = actorid + 1
-                                peoplesql="insert into actors(idActor, strActor, strThumb) values(?, ?, ?)"
-                            cursor.execute(peoplesql, (actorid,Name,Thumb))
-                        
-                        if kodiVersion == 15:
-                            # Kodi Isengard database #
-                            peoplesql="INSERT OR REPLACE into actor_link(actor_id, media_id, media_type, role, cast_order) values(?, ?, ?, ?, ?)"
-                            cursor.execute(peoplesql, (actorid, id, mediatype, Role, None))
-                        else:
-                            # Kodi Gotham or Helix database #
-                            if mediatype == "movie":
-                                peoplesql="INSERT OR REPLACE into actorlinkmovie(idActor, idMovie, strRole, iOrder) values(?, ?, ?, ?)"
-                            if mediatype == "tvshow":
-                                peoplesql="INSERT OR REPLACE into actorlinktvshow(idActor, idShow, strRole, iOrder) values(?, ?, ?, ?)"
-                            if mediatype == "episode":
-                                peoplesql="INSERT OR REPLACE into actorlinkepisode(idActor, idEpisode, strRole, iOrder) values(?, ?, ?, ?)"
+                    
+                    Role = person.get("Role")
+                    if kodiVersion == 15:
+                        # Kodi Isengard database #
+                        peoplesql="INSERT OR REPLACE into actor_link(actor_id, media_id, media_type) values(?, ?, ?)"
+                        cursor.execute(peoplesql, (actorid, id, mediatype))
+                    else:
+                        # Kodi Gotham or Helix database #
+                        if mediatype == "movie":
+                            peoplesql="INSERT OR REPLACE into actorlinkmovie(idActor, idMovie, strRole, iOrder) values(?, ?, ?, ?)"
                             cursor.execute(peoplesql, (actorid,id,Role,None))
-        
-        connection.commit()
-        #cursor.close()
-        
-        return True
+                        if mediatype == "tvshow":
+                            peoplesql="INSERT OR REPLACE into actorlinktvshow(idActor, idShow, strRole, iOrder) values(?, ?, ?, ?)"
+                            cursor.execute(peoplesql, (actorid,id,Role,None))
+                        if mediatype == "episode":
+                            peoplesql="INSERT OR REPLACE into actorlinkepisode(idActor, idEpisode, strRole, iOrder) values(?, ?, ?, ?)"
+                            cursor.execute(peoplesql, (actorid,id,Role,None))         
+                        
+                #### DIRECTORS ######
+                if(person.get("Type") == "Director"):
+                    
+                    if kodiVersion == 15:
+                        # Kodi Isengard database #
+                        peoplesql="INSERT OR REPLACE into director_link(actor_id, media_id, media_type) values(?, ?, ?)"
+                        cursor.execute(peoplesql, (actorid, id, mediatype))
+                    else:
+                        # Kodi Gotham or Helix database #
+                        if mediatype == "movie":
+                            peoplesql="INSERT OR REPLACE into directorlinkmovie(idDirector, idMovie) values(?, ?)"
+                        if mediatype == "tvshow":
+                            peoplesql="INSERT OR REPLACE into directorlinktvshow(idDirector, idShow) values(?, ?)"
+                        if mediatype == "musicvideo":
+                            peoplesql="INSERT OR REPLACE into directorlinkmusicvideo(idDirector, idMVideo) values(?, ?)"
+                        if mediatype == "episode":
+                            peoplesql="INSERT OR REPLACE into directorlinkepisode(idDirector, idEpisode) values(?, ?)"
+                        cursor.execute(peoplesql, (actorid,id))
+                        
+                #### WRITERS ######
+                if(person.get("Type") == "Writing" or person.get("Type") == "Writer"):
+                    
+                    if kodiVersion == 15:
+                        # Kodi Isengard database #
+                        peoplesql="INSERT OR REPLACE into writer_link(actor_id, media_id, media_type) values(?, ?, ?)"
+                        cursor.execute(peoplesql, (actorid, id, mediatype))
+                    else:
+                        # Kodi Gotham or Helix database #
+                        if mediatype == "movie":
+                            peoplesql="INSERT OR REPLACE into writerlinkmovie(idWriter, idMovie) values(?, ?)"
+                            cursor.execute(peoplesql, (actorid,id))
+                        if mediatype == "episode":
+                            peoplesql="INSERT OR REPLACE into writerlinkepisode(idWriter, idEpisode) values(?, ?)"
+                            cursor.execute(peoplesql, (actorid,id))
+                        
+    def AddGenresToMedia(self, id, genres, mediatype, cursor):
+
+        if genres:
+            
+            kodiVersion = 14
+            if xbmc.getInfoLabel("System.BuildVersion").startswith("15"):
+                kodiVersion = 15
+            
+            for genre in genres:
+
+                if kodiVersion == 15:
+                    genre_id = None
+                    cursor.execute("SELECT genre_id as genre_id FROM genre WHERE name = ?",(genre,))
+                    result = cursor.fetchone()
+                    if result != None:
+                        genre_id = result[0]
+                    #create genre
+                    if genre_id == None:
+                        cursor.execute("select coalesce(max(genre_id),0) as genre_id from genre")
+                        genre_id = cursor.fetchone()[0]
+                        genre_id = genre_id + 1
+                        sql="insert into genre(genre_id, name) values(?, ?)"
+                        cursor.execute(sql, (genre_id,genre))
+                        utils.logMsg("AddGenresToMedia", "Processing : " + genre)
+                    
+                    #assign genre to item    
+                    sql="INSERT OR REPLACE into genre_link(genre_id, media_id, media_type) values(?, ?, ?)"
+                    cursor.execute(sql, (genre_id, id, mediatype))
+                
+                else:
+                    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 == "movie":
+                        sql="INSERT OR REPLACE into genrelinkmovie(idGenre, idMovie) values(?, ?)"
+                    if mediatype == "tvshow":
+                        sql="INSERT OR REPLACE into genrelinktvshow(idGenre, idShow) values(?, ?)"
+                    if mediatype == "episode":
+                        return
+                    if mediatype == "musicvideo":
+                        sql="INSERT OR REPLACE into genrelinkmusicvideo(idGenre, idMVideo) values(?, ?)"
+                    cursor.execute(sql, (idGenre,id))
     
+    def AddStudiosToMedia(self, id, studios, mediatype, cursor):
+
+        if studios:
+            
+            kodiVersion = 14
+            if xbmc.getInfoLabel("System.BuildVersion").startswith("15"):
+                kodiVersion = 15
+            
+            for studio in studios:
+
+                if kodiVersion == 15:
+                    studio_id = None
+                    cursor.execute("SELECT studio_id as studio_id FROM studio WHERE name = ?",(studio,))
+                    result = cursor.fetchone()
+                    if result != None:
+                        studio_id = result[0]
+                    #create studio
+                    if studio_id == None:
+                        cursor.execute("select coalesce(max(studio_id),0) as studio_id from studio")
+                        studio_id = cursor.fetchone()[0]
+                        studio_id = studio_id + 1
+                        sql="insert into studio(studio_id, name) values(?, ?)"
+                        cursor.execute(sql, (studio_id,studio))
+                        utils.logMsg("AddstudiosToMedia", "Processing : " + studio)
+                    
+                    #assign studio to item    
+                    sql="INSERT OR REPLACE into studio_link(studio_id, media_id, media_type) values(?, ?, ?)"
+                    cursor.execute(sql, (studio_id, id, mediatype))
+                
+                else:
+                    idstudio = None
+                    cursor.execute("SELECT idstudio as idstudio FROM studio WHERE strstudio = ?",(studio,))
+                    result = cursor.fetchone()
+                    if result != None:
+                        idstudio = result[0]
+                    #create studio
+                    if idstudio == None:
+                        cursor.execute("select coalesce(max(idstudio),0) as idstudio from studio")
+                        idstudio = cursor.fetchone()[0]
+                        idstudio = idstudio + 1
+                        sql="insert into studio(idstudio, strstudio) values(?, ?)"
+                        cursor.execute(sql, (idstudio,studio))
+
+                    #assign studio to item    
+                    if mediatype == "movie":
+                        sql="INSERT OR REPLACE into studiolinkmovie(idstudio, idMovie) values(?, ?)"
+                    if mediatype == "musicvideo":
+                        sql="INSERT OR REPLACE into studiolinkmusicvideo(idstudio, idMVideo) values(?, ?)"
+                    if mediatype == "tvshow":
+                        sql="INSERT OR REPLACE into studiolinktvshow(idstudio, idShow) values(?, ?)"
+                    if mediatype == "episode":
+                        sql="INSERT OR REPLACE into studiolinkepisode(idstudio, idEpisode) values(?, ?)"
+                    cursor.execute(sql, (idstudio,id))
+        
+    def AddTagToMedia(self, id, tag, mediatype, cursor, doRemove=False):
+
+        if tag:
+            
+            kodiVersion = 14
+            if xbmc.getInfoLabel("System.BuildVersion").startswith("15"):
+                kodiVersion = 15
+            
+            if kodiVersion == 15:
+                tag_id = None
+                cursor.execute("SELECT tag_id as tag_id FROM tag WHERE name = ?",(tag,))
+                result = cursor.fetchone()
+                if result != None:
+                    tag_id = result[0]
+                #create tag
+                if tag_id == None:
+                    cursor.execute("select coalesce(max(tag_id),0) as tag_id from tag")
+                    tag_id = cursor.fetchone()[0]
+                    tag_id = tag_id + 1
+                    sql="insert into tag(tag_id, name) values(?, ?)"
+                    cursor.execute(sql, (tag_id,tag))
+                    utils.logMsg("AddTagToMedia", "Adding tag: " + tag)
+                    self.addVideoNodesForTag(tag, mediatype)
+                
+                #assign tag to item
+                if doRemove:
+                    sql="DELETE FROM tag_link WHERE media_id = ? AND media_type = ? AND tag_id = ?"
+                    cursor.execute(sql, (id, mediatype, tag_id))
+                else:
+                    sql="INSERT OR REPLACE into tag_link(tag_id, media_id, media_type) values(?, ?, ?)"
+                    cursor.execute(sql, (tag_id, id, mediatype))
+            
+            else:
+                idTag = None
+                cursor.execute("SELECT idTag as idTag FROM tag WHERE strTag = ?",(tag,))
+                result = cursor.fetchone()
+                if result != None:
+                    idTag = result[0]
+                #create idTag
+                if idTag == None:
+                    cursor.execute("select coalesce(max(idTag),0) as idTag from tag")
+                    idTag = cursor.fetchone()[0]
+                    idTag = idTag + 1
+                    sql="insert into tag(idTag, strTag) values(?, ?)"
+                    cursor.execute(sql, (idTag,tag))
+                    utils.logMsg("AddTagToMedia", "Adding tag: " + tag)
+                    self.addVideoNodesForTag(tag, mediatype)
+
+                #assign tag to item
+                if doRemove:
+                    sql="DELETE FROM taglinks WHERE idMedia = ? AND media_type = ? AND idTag = ?"
+                    cursor.execute(sql, (id, mediatype, idTag))
+                else:                
+                    sql="INSERT OR REPLACE into taglinks(idTag, idMedia, media_type) values(?, ?, ?)"
+                    cursor.execute(sql, (idTag, id, mediatype))
+    
+    def AddStreamDetailsToMedia(self, streamdetails, fileid, cursor):
+        
+        #first remove any existing entries
+        cursor.execute("delete FROM streamdetails WHERE idFile = ?", (fileid,))
+        if streamdetails:
+            #video details
+            sql="insert into streamdetails(idFile, iStreamType, strVideoCodec, fVideoAspect, iVideoWidth, iVideoHeight, strStereoMode) values(?, ?, ?, ?, ?, ?, ?)"
+            cursor.execute(sql, (fileid,0,streamdetails.get("videocodec"),streamdetails.get("aspectratio"),streamdetails.get("width"),streamdetails.get("height"),streamdetails.get("3dformat")))
+            #audio details
+            sql="insert into streamdetails(idFile, iStreamType, strAudioCodec, iAudioChannels) values(?, ?, ?, ?)"
+            cursor.execute(sql, (fileid,1,streamdetails.get("audiocodec"),streamdetails.get("channels")))
+  
     def addBoxsetToKodiLibrary(self, boxset, connection, cursor):
-        #use sqlite to set add the set 
-        #connection = utils.KodiSQL()
-        #cursor = connection.cursor() 
         
         strSet = boxset["Name"]
         # check if exists
@@ -1361,17 +995,192 @@ class WriteKodiDB():
             setssql="INSERT INTO sets (idSet, strSet)  values(?, ?)"
             cursor.execute(setssql, (None,strSet))
             #if OK:
+            cursor.execute("SELECT idSet FROM sets WHERE strSet = ?", (strSet,))
+        
             result = cursor.fetchone()
             if result != None:
                 setid = result[0]
-        connection.commit()
-        #cursor.close()
+                
+                currentsetartsql =  "SELECT type, url FROM art where media_type = ? and media_id = ? and url != ''"
+                cursor.execute(currentsetartsql, ("set", setid))
+                existing_type_map = {}
+                rows = cursor.fetchall()
+                for row in rows:
+                    existing_type_map[row[0] ] = row[1]
+              
+                artwork = {}
+                artwork["poster"] = API().getArtwork(boxset, "Primary")
+                artwork["banner"] = API().getArtwork(boxset, "Banner")
+                artwork["clearlogo"] = API().getArtwork(boxset, "Logo")
+                artwork["clearart"] = API().getArtwork(boxset, "Art")
+                artwork["landscape"] = API().getArtwork(boxset, "Thumb")
+                artwork["discart"] = API().getArtwork(boxset, "Disc")
+                artwork["fanart"] = API().getArtwork(boxset, "Backdrop")
+               
+                art_types = ['poster','fanart','landscape','clearlogo','clearart','banner','discart']
+                for update_type in art_types:
+                    if ( update_type in existing_type_map ):
+                        if ( existing_type_map[update_type] != artwork[update_type] ) and artwork[update_type] != '':
+                            setupdateartsql = "UPDATE art SET url = ? where media_type = ? and media_id = ? and type = ?"
+                            cursor.execute(setupdateartsql,(artwork[update_type],"set",setid,update_type))
+                    elif artwork[update_type] != '':
+                        setartsql = "INSERT INTO art(media_id, media_type, type, url) VALUES(?,?,?,?)"
+                        cursor.execute(setartsql,(setid,"set",update_type,artwork[update_type]))
         
         return True
     
-    def updateBoxsetToKodiLibrary(self, boxsetmovie, boxset):
+    def addVideoNodesForTag(self, tagname, type):
+        
+        utils.logMsg("addVideoNodesForTag", "Creating nodes for tag: " + tagname)
+        
+        # the library path doesn't exist on all systems
+        if not xbmcvfs.exists("special://userdata/library/"):
+            xbmcvfs.mkdir("special://userdata/library") 
+        if not xbmcvfs.exists("special://userdata/library/video/"):
+            #we need to copy over the default items
+            import shutil
+            shutil.copytree(xbmc.translatePath("special://xbmc/system/library/video"), xbmc.translatePath("special://userdata/library/video"))
+        
+        libraryPath = xbmc.translatePath("special://userdata/library/video/emby/")
+        
+        if type == "movie":
+            type = "movies"
+        elif type == "tvshow":
+            type = "tvshows"
+        else:
+            return
+               
+        #tagpath
+        libraryPath = xbmc.translatePath("special://userdata/library/video/Emby - %s/" %tagname)
+        
+        if not xbmcvfs.exists(libraryPath):
+            #create tag node - index
+            xbmcvfs.mkdir(libraryPath)
+            nodefile = os.path.join(libraryPath, "index.xml")
+            root = Element("node", {"order":"1"})
+            SubElement(root, "label").text = "Emby - " + tagname
+            SubElement(root, "icon").text = "DefaultMovies.png"
+            try:
+                ET.ElementTree(root).write(nodefile, xml_declaration=True)
+            except:
+                ET.ElementTree(root).write(nodefile)
+            
+            #create tag node - all items
+            nodefile = os.path.join(libraryPath, tagname + "_all.xml")
+            root = Element("node", {"order":"1", "type":"filter"})
+            SubElement(root, "label").text = tagname
+            SubElement(root, "match").text = "all"
+            SubElement(root, "content").text = type
+            SubElement(root, "icon").text = "DefaultMovies.png"
+            SubElement(root, "order", {"direction":"ascending"}).text = "sorttitle"
+            Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
+            SubElement(Rule, "value").text = tagname
+            try:
+                ET.ElementTree(root).write(nodefile, xml_declaration=True)
+            except:
+                ET.ElementTree(root).write(nodefile)
+            
+            #create tag node - recent items
+            nodefile = os.path.join(libraryPath, tagname + "_recent.xml")
+            root = Element("node", {"order":"2", "type":"filter"})
+            SubElement(root, "label").text = tagname + " - Recently added"
+            SubElement(root, "match").text = "all"
+            SubElement(root, "content").text = type
+            SubElement(root, "icon").text = "DefaultMovies.png"
+            Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
+            SubElement(Rule, "value").text = tagname
+            SubElement(root, "order", {"direction":"descending"}).text = "dateadded"
+            #set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
+            SubElement(root, "limit").text = "25"
+            #exclude watched items --> currently hardcoded --> TODO: add a setting for this ?
+            Rule2 = SubElement(root, "rule", {"field":"playcount","operator":"is"})
+            SubElement(Rule2, "value").text = "0"
+            
+            try:
+                ET.ElementTree(root).write(nodefile, xml_declaration=True)
+            except:
+                ET.ElementTree(root).write(nodefile)
+            
+            #create tag node - inprogress items
+            nodefile = os.path.join(libraryPath, tagname + "_progress.xml")
+            root = Element("node", {"order":"3", "type":"filter"})
+            SubElement(root, "label").text = tagname + " - In progress"
+            SubElement(root, "match").text = "all"
+            SubElement(root, "content").text = type
+            SubElement(root, "icon").text = "DefaultMovies.png"
+            Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
+            SubElement(Rule, "value").text = tagname
+            #set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
+            SubElement(root, "limit").text = "25"
+            Rule2 = SubElement(root, "rule", {"field":"inprogress","operator":"true"})
+            
+            try:
+                ET.ElementTree(root).write(nodefile, xml_declaration=True)
+            except:
+                ET.ElementTree(root).write(nodefile)
+                
+            #add some additional nodes for episodes
+            if type == "tvshows":
+                #create tag node - recent episodes
+                nodefile = os.path.join(libraryPath, tagname + "_recent_episodes.xml")
+                root = Element("node", {"order":"3", "type":"filter"})
+                SubElement(root, "label").text = tagname + " - Recently added episodes"
+                SubElement(root, "match").text = "all"
+                SubElement(root, "content").text = "episodes"
+                SubElement(root, "icon").text = "DefaultMovies.png"
+                Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
+                SubElement(Rule, "value").text = tagname
+                SubElement(root, "order", {"direction":"descending"}).text = "dateadded"
+                #set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
+                SubElement(root, "limit").text = "25"
+                #exclude watched items --> currently hardcoded --> TODO: add a setting for this ?
+                Rule2 = SubElement(root, "rule", {"field":"playcount","operator":"is"})
+                SubElement(Rule2, "value").text = "0"
+                
+                try:
+                    ET.ElementTree(root).write(nodefile, xml_declaration=True)
+                except:
+                    ET.ElementTree(root).write(nodefile)
+                
+                #create tag node - inprogress items
+                nodefile = os.path.join(libraryPath, tagname + "_progress_episodes.xml")
+                root = Element("node", {"order":"4", "type":"filter"})
+                SubElement(root, "label").text = tagname + " - In progress episodes"
+                SubElement(root, "match").text = "all"
+                SubElement(root, "content").text = "episodes"
+                SubElement(root, "icon").text = "DefaultMovies.png"
+                Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
+                SubElement(Rule, "value").text = tagname
+                #set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
+                SubElement(root, "limit").text = "25"
+                Rule2 = SubElement(root, "rule", {"field":"inprogress","operator":"true"})
+                
+                try:
+                    ET.ElementTree(root).write(nodefile, xml_declaration=True)
+                except:
+                    ET.ElementTree(root).write(nodefile)
+                
+    def updateBoxsetToKodiLibrary(self, boxsetmovie, boxset, connection, cursor):
         strSet = boxset["Name"]
-        kodiMovie = ReadKodiDB().getKodiMovie(boxsetmovie["Id"])
-        if kodiMovie != None:
-            WriteKodiDB().updateProperty(kodiMovie,"set",strSet,"movie",True)
-            
\ No newline at end of file
+        cursor.execute("SELECT kodi_id FROM emby WHERE emby_id = ?",(boxsetmovie["Id"],))
+        result = cursor.fetchone()
+        if result != None:
+            movieid = result[0]
+        else:
+            movieid = None
+        if movieid != None:
+            # check if exists
+            cursor.execute("SELECT idSet FROM sets WHERE strSet = ?", (strSet,))
+            result = cursor.fetchone()
+            setid = None
+            if result != None:
+                setid = result[0]
+           
+                pathsql="update movie SET idSet = ? WHERE idMovie = ?"
+                cursor.execute(pathsql, (setid, movieid))
+                
+                #update the checksum in emby table
+                cursor.execute("UPDATE emby SET checksum = ? WHERE emby_id = ?", (API().getChecksum(boxsetmovie),boxsetmovie["Id"]))
+             
+                
+               
diff --git a/resources/settings.xml b/resources/settings.xml
index ff9d43aa..b1305123 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -12,12 +12,9 @@
 		<setting id="deviceName" type="text" label="30016" default="Kodi" />
 		<setting id="playFromStream" type="bool" label="30002" visible="true" enable="true" default="false" />
 	</category>
-	<!-- <category label="Manual sync"> <setting label="Run manual full sync now" type="action" action="RunScript(plugin.video.mbsync, fullsync)" /> <setting label="Run manual incremental sync now" type="action" action="RunScript(plugin.video.mbsync, incrementalsync)" /> <setting label="Reset entire local library" type="action" action="RunScript(plugin.video.mbsync, reset)" /> </category> -->
 	<category label="Sync Options">
 	<!--  	<setting id="syncMovieBoxSets" type="bool" label="30238" default="true" visible="true" enable="true" /> -->
-		<setting id="enablePlayCountSync" type="bool" label="30240" default="true" visible="true" enable="true" />
-		<setting id="dbSyncIndication" type="labelenum" label="30241" values="None|Notify OnChange|Notify OnFinish|BG Progress|Dialog Progress" default="None" />
-		<setting id="playCountSyncIndication" type="labelenum" label="30242" values="None|Notify OnChange|Notify OnFinish|BG Progress|Dialog Progress" default="None" />
+		<setting id="dbSyncIndication" type="bool" label="30241" default="false" visible="true" enable="true" />
 	</category>
 	<category label="Playback"> <!-- Extra Sync options -->
 		<setting id="smbusername" type="text" label="30007" default="" visible="true" enable="true" />
@@ -27,6 +24,9 @@
 	    <setting id="videoBitRate" type="enum" label="30160" values="664 Kbps SD|996 Kbps HD|1.3 Mbps HD|2.0 Mbps HD|3.2 Mbps HD|4.7 Mbps HD|6.2 Mbps HD|7.7 Mbps HD|9.2 Mbps HD|10.7 Mbps HD|12.2 Mbps HD|13.7 Mbps HD|15.2 Mbps HD|16.7 Mbps HD|18.2 Mbps HD|20.0 Mbps HD|40.0 Mbps HD|100.0 Mbps HD [default]|1000.0 Mbps HD" default="17" />
 		<setting id="forceTranscodingCodecs" type="text" label="30245" />
 	</category>
+	<category label="Artwork">
+	    <setting id="disableCoverArt" type="bool" label="30157" default="false" visible="true" enable="true" />
+	</category>
 	<category label="30022">
 		<setting id="logLevel" type="enum" label="30004" values="None|Info|Debug" default="1" />
 		<setting label="30239" type="action" action="RunScript(plugin.video.emby, reset)" />
diff --git a/service.py b/service.py
index 55c8b664..80395ad4 100644
--- a/service.py
+++ b/service.py
@@ -19,6 +19,7 @@ from ConnectionManager import ConnectionManager
 from ClientInformation import ClientInformation
 from WebSocketClient import WebSocketThread
 from UserClient import UserClient
+from PlaybackUtils import PlaybackUtils
 librarySync = LibrarySync()
 
 
@@ -30,7 +31,10 @@ class Service():
 
     clientInfo = ClientInformation()
     addonName = clientInfo.getAddonName()
-    className = None
+    WINDOW = xbmcgui.Window(10000)
+
+    warn_auth = True
+    server_online = True
     
     def __init__(self, *args ):
         self.KodiMonitor = KodiMonitor.Kodi_Monitor()
@@ -40,24 +44,21 @@ class Service():
         self.logMsg("======== START %s ========" % addonName, 0)
         self.logMsg("KODI Version: %s" % xbmc.getInfoLabel("System.BuildVersion"), 0)
         self.logMsg("%s Version: %s" % (addonName, self.clientInfo.getVersion()), 0)
+        self.logMsg("Platform: %s" % (self.clientInfo.getPlatform()), 0)
 
     def logMsg(self, msg, lvl=1):
         
-        self.className = self.__class__.__name__
-        utils.logMsg("%s %s" % (self.addonName, self.className), str(msg), int(lvl))
+        className = self.__class__.__name__
+        utils.logMsg("%s %s" % (self.addonName, className), str(msg), int(lvl))
             
     def ServiceEntryPoint(self):
         
+        WINDOW = self.WINDOW
+        WINDOW.setProperty("Server_online", "")
+
         ConnectionManager().checkServer()
-        
         lastProgressUpdate = datetime.today()
-        
         startupComplete = False
-        #interval_FullSync = 600
-        #interval_IncrementalSync = 300
-        
-        #cur_seconds_fullsync = interval_FullSync
-        #cur_seconds_incrsync = interval_IncrementalSync
         
         user = UserClient()
         player = Player()
@@ -70,71 +71,101 @@ class Service():
             if self.KodiMonitor.waitForAbort(1):
                 # Abort was requested while waiting. We should exit
                 break
-            
-            if xbmc.Player().isPlaying():
-                try:
-                    playTime = xbmc.Player().getTime()
-                    totalTime = xbmc.Player().getTotalTime()
-                    currentFile = xbmc.Player().getPlayingFile()
 
-                    if(player.played_information.get(currentFile) != None):
-                        player.played_information[currentFile]["currentPosition"] = playTime
-                    
-                    # send update
-                    td = datetime.today() - lastProgressUpdate
-                    secDiff = td.seconds
-                    if(secDiff > 3):
-                        try:
-                            player.reportPlayback()
-                        except Exception, msg:
-                            self.logMsg("Exception reporting progress: %s" % msg)
-                            pass
-                        lastProgressUpdate = datetime.today()
-                    # only try autoplay when there's 20 seconds or less remaining and only once!
-                    if (totalTime - playTime <= 20 and (lastFile==None or lastFile!=currentFile)):
-                        lastFile = currentFile
-                        player.autoPlayPlayback()
-                    
-                except Exception, e:
-                    self.logMsg("Exception in Playback Monitor Service: %s" % e)
-                    pass
-            else:
-                if (self.newUserClient == None):
-                        self.newUserClient = "Started"
-                        user.start()
-                # background worker for database sync
-                if (user.currUser != None):
-                    
-                    # Correctly launch the websocket, if user manually launches the add-on
-                    if (self.newWebSocketThread == None):
-                        self.newWebSocketThread = "Started"
-                        ws.start()
-            
-                    #full sync
-                    if(startupComplete == False):
-                        self.logMsg("Doing_Db_Sync: syncDatabase (Started)")
-                        libSync = librarySync.syncDatabase()
-                        self.logMsg("Doing_Db_Sync: syncDatabase (Finished) " + str(libSync))
-                        countSync = librarySync.updatePlayCounts()
-                        self.logMsg("Doing_Db_Sync: updatePlayCounts (Finished) "  + str(countSync))
+            if WINDOW.getProperty('Server_online') == "true":
+                # Server is online
+                if xbmc.Player().isPlaying():
+                    try:
+                        playTime = xbmc.Player().getTime()
+                        totalTime = xbmc.Player().getTotalTime()
+                        currentFile = xbmc.Player().getPlayingFile()
 
-                        # Force refresh newly set thumbnails
-                        xbmc.executebuiltin("UpdateLibrary(video)")
-                        if(libSync and countSync):
-                            startupComplete = True
-                    else:
-                        if self.KodiMonitor.waitForAbort(10):
-                            # Abort was requested while waiting. We should exit
-                            break    
-                        WebSocketThread().processPendingActions()
-                    
+                        if(player.played_information.get(currentFile) != None):
+                            player.played_information[currentFile]["currentPosition"] = playTime
+                        
+                        # send update
+                        td = datetime.today() - lastProgressUpdate
+                        secDiff = td.seconds
+                        if(secDiff > 3):
+                            try:
+                                player.reportPlayback()
+                            except Exception, msg:
+                                self.logMsg("Exception reporting progress: %s" % msg)
+                                pass
+                            lastProgressUpdate = datetime.today()
+                        # only try autoplay when there's 20 seconds or less remaining and only once!
+                        if (totalTime - playTime <= 20 and (lastFile==None or lastFile!=currentFile)):
+                            lastFile = currentFile
+                            player.autoPlayPlayback()
+                        
+                    except Exception, e:
+                        self.logMsg("Exception in Playback Monitor Service: %s" % e)
+                        pass
                 else:
-                    self.logMsg("Not authenticated yet", 0)
+                    # background worker for database sync
+                    if (user.currUser != None):
+                        self.warn_auth = True
+                        
+                        # Correctly launch the websocket, if user manually launches the add-on
+                        if (self.newWebSocketThread == None):
+                            self.newWebSocketThread = "Started"
+                            ws.start()
+                
+                        #full sync
+                        if (startupComplete == False):
+                            self.logMsg("Doing_Db_Sync: syncDatabase (Started)")
+                            libSync = librarySync.FullLibrarySync()
+                            self.logMsg("Doing_Db_Sync: syncDatabase (Finished) " + str(libSync))
+
+                            if (libSync):
+                                startupComplete = True
+                        else:
+                            if self.KodiMonitor.waitForAbort(1):
+                                # Abort was requested while waiting. We should exit
+                                break    
+                            WebSocketThread().processPendingActions()
+                        
+                    else:
+                        if self.warn_auth:
+                            self.logMsg("Not authenticated yet.", 1)
+                            self.warn_auth = False
+            else:
+                # Wait until server becomes online or shut down is requested
+                while not self.KodiMonitor.abortRequested():
                     
-        self.logMsg("stopping Service", 0)
+                    if user.getServer() == "":
+                        pass
+                    elif not user.getPublicUsers():
+                        # Server is not online, suppress future warning
+                        if self.server_online:
+                            WINDOW.setProperty("Server_online", "false")
+                            self.logMsg("Server is offline.", 1)
+                            xbmcgui.Dialog().notification("Error connecting", "%s Server is unreachable." % self.addonName)
+                        self.server_online = False
+                    else:
+                        # Server is online
+                        if not self.server_online:
+                            # Server was not online when Kodi started.
+                            # Wait for server to be fully established.
+                            if self.KodiMonitor.waitForAbort(5):
+                                # Abort was requested while waiting.
+                                break
+                        self.server_online = True
+                        self.logMsg("Server is online and ready.", 1)
+                        xbmcgui.Dialog().notification("Connection successful", "%s Server is online." % self.addonName, time=2000)
+                        WINDOW.setProperty("Server_online", "true")
+                        
+                        # Server is online, proceed.
+                        if (self.newUserClient == None):
+                            self.newUserClient = "Started"
+                            user.start()
+                        break
+
+                    if self.KodiMonitor.waitForAbort(1):
+                        # Abort was requested while waiting.
+                        break
 
         # If user reset library database.
-        WINDOW = xbmcgui.Window(10000)
         if WINDOW.getProperty("SyncInstallRunDone") == "false":
             addon = xbmcaddon.Addon('plugin.video.emby')
             addon.setSetting("SyncInstallRunDone", "false")
@@ -143,8 +174,9 @@ class Service():
             ws.stopClient()
 
         if (self.newUserClient != None):
-            user.stopClient()              
-        
+            user.stopClient()
+
+        self.logMsg("======== STOP %s ========" % self.addonName, 0)
        
 #start the service
 Service().ServiceEntryPoint()