From 23b9f000e765cb2d2ba7622ffa9c34d1071dae85 Mon Sep 17 00:00:00 2001
From: angelblue05 <tamara.angel05@gmail.com>
Date: Fri, 5 Jun 2015 01:05:40 -0500
Subject: [PATCH] Unicode paths for users with special characters

---
 service.py | 248 +++++++++++++++++++++++++++--------------------------
 1 file changed, 128 insertions(+), 120 deletions(-)

diff --git a/service.py b/service.py
index 80a9d82b..b86c535c 100644
--- a/service.py
+++ b/service.py
@@ -1,155 +1,188 @@
+# -- coding: utf-8 --
+
+import os
+import sys
+import time
+from datetime import datetime
+
 import xbmcaddon
 import xbmc
 import xbmcgui
-import os
-import threading
-import json
-from datetime import datetime
-import time
 
-cwd = xbmcaddon.Addon(id='plugin.video.emby').getAddonInfo('path')
-BASE_RESOURCE_PATH = xbmc.translatePath( os.path.join( cwd, 'resources', 'lib' ) )
-sys.path.append(BASE_RESOURCE_PATH)
+addon_ = xbmcaddon.Addon(id='plugin.video.emby')
+addon_path = addon_.getAddonInfo('path').decode('utf-8')
+base_resource_path = xbmc.translatePath(os.path.join(addon_path, 'resources', 'lib')).decode('utf-8')
+sys.path.append(base_resource_path)
 
 import KodiMonitor
 import Utils as utils
-from LibrarySync import LibrarySync
-from Player import Player
-from DownloadUtils import DownloadUtils
-from ConnectionManager import ConnectionManager
 from ClientInformation import ClientInformation
-from WebSocketClient import WebSocketThread
+from ConnectionManager import ConnectionManager
 from UserClient import UserClient
-from PlaybackUtils import PlaybackUtils
-librarySync = LibrarySync()
+from Player import Player
+from WebSocketClient import WebSocketThread
+from LibrarySync import LibrarySync
 
 
 class Service():
-    
 
-    newWebSocketThread = None
-    newUserClient = None
-
-    clientInfo = ClientInformation()
     KodiMonitor = KodiMonitor.Kodi_Monitor()
+    clientInfo = ClientInformation()
+    librarySync = LibrarySync()
+
     addonName = clientInfo.getAddonName()
     WINDOW = xbmcgui.Window(10000)
 
+    newWebSocketThread = None
+    newUserClient = None
     warn_auth = True
+    welcome_msg = True
     server_online = True
-    
-    def __init__(self, *args ):
-        addonName = self.addonName
 
+    def __init__(self, *args):
+
+        addonName = self.addonName
+        WINDOW = self.WINDOW
+
+        # Initial logging
         self.logMsg("Starting Monitor", 0)
         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)
+        self.logMsg("KODI Version: %s" % xbmc.getInfoLabel('System.BuildVersion'), 0)
+        self.logMsg("%s Version: %s" % (addonName, self.clientInfo.getVersion()), 0)
+        self.logMsg("Log Level: %s" % UserClient().getLogLevel(), 1)
+
+        # Reset window props for profile switch
+        WINDOW.clearProperty('Server_online')
+        WINDOW.clearProperty('Server_status')
+        WINDOW.clearProperty('startup')
+
+        embyProperty = WINDOW.getProperty('Emby.nodes.total')
+        propNames = [
         
-        #reset all window props on startup for user profile switches
-        self.WINDOW.clearProperty("startup")
-        embyProperty = self.WINDOW.getProperty("Emby.nodes.total")
-        propNames = ["index","path","title","content","inprogress.content","inprogress.title","inprogress.content","inprogress.path","nextepisodes.title","nextepisodes.content","nextepisodes.path","unwatched.title","unwatched.content","unwatched.path","recent.title","recent.content","recent.path","recentepisodes.title","recentepisodes.content","recentepisodes.path","inprogressepisodes.title","inprogressepisodes.content","inprogressepisodes.path"]
+            "index","path","title","content",
+            "inprogress.content","inprogress.title",
+            "inprogress.content","inprogress.path",
+            "nextepisodes.title","nextepisodes.content",
+            "nextepisodes.path","unwatched.title",
+            "unwatched.content","unwatched.path",
+            "recent.title","recent.content","recent.path",
+            "recentepisodes.title","recentepisodes.content",
+            "recentepisodes.path","inprogressepisodes.title",
+            "inprogressepisodes.content","inprogressepisodes.path"
+        ]
+
         if embyProperty:
             totalNodes = int(embyProperty)
             for i in range(totalNodes):
                 for prop in propNames:
-                    self.WINDOW.clearProperty("Emby.nodes.%s.%s" %(str(i),prop))
-
+                    WINDOW.clearProperty('Emby.nodes.%s.%s' % (str(i), prop))
 
     def logMsg(self, msg, lvl=1):
-        
+
         className = self.__class__.__name__
-        utils.logMsg("%s %s" % (self.addonName, className), str(msg), int(lvl))
-            
+        utils.logMsg("%s %s" % (self.addonName, className), msg, int(lvl))
+       
     def ServiceEntryPoint(self):
         
         WINDOW = self.WINDOW
-        WINDOW.setProperty("Server_online", "")
-        self.WINDOW.setProperty("Server_status", "")
-        WINDOW.setProperty("Emby_Service_Timestamp", str(int(time.time())))
         
+        # Server auto-detect
         ConnectionManager().checkServer()
-        lastProgressUpdate = datetime.today()
-        startupComplete = False
-        
+
+        # Initialize important threads
         user = UserClient()
         player = Player()
         ws = WebSocketThread()
-        
-        lastFile = None
-        
+
+        # Sync and progress report
+        startupComplete = False
+        lastProgressUpdate = datetime.today()
+
         while not self.KodiMonitor.abortRequested():
-            #WINDOW.setProperty("Emby_Service_Timestamp", str(int(time.time())))
-                     
-            if self.KodiMonitor.waitForAbort(1):
-                # Abort was requested while waiting. We should exit
-                break
 
+            # Before proceeding, need to make sure:
+            # 1. Server is online
+            # 2. User is set
+            # 3. User has access to the server
+            
             if WINDOW.getProperty('Server_online') == "true":
-                # Server is online
-                if (user.currUser != None) and (user.HasAccess == True):
-                    self.warn_auth = True
+                
+                # Emby server is online
+                # Verify if user is set and has access to the server
+                if (user.currUser != None) and user.HasAccess:
+                    
+                    if self.welcome_msg:
+                        # Reset authentication warnings
+                        self.welcome_msg = False
+                        self.warn_auth = True
+                        xbmcgui.Dialog().notification("Emby server", "Welcome %s!" % user.currUser, sound=False)
 
-                    # Correctly launch the websocket, if user manually launches the add-on
+                    # Start the Websocket Client
                     if (self.newWebSocketThread == None):
                         self.newWebSocketThread = "Started"
                         ws.start()
 
+                    # If an item is playing
                     if xbmc.Player().isPlaying():
-                        #WINDOW.setProperty("Emby_Service_Timestamp", str(int(time.time())))
                         try:
+                            # Update and report progress
                             playTime = xbmc.Player().getTime()
                             totalTime = xbmc.Player().getTotalTime()
                             currentFile = xbmc.Player().getPlayingFile()
 
-                            if(player.played_information.get(currentFile) != None):
+                            # Update positionticks
+                            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):
+                            
+                            # Report progress to Emby server
+                            if (secDiff > 3):
                                 try:
                                     player.reportPlayback()
-                                except Exception, msg:
+                                except Exception as msg:
                                     self.logMsg("Exception reporting progress: %s" % msg)
                                     pass
                                 lastProgressUpdate = datetime.today()
+                            
                             elif WINDOW.getProperty('commandUpdate') == "true":
+                                # Received a remote control command that
+                                # requires updating immediately
                                 try:
                                     WINDOW.clearProperty('commandUpdate')
                                     player.reportPlayback()
                                 except: pass
                                 lastProgressUpdate = datetime.today()
                             
-                        except Exception, e:
+                        except Exception as e:
                             self.logMsg("Exception in Playback Monitor Service: %s" % e)
                             pass
 
                     else:
-                        #full sync
-                        if (startupComplete == False):
-                            self.logMsg("Doing_Db_Sync: syncDatabase (Started)")
-                            libSync = librarySync.FullLibrarySync()
-                            self.logMsg("Doing_Db_Sync: syncDatabase (Finished) " + str(libSync))
-                            #WINDOW.setProperty("Emby_Service_Timestamp", str(int(time.time())))
-                            if (libSync):
+                        # Library sync
+                        if not startupComplete:
+                            # Run full sync
+                            self.logMsg("Doing_Db_Sync: syncDatabase (Started)", 1)
+                            libSync = self.librarySync.FullLibrarySync()
+                            self.logMsg("Doing_Db_Sync: syncDatabase (Finished) %s" % libSync, 1)
+
+                            if libSync:
                                 startupComplete = True
-                        else:
-                            if self.KodiMonitor.waitForAbort(1):
-                                # Abort was requested while waiting. We should exit
-                                break
+
                 else:
                     
-                    if self.warn_auth:
-                        self.logMsg("Not authenticated yet.", 1)
+                    if (user.currUser == None) and self.warn_auth:
+                        # Alert user is not authenticated and suppress future warning
                         self.warn_auth = False
+                        self.logMsg("Not authenticated yet.", 1)
 
+                    # User access is restricted.
+                    # Keep verifying until access is granted
+                    # unless server goes offline or Kodi is shut down.
                     while user.HasAccess == False:
-
-                        #WINDOW.setProperty("Emby_Service_Timestamp", str(int(time.time())))
+                        # Verify access with an API call
                         user.hasAccess()
 
                         if WINDOW.getProperty('Server_online') != "true":
@@ -160,38 +193,41 @@ class Service():
                             # Abort was requested while waiting. We should exit
                             break
 
-
             else:
-                # Wait until server becomes online or shut down is requested
+                # Wait until Emby server is online
+                # or Kodi is shut down.
                 while not self.KodiMonitor.abortRequested():
-                    #WINDOW.setProperty("Emby_Service_Timestamp", str(int(time.time())))
                     
                     if user.getServer() == "":
+                        # No server info set in add-on settings
                         pass
+                    
                     elif user.getPublicUsers() == False:
-                        # Server is not online, suppress future warning
+                        # Server is offline.
+                        # Alert the user and 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)
+                            WINDOW.setProperty('Server_online', "false")
+                            xbmcgui.Dialog().notification("Error connecting", "%s Server is unreachable." % self.addonName, sound=False)
                         self.server_online = False
+                    
                     else:
                         # Server is online
                         if not self.server_online:
-                            # Server was not online when Kodi started.
+                            # Server was offline when Kodi started.
                             # Wait for server to be fully established.
                             if self.KodiMonitor.waitForAbort(5):
                                 # Abort was requested while waiting.
                                 break
+                            # Alert the user that server is online.
+                            xbmcgui.Dialog().notification("Connection successful", "%s Server is online." % self.addonName, time=2000, sound=False)
+                        
                         self.server_online = True
                         self.logMsg("Server is online and ready.", 1)
-                        addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
-                        if addonSettings.getSetting("supressConnectMsg")=="false":
-                            xbmcgui.Dialog().notification("Connection successful", "%s Server is online." % self.addonName, time=2000)
-                        WINDOW.setProperty("Server_online", "true")
+                        WINDOW.setProperty('Server_online', "true")
                         
-                        # Server is online, proceed.
-                        if (self.newUserClient == None):
+                        # Start the User client
+                        if self.newUserClient == None:
                             self.newUserClient = "Started"
                             user.start()
                         break
@@ -200,12 +236,14 @@ class Service():
                         # Abort was requested while waiting.
                         break
 
-            #self.checkService()
+            if self.KodiMonitor.waitForAbort(1):
+                # Abort was requested while waiting. We should exit
+                break
 
         # If user reset library database.
-        if WINDOW.getProperty("SyncInstallRunDone") == "false":
+        if WINDOW.getProperty('SyncInstallRunDone') == "false":
             addon = xbmcaddon.Addon('plugin.video.emby')
-            addon.setSetting("SyncInstallRunDone", "false")
+            addon.setSetting('SyncInstallRunDone', "false")
         
         if (self.newWebSocketThread != None):
             ws.stopClient()
@@ -215,35 +253,5 @@ class Service():
 
         self.logMsg("======== STOP %s ========" % self.addonName, 0)
 
-    # To be reviewed when moving the sync process to it's own thread
-    '''def checkService(self):
-
-        WINDOW = self.WINDOW
-        timeStamp = WINDOW.getProperty("Emby_Service_Timestamp")
-        loops = 0
-
-        while(timeStamp == ""):
-            timeStamp = WINDOW.getProperty("Emby_Service_Timestamp")
-            loops = loops + 1
-            if(loops == 5):
-                self.logMsg("Emby Service Not Running, no time stamp, exiting.", 0)
-                addon = xbmcaddon.Addon(id='plugin.video.emby')
-                language = addon.getLocalizedString
-                xbmcgui.Dialog().ok(language(30135), language(30136), language(30137))
-                sys.exit()
-            if self.KodiMonitor.waitForAbort(1):
-                # Abort was requested while waiting. We should exit
-                return
-            
-        self.logMsg("Emby Service Timestamp: " + timeStamp, 2)
-        self.logMsg("Emby Current Timestamp: " + str(int(time.time())), 2)
-        
-        if((int(timeStamp) + 30) < int(time.time())):
-            self.logMsg("Emby Service Not Running, time stamp to old, exiting.", 0)
-            addon = xbmcaddon.Addon(id='plugin.video.emby')
-            language = addon.getLocalizedString        
-            xbmcgui.Dialog().ok(language(30135), language(30136), language(30137))
-            sys.exit()'''
-       
 #start the service
-Service().ServiceEntryPoint()
+Service().ServiceEntryPoint()
\ No newline at end of file