diff --git a/addon.xml b/addon.xml
index a43e3393..ffe99310 100644
--- a/addon.xml
+++ b/addon.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <addon  id="plugin.video.emby" 
         name="Emby" 
-        version="1.0.08"
+        version="1.0.15"
         provider-name="Emby.media">
   <requires>
     <import addon="xbmc.python" version="2.1.0"/>
diff --git a/resources/lib/Entrypoint.py b/resources/lib/Entrypoint.py
index d64bd28d..02556930 100644
--- a/resources/lib/Entrypoint.py
+++ b/resources/lib/Entrypoint.py
@@ -144,6 +144,20 @@ def getThemeMedia():
         playback = "DirectStream"
     else:return
 
+    # Set custom path for user
+    tvtunes_path = xbmc.translatePath("special://profile/addon_data/script.tvtunes/")
+    if xbmcvfs.exists(tvtunes_path):
+        tvtunes = xbmcaddon.Addon(id="script.tvtunes")
+        tvtunes.setSetting('custom_path_enable', "true")
+        tvtunes.setSetting('custom_path', library)
+        xbmc.log("TV Tunes custom path is enabled and set.")
+    else:
+        # if it does not exist this will not work so warn user, often they need to edit the settings first for it to be created.
+        dialog = xbmcgui.Dialog()
+        dialog.ok('Warning', 'The settings file does not exist in tvtunes. Go to the tvtunes addon and change a setting, then come back and re-run')
+        return
+        
+
     # Create library directory
     if not xbmcvfs.exists(library):
         xbmcvfs.mkdir(library)
@@ -157,18 +171,20 @@ def getThemeMedia():
         userviewId = view[u'Id']
         userViews.append(userviewId)
 
-    # Get Ids with Theme songs
+
+    # Get Ids with Theme Videos
     itemIds = {}
     for view in userViews:
-        url = "{server}/mediabrowser/Users/{UserId}/Items?HasThemeSong=True&ParentId=%s&format=json" % view
+        url = "{server}/mediabrowser/Users/{UserId}/Items?HasThemeVideo=True&ParentId=%s&format=json" % view
         result = doUtils.downloadUrl(url)
         if result[u'TotalRecordCount'] != 0:
             for item in result[u'Items']:
                 itemId = item[u'Id']
                 folderName = item[u'Name']
+                folderName = utils.normalize_string(folderName.encode('utf-8'))
                 itemIds[itemId] = folderName
 
-    # Get paths
+    # Get paths for theme videos
     for itemId in itemIds:
         nfo_path = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/library/%s/" % itemIds[itemId])
         # Create folders for each content
@@ -177,6 +193,64 @@ def getThemeMedia():
         # Where to put the nfos
         nfo_path = "%s%s" % (nfo_path, "tvtunes.nfo")
 
+        url = "{server}/mediabrowser/Items/%s/ThemeVideos?format=json" % itemId
+        result = doUtils.downloadUrl(url)
+
+        # Create nfo and write themes to it
+        nfo_file = open(nfo_path, 'w')
+        pathstowrite = ""
+        # May be more than one theme
+        for theme in result[u'Items']:  
+            if playback == "DirectPlay":
+                playurl = playUtils.directPlay(theme)
+            else:
+                playurl = playUtils.directStream(result, server, theme[u'Id'])
+            pathstowrite += ('<file>%s</file>' % playurl.encode('utf-8'))
+        
+        # Check if the item has theme songs and add them   
+        url = "{server}/mediabrowser/Items/%s/ThemeSongs?format=json" % itemId
+        result = doUtils.downloadUrl(url)
+
+        # May be more than one theme
+        for theme in result[u'Items']:  
+            if playback == "DirectPlay":
+                playurl = playUtils.directPlay(theme)
+            else:
+                playurl = playUtils.directStream(result, server, theme[u'Id'], "Audio")
+            pathstowrite += ('<file>%s</file>' % playurl.encode('utf-8'))
+
+        nfo_file.write(
+            '<tvtunes>%s</tvtunes>' % pathstowrite
+        )
+        # Close nfo file
+        nfo_file.close()
+
+    # Get Ids with Theme songs
+    musicitemIds = {}
+    for view in userViews:
+        url = "{server}/mediabrowser/Users/{UserId}/Items?HasThemeSong=True&ParentId=%s&format=json" % view
+        result = doUtils.downloadUrl(url)
+        if result[u'TotalRecordCount'] != 0:
+            for item in result[u'Items']:
+                itemId = item[u'Id']
+                folderName = item[u'Name']
+                folderName = utils.normalize_string(folderName.encode('utf-8'))
+                musicitemIds[itemId] = folderName
+
+    # Get paths
+    for itemId in musicitemIds:
+        
+        # if the item was already processed with video themes back out
+        if itemId in itemIds:
+            continue
+        
+        nfo_path = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/library/%s/" % musicitemIds[itemId])
+        # Create folders for each content
+        if not xbmcvfs.exists(nfo_path):
+            xbmcvfs.mkdir(nfo_path)
+        # Where to put the nfos
+        nfo_path = "%s%s" % (nfo_path, "tvtunes.nfo")
+        
         url = "{server}/mediabrowser/Items/%s/ThemeSongs?format=json" % itemId
         result = doUtils.downloadUrl(url)
 
@@ -189,7 +263,7 @@ def getThemeMedia():
                 playurl = playUtils.directPlay(theme)
             else:
                 playurl = playUtils.directStream(result, server, theme[u'Id'], "Audio")
-            pathstowrite += ('<file>%s</file>' % playurl)
+            pathstowrite += ('<file>%s</file>' % playurl.encode('utf-8'))
 
         nfo_file.write(
             '<tvtunes>%s</tvtunes>' % pathstowrite
@@ -576,12 +650,12 @@ def doMainListing():
                 addDirectoryItem(label, path)
     
     # some extra entries for settings and stuff. TODO --> localize the labels
-    addDirectoryItem("Settings", "plugin://plugin.video.emby/?mode=settings")
-    addDirectoryItem("Perform manual sync", "plugin://plugin.video.emby/?mode=manualsync")
-    addDirectoryItem("Add user to session", "plugin://plugin.video.emby/?mode=adduser")
-    addDirectoryItem("Configure user preferences", "plugin://plugin.video.emby/?mode=userprefs")
-    addDirectoryItem("Perform local database reset (full resync)", "plugin://plugin.video.emby/?mode=reset")
-    addDirectoryItem("Cache all images to Kodi texture cache (advanced)", "plugin://plugin.video.emby/?mode=texturecache")
-    addDirectoryItem("Sync Emby Theme Media to Kodi", "plugin://plugin.video.emby/?mode=thememedia")
+    addDirectoryItem("Settings", "plugin://plugin.video.emby/?mode=settings", False)
+    addDirectoryItem("Perform manual sync", "plugin://plugin.video.emby/?mode=manualsync", False)
+    addDirectoryItem("Add user to session", "plugin://plugin.video.emby/?mode=adduser", False)
+    addDirectoryItem("Configure user preferences", "plugin://plugin.video.emby/?mode=userprefs", False)
+    addDirectoryItem("Perform local database reset (full resync)", "plugin://plugin.video.emby/?mode=reset", False)
+    addDirectoryItem("Cache all images to Kodi texture cache (advanced)", "plugin://plugin.video.emby/?mode=texturecache", False)
+    addDirectoryItem("Sync Emby Theme Media to Kodi", "plugin://plugin.video.emby/?mode=thememedia", False)
     
     xbmcplugin.endOfDirectory(int(sys.argv[1]))                
diff --git a/resources/lib/LibrarySync.py b/resources/lib/LibrarySync.py
index ebfaee9e..90be6ec3 100644
--- a/resources/lib/LibrarySync.py
+++ b/resources/lib/LibrarySync.py
@@ -131,6 +131,9 @@ class LibrarySync(threading.Thread):
             # set prop to show we have run for the first time
             WINDOW.setProperty("startup", "done")
             
+            # tell any widgets to refresh because the content has changed
+            WINDOW.setProperty("widgetreload", datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
+            
         finally:
             WINDOW.setProperty("SyncDatabaseRunning", "false")
             utils.logMsg("Sync DB", "syncDatabase Exiting", 0)
@@ -596,6 +599,16 @@ class LibrarySync(threading.Thread):
                             #tv show doesn't exist
                             #perform full tvshow sync instead so both the show and episodes get added
                             self.TvShowsFullSync(connection,cursor,None)
+
+                    elif u"Season" in MBitem['Type']:
+
+                        #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]
+                            # update season
+                            WriteKodiVideoDB().updateSeasons(MBitem["SeriesId"], kodi_show_id, connection, cursor)
                     
                     #### PROCESS BOXSETS ######
                     elif MBitem["Type"] == "BoxSet":
@@ -630,9 +643,10 @@ class LibrarySync(threading.Thread):
                     cursor.close()
 
             finally:
-                
                 xbmc.executebuiltin("UpdateLibrary(video)")
                 WINDOW.setProperty("SyncDatabaseRunning", "false")
+                # tell any widgets to refresh because the content has changed
+                WINDOW.setProperty("widgetreload", datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
 
     def ShouldStop(self):
             
@@ -673,4 +687,4 @@ class LibrarySync(threading.Thread):
                 # Abort was requested while waiting. We should exit
                 break
 
-        self.logMsg("--- Library Sync Thread stopped ---", 0)
\ No newline at end of file
+        self.logMsg("--- Library Sync Thread stopped ---", 0)
diff --git a/resources/lib/TextureCache.py b/resources/lib/TextureCache.py
index e095cbec..81762afb 100644
--- a/resources/lib/TextureCache.py
+++ b/resources/lib/TextureCache.py
@@ -3,11 +3,11 @@
 #################################################################################################
 
 
-import xbmc
-import xbmcaddon
+import xbmc, xbmcaddon, xbmcvfs
 import json
 import requests
 import urllib
+import os
 
 import Utils as utils
 
@@ -42,15 +42,38 @@ class TextureCache():
     def FullTextureCacheSync(self):
         #this method can be called from the plugin to sync all Kodi textures to the texture cache.
         #Warning: this means that every image will be cached locally, this takes diskspace!
+        
+        #remove all existing textures first
+        path = "special://thumbnails/"
+        if xbmcvfs.exists(path):
+            allDirs, allFiles = xbmcvfs.listdir(path)
+            for dir in allDirs:
+                allDirs, allFiles = xbmcvfs.listdir(path+dir)
+                for file in allFiles:
+                    xbmcvfs.delete(os.path.join(path+dir,file))
+        
+        textureconnection = utils.KodiSQL("texture")
+        texturecursor = textureconnection.cursor()
+        texturecursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
+        rows = texturecursor.fetchall()
+        for row in rows:
+            tableName = row[0]
+            if(tableName != "version"):
+                texturecursor.execute("DELETE FROM " + tableName)
+        textureconnection.commit()
+        texturecursor.close()
+
+        
+        #cache all entries in video DB
         connection = utils.KodiSQL("video")
         cursor = connection.cursor()
         cursor.execute("SELECT url FROM art")
         result = cursor.fetchall()
         for url in result:
             self.CacheTexture(url[0])
-        
         cursor.close()    
         
+        #cache all entries in music DB
         connection = utils.KodiSQL("music")
         cursor = connection.cursor()
         cursor.execute("SELECT url FROM art")
@@ -73,7 +96,7 @@ class TextureCache():
             except:
                 #extreme short timeouts so we will have a exception, but we don't need the result so pass
                 pass
-            
+           
       
     def setKodiWebServerDetails(self):
         # Get the Kodi webserver details - used to set the texture cache
diff --git a/resources/lib/Utils.py b/resources/lib/Utils.py
index 40bba457..5ea5bcfa 100644
--- a/resources/lib/Utils.py
+++ b/resources/lib/Utils.py
@@ -54,6 +54,8 @@ def KodiSQL(type="video"):
     
     if type == "music":
         dbPath = getKodiMusicDBPath()
+    elif type == "texture":
+        dbPath = xbmc.translatePath("special://database/Textures13.db")
     else:
         dbPath = getKodiVideoDBPath()
     
@@ -73,12 +75,7 @@ def getKodiVideoDBPath():
         dbVersion = "90"
     elif kodibuild.startswith("15"):
         # Isengard
-        if "BETA1" in kodibuild:
-            # Beta 1
-            dbVersion = "92"
-        elif "BETA2" in kodibuild:
-            # Beta 2
-            dbVersion = "93"
+        dbVersion = "93"
     else:
         # Not a compatible build
         xbmc.log("This Kodi version is incompatible. Current version: %s" % kodibuild)
@@ -100,17 +97,7 @@ def getKodiMusicDBPath():
     
     dbPath = xbmc.translatePath("special://profile/Database/MyMusic" + dbVersion + ".db")
     
-    return dbPath      
-    
-    
-def checkAuthentication():
-    #check authentication
-    if addonSettings.getSetting('username') != "" and addonSettings.getSetting('ipaddress') != "":
-        try:
-            downloadUtils.authenticate()
-        except Exception, e:
-            logMsg("Emby authentication failed",e)
-            pass
+    return dbPath   
     
 def prettifyXml(elem):
     rough_string = etree.tostring(elem, "utf-8")
@@ -174,6 +161,25 @@ def CleanName(filename):
     validFilenameChars = "-_.() %s%s" % (string.ascii_letters, string.digits)
     cleanedFilename = unicodedata.normalize('NFKD', filename).encode('ASCII', 'ignore')
     return ''.join(c for c in cleanedFilename if c in validFilenameChars)
+
+def normalize_string(text):
+    try:
+        text = text.replace(":", "")
+        text = text.replace("/", "-")
+        text = text.replace("\\", "-")
+        text = text.replace("<", "")
+        text = text.replace(">", "")
+        text = text.replace("*", "")
+        text = text.replace("?", "")
+        text = text.replace('|', "")
+        text = text.strip()
+        # Remove dots from the last character as windows can not have directories
+        # with dots at the end
+        text = text.rstrip('.')
+        text = unicodedata.normalize('NFKD', unicode(text, 'utf-8')).encode('ascii', 'ignore')
+    except:
+        pass
+    return text
    
         
 def reset():
diff --git a/resources/lib/WriteKodiVideoDB.py b/resources/lib/WriteKodiVideoDB.py
index a980ce22..5de8f6b6 100644
--- a/resources/lib/WriteKodiVideoDB.py
+++ b/resources/lib/WriteKodiVideoDB.py
@@ -39,18 +39,11 @@ class WriteKodiVideoDB():
         cursor = connection.cursor()
         cursor.execute("SELECT emby_id FROM emby WHERE media_type=? AND kodi_id=?",(type,id))
         
-        emby_id = cursor.fetchone()[0]
-        cursor.close
+        emby_id = cursor.fetchone()
 
         if(emby_id != None):
+            emby_id = emby_id[0]
             # Erase resume point when user marks watched/unwatched to follow Emby behavior
-            # Also force sets the playcount to instantly reflect the appropriate playstate.
-            if type == "episode":
-                resume = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetEpisodeDetails", "params": {"episodeid": %d, "playcount": %d, "resume": {"position": 0}}, "id": "setResumePoint"}' % (id, playcount)
-            elif type == "movie":
-                resume = '{"jsonrpc": "2.0", "method": "VideoLibrary.SetMovieDetails", "params": {"movieid": %d, "playcount": %d, "resume": {"position": 0}}, "id": "setResumePoint"}' % (id, playcount)
-            xbmc.executeJSONRPC(resume)
-            
             addon = xbmcaddon.Addon(id='plugin.video.emby')   
             downloadUtils = DownloadUtils()       
             watchedurl = "{server}/mediabrowser/Users/{UserId}/PlayedItems/%s" % emby_id
@@ -58,6 +51,9 @@ class WriteKodiVideoDB():
                 downloadUtils.downloadUrl(watchedurl, type="POST")
             else:
                 downloadUtils.downloadUrl(watchedurl, type="DELETE")
+
+            self.setKodiResumePoint(id, 0, 0, cursor)
+        cursor.close
         
     def addOrUpdateMovieToKodiLibrary( self, embyId ,connection, cursor, viewTag):
         
@@ -123,6 +119,13 @@ class WriteKodiVideoDB():
             if(jsonData != ""):
                 trailerItem = jsonData
                 trailerUrl = "plugin://plugin.video.emby/trailer/?id=%s&mode=play" % trailerItem[0][u'Id']
+        elif MBitem.get("RemoteTrailers"):
+            try:
+                trailerUrl = MBitem.get("RemoteTrailers")[0].get("Url")
+                trailerId = trailerUrl.split('=')[1]
+                trailerUrl = "plugin://plugin.video.youtube/play/?video_id=%s" % trailerId
+            except:
+                trailerUrl = MBitem.get("RemoteTrailers")[0].get("Url")
         
         if MBitem.get("DateCreated") != None:
             dateadded = MBitem["DateCreated"].split('.')[0].replace('T', " ")
@@ -142,24 +145,20 @@ class WriteKodiVideoDB():
             
         #### ADD OR UPDATE THE FILE AND PATH ###########
         #### NOTE THAT LASTPLAYED AND PLAYCOUNT ARE STORED AT THE FILE ENTRY
-        if addon.getSetting('useDirectPaths')=='true':
-            if PlayUtils().isDirectPlay(MBitem):
-                playurl = PlayUtils().directPlay(MBitem)
-                #use the direct file path
-                if "\\" in playurl:
-                    filename = playurl.rsplit("\\",1)[-1]
-                    path = playurl.replace(filename,"")
-                elif "/" in playurl:
-                    filename = playurl.rsplit("/",1)[-1]
-                    path = playurl.replace(filename,"")        
-            else:
-                #for transcoding we just use the server's streaming path because I couldn't figure out how to set the plugin path in the music DB
-                path = server + "/Video/%s/" %MBitem["Id"]
-                filename = "stream.mp4"                
+        if addon.getSetting('useDirectPaths') == 'true':
+            playurl = PlayUtils().directPlay(MBitem)
+            if playurl == False:
+                return
+            elif "\\" in playurl:
+                filename = playurl.rsplit("\\",1)[-1]
+                path = playurl.replace(filename, "")
+            elif "/" in playurl:
+                filename = playurl.rsplit("/",1)[-1]
+                path = playurl.replace(filename, "")
         else:
             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()
@@ -757,7 +756,22 @@ class WriteKodiVideoDB():
                     self.addOrUpdateArt(imageUrl, seasonid, "season", "poster", cursor)
                     
                     imageUrl = API().getArtwork(season, "Banner")
-                    self.addOrUpdateArt(imageUrl, seasonid, "season", "banner", cursor)                    
+                    self.addOrUpdateArt(imageUrl, seasonid, "season", "banner", cursor)
+            # Set All season poster
+            MBitem = ReadEmbyDB().getFullItem(embyTvShowId)
+            seasonNum = -1
+            cursor.execute("SELECT idSeason as seasonid FROM seasons WHERE idShow = ? and season = ?", (kodiTvShowId, seasonNum))
+            result = cursor.fetchone()
+            if result == None:
+                # Create the all-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, kodiTvShowId, seasonNum))
+            else:
+                seasonid = result[0]
+            imageUrl = API().getArtwork(MBitem, "Primary")
+            self.addOrUpdateArt(imageUrl, seasonid, "season", "poster", cursor)
                             
     def addOrUpdateArt(self, imageUrl, kodiId, mediaType, imageType, cursor):
         updateDone = False
@@ -774,7 +788,8 @@ class WriteKodiVideoDB():
                     cursor.execute("UPDATE art set url = ? WHERE media_id = ? AND media_type = ? AND type = ?", (imageUrl, kodiId, mediaType, imageType))
                     
             #cache fanart and poster in Kodi texture cache
-            if imageType == "fanart" or imageType == "poster":
+            if "fanart" in imageType or "poster" in imageType:
+                utils.logMsg("ArtworkSync", "Adding or Updating Fanart: %s" % imageUrl)
                 self.textureCache.CacheTexture(imageUrl)
         
     def setKodiResumePoint(self, fileid, resume_seconds, total_seconds, cursor):