diff --git a/resources/lib/connect.py b/resources/lib/connect.py
index 2bd5c05d..87dbc2e1 100644
--- a/resources/lib/connect.py
+++ b/resources/lib/connect.py
@@ -6,8 +6,8 @@ import json
 import requests
 import logging
 
-import utils
 import clientinfo
+from utils import Logging, window
 
 ##################################################################################################
 
@@ -34,28 +34,26 @@ class ConnectUtils():
 
     def __init__(self):
 
+        global log
+        log = Logging(self.__class__.__name__).log
+
         self.__dict__ = self._shared_state
 
-    def logMsg(self, msg, lvl=1):
-
-        className = self.__class__.__name__
-        utils.logMsg("%s %s" % (self.addonName, className), msg, lvl)
-
 
     def setUserId(self, userId):
         # Reserved for userclient only
         self.userId = userId
-        self.logMsg("Set connect userId: %s" % userId, 2)
+        log("Set connect userId: %s" % userId, 2)
 
     def setServer(self, server):
         # Reserved for userclient only
         self.server = server
-        self.logMsg("Set connect server: %s" % server, 2)
+        log("Set connect server: %s" % server, 2)
 
     def setToken(self, token):
         # Reserved for userclient only
         self.token = token
-        self.logMsg("Set connect token: %s" % token, 2)
+        log("Set connect token: %s" % token, 2)
 
 
     def startSession(self):
@@ -73,7 +71,7 @@ class ConnectUtils():
             if self.sslclient is not None:
                 verify = self.sslclient
         except:
-            self.logMsg("Could not load SSL settings.", 1)
+            log("Could not load SSL settings.", 1)
 
         # Start session
         self.c = requests.Session()
@@ -83,13 +81,13 @@ class ConnectUtils():
         self.c.mount("http://", requests.adapters.HTTPAdapter(max_retries=1))
         self.c.mount("https://", requests.adapters.HTTPAdapter(max_retries=1))
 
-        self.logMsg("Requests session started on: %s" % self.server, 1)
+        log("Requests session started on: %s" % self.server, 1)
 
     def stopSession(self):
         try:
             self.c.close()
         except Exception as e:
-            self.logMsg("Requests session could not be terminated: %s" % e, 1)
+            log("Requests session could not be terminated: %s" % e, 1)
 
     def getHeader(self, authenticate=True):
 
@@ -103,7 +101,7 @@ class ConnectUtils():
                 'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
                 'Accept': "application/json"
             }
-            self.logMsg("Header: %s" % header, 1)
+            log("Header: %s" % header, 1)
 
         else:
             token = self.token
@@ -115,17 +113,17 @@ class ConnectUtils():
                 'X-Application': "Kodi/%s" % version,
                 'X-Connect-UserToken': token
             }
-            self.logMsg("Header: %s" % header, 1)
+            log("Header: %s" % header, 1)
 
         return header
 
     def doUrl(self, url, data=None, postBody=None, rtype="GET",
                 parameters=None, authenticate=True, timeout=None):
 
-        window = utils.window
-
-        self.logMsg("=== ENTER connectUrl ===", 2)
+        log("=== ENTER connectUrl ===", 2)
+        
         default_link = ""
+        
         if timeout is None:
             timeout = self.timeout
 
@@ -209,25 +207,25 @@ class ConnectUtils():
                                     verify=verifyssl)
 
             ##### THE RESPONSE #####
-            self.logMsg(r.url, 1)
-            self.logMsg(r, 1)
+            log(r.url, 1)
+            log(r, 1)
 
             if r.status_code == 204:
                 # No body in the response
-                self.logMsg("====== 204 Success ======", 1)
+                log("====== 204 Success ======", 1)
 
             elif r.status_code == requests.codes.ok:
 
                 try:
                     # UNICODE - JSON object
                     r = r.json()
-                    self.logMsg("====== 200 Success ======", 1)
-                    self.logMsg("Response: %s" % r, 1)
+                    log("====== 200 Success ======", 1)
+                    log("Response: %s" % r, 1)
                     return r
 
                 except:
                     if r.headers.get('content-type') != "text/html":
-                        self.logMsg("Unable to convert the response for: %s" % url, 1)
+                        log("Unable to convert the response for: %s" % url, 1)
             else:
                 r.raise_for_status()
 
@@ -238,8 +236,8 @@ class ConnectUtils():
             pass
 
         except requests.exceptions.ConnectTimeout as e:
-            self.logMsg("Server timeout at: %s" % url, 0)
-            self.logMsg(e, 1)
+            log("Server timeout at: %s" % url, 0)
+            log(e, 1)
 
         except requests.exceptions.HTTPError as e:
 
@@ -255,11 +253,11 @@ class ConnectUtils():
                 pass
 
         except requests.exceptions.SSLError as e:
-            self.logMsg("Invalid SSL certificate for: %s" % url, 0)
-            self.logMsg(e, 1)
+            log("Invalid SSL certificate for: %s" % url, 0)
+            log(e, 1)
 
         except requests.exceptions.RequestException as e:
-            self.logMsg("Unknown error connecting to: %s" % url, 0)
-            self.logMsg(e, 1)
+            log("Unknown error connecting to: %s" % url, 0)
+            log(e, 1)
 
-        return default_link
+        return default_link
\ No newline at end of file
diff --git a/resources/lib/downloadutils.py b/resources/lib/downloadutils.py
index a74ee6f2..ea55e7d1 100644
--- a/resources/lib/downloadutils.py
+++ b/resources/lib/downloadutils.py
@@ -9,14 +9,15 @@ import logging
 import xbmc
 import xbmcgui
 
-import utils
 import clientinfo
+from utils import Logging, window, settings
 
 ##################################################################################################
 
 # Disable requests logging
-from requests.packages.urllib3.exceptions import InsecureRequestWarning
+from requests.packages.urllib3.exceptions import InsecureRequestWarning, InsecurePlatformWarning
 requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
+requests.packages.urllib3.disable_warnings(InsecurePlatformWarning)
 #logging.getLogger('requests').setLevel(logging.WARNING)
 
 ##################################################################################################
@@ -36,40 +37,38 @@ class DownloadUtils():
 
     def __init__(self):
 
+        global log
+        log = Logging(self.__class__.__name__).log
+
         self.__dict__ = self._shared_state
 
-    def logMsg(self, msg, lvl=1):
-
-        className = self.__class__.__name__
-        utils.logMsg("%s %s" % (self.addonName, className), msg, lvl)
-
 
     def setUsername(self, username):
         # Reserved for userclient only
         self.username = username
-        self.logMsg("Set username: %s" % username, 2)
+        log("Set username: %s" % username, 2)
 
     def setUserId(self, userId):
         # Reserved for userclient only
         self.userId = userId
-        self.logMsg("Set userId: %s" % userId, 2)
+        log("Set userId: %s" % userId, 2)
 
     def setServer(self, server):
         # Reserved for userclient only
         self.server = server
-        self.logMsg("Set server: %s" % server, 2)
+        log("Set server: %s" % server, 2)
 
     def setToken(self, token):
         # Reserved for userclient only
         self.token = token
-        self.logMsg("Set token: %s" % token, 2)
+        log("Set token: %s" % token, 2)
 
     def setSSL(self, ssl, sslclient):
         # Reserved for userclient only
         self.sslverify = ssl
         self.sslclient = sslclient
-        self.logMsg("Verify SSL host certificate: %s" % ssl, 2)
-        self.logMsg("SSL client side certificate: %s" % sslclient, 2)
+        log("Verify SSL host certificate: %s" % ssl, 2)
+        log("SSL client side certificate: %s" % sslclient, 2)
 
 
     def postCapabilities(self, deviceId):
@@ -94,11 +93,11 @@ class DownloadUtils():
             )
         }
 
-        self.logMsg("Capabilities URL: %s" % url, 2)
-        self.logMsg("Postdata: %s" % data, 2)
+        log("Capabilities URL: %s" % url, 2)
+        log("Postdata: %s" % data, 2)
 
         self.downloadUrl(url, postBody=data, action_type="POST")
-        self.logMsg("Posted capabilities to %s" % self.server, 2)
+        log("Posted capabilities to %s" % self.server, 2)
 
         # Attempt at getting sessionId
         url = "{server}/emby/Sessions?DeviceId=%s&format=json" % deviceId
@@ -107,20 +106,19 @@ class DownloadUtils():
             sessionId = result[0]['Id']
 
         except (KeyError, TypeError):
-            self.logMsg("Failed to retrieve sessionId.", 1)
+            log("Failed to retrieve sessionId.", 1)
 
         else:
-            self.logMsg("Session: %s" % result, 2)
-            self.logMsg("SessionId: %s" % sessionId, 1)
-            utils.window('emby_sessionId', value=sessionId)
+            log("Session: %s" % result, 2)
+            log("SessionId: %s" % sessionId, 1)
+            window('emby_sessionId', value=sessionId)
 
             # Post any permanent additional users
-            additionalUsers = utils.settings('additionalUsers')
+            additionalUsers = settings('additionalUsers')
             if additionalUsers:
 
                 additionalUsers = additionalUsers.split(',')
-                self.logMsg(
-                    "List of permanent users added to the session: %s"
+                log("List of permanent users added to the session: %s"
                     % additionalUsers, 1)
 
                 # Get the user list from server to get the userId
@@ -158,7 +156,7 @@ class DownloadUtils():
             if self.sslclient is not None:
                 verify = self.sslclient
         except:
-            self.logMsg("Could not load SSL settings.", 1)
+            log("Could not load SSL settings.", 1)
 
         # Start session
         self.s = requests.Session()
@@ -168,18 +166,18 @@ class DownloadUtils():
         self.s.mount("http://", requests.adapters.HTTPAdapter(max_retries=1))
         self.s.mount("https://", requests.adapters.HTTPAdapter(max_retries=1))
 
-        self.logMsg("Requests session started on: %s" % self.server, 1)
+        log("Requests session started on: %s" % self.server, 1)
 
     def stopSession(self):
         try:
             self.s.close()
         except:
-            self.logMsg("Requests session could not be terminated.", 1)
+            log("Requests session could not be terminated.", 1)
 
     def getHeader(self, authenticate=True):
 
         deviceName = self.clientInfo.getDeviceName()
-        deviceName = utils.normalize_string(deviceName.encode('utf-8'))
+        deviceName = deviceName.encode('utf-8')
         deviceId = self.clientInfo.getDeviceId()
         version = self.clientInfo.getVersion()
 
@@ -195,7 +193,7 @@ class DownloadUtils():
                 'Accept-Charset': 'UTF-8,*',
                 'Authorization': auth
             }
-            self.logMsg("Header: %s" % header, 2)
+            log("Header: %s" % header, 2)
 
         else:
             userId = self.userId
@@ -212,19 +210,20 @@ class DownloadUtils():
                 'Authorization': auth,
                 'X-MediaBrowser-Token': token
             }
-            self.logMsg("Header: %s" % header, 2)
+            log("Header: %s" % header, 2)
 
         return header
 
-    def downloadUrl(self, url, postBody=None, action_type="GET", parameters=None, authenticate=True):
+    def downloadUrl(self, url, postBody=None, action_type="GET", parameters=None,
+                    authenticate=True):
 
-        self.logMsg("=== ENTER downloadUrl ===", 2)
+        log("=== ENTER downloadUrl ===", 2)
 
         default_link = ""
 
         try:
             # If user is authenticated
-            if (authenticate):
+            if authenticate:
                 # Get requests session
                 try:
                     s = self.s
@@ -243,18 +242,18 @@ class DownloadUtils():
                 except AttributeError:
                     # request session does not exists
                     # Get user information
-                    self.userId = utils.window('emby_currUser')
-                    self.server = utils.window('emby_server%s' % self.userId)
-                    self.token = utils.window('emby_accessToken%s' % self.userId)
+                    self.userId = window('emby_currUser')
+                    self.server = window('emby_server%s' % self.userId)
+                    self.token = window('emby_accessToken%s' % self.userId)
                     header = self.getHeader()
                     verifyssl = False
                     cert = None
 
                     # IF user enables ssl verification
-                    if utils.settings('sslverify') == "true":
+                    if settings('sslverify') == "true":
                         verifyssl = True
-                    if utils.settings('sslcert') != "None":
-                        verifyssl = utils.settings('sslcert')
+                    if settings('sslcert') != "None":
+                        verifyssl = settings('sslcert')
 
                     # Replace for the real values
                     url = url.replace("{server}", self.server)
@@ -314,23 +313,23 @@ class DownloadUtils():
                                     verify=verifyssl)
 
             ##### THE RESPONSE #####
-            self.logMsg(r.url, 2)
+            log(r.url, 2)
             if r.status_code == 204:
                 # No body in the response
-                self.logMsg("====== 204 Success ======", 2)
+                log("====== 204 Success ======", 2)
 
             elif r.status_code == requests.codes.ok:
 
                 try:
                     # UNICODE - JSON object
                     r = r.json()
-                    self.logMsg("====== 200 Success ======", 2)
-                    self.logMsg("Response: %s" % r, 2)
+                    log("====== 200 Success ======", 2)
+                    log("Response: %s" % r, 2)
                     return r
 
                 except:
                     if r.headers.get('content-type') != "text/html":
-                        self.logMsg("Unable to convert the response for: %s" % url, 1)
+                        log("Unable to convert the response for: %s" % url, 1)
             else:
                 r.raise_for_status()
 
@@ -338,26 +337,26 @@ class DownloadUtils():
 
         except requests.exceptions.ConnectionError as e:
             # Make the addon aware of status
-            if utils.window('emby_online') != "false":
-                self.logMsg("Server unreachable at: %s" % url, 0)
-                self.logMsg(e, 2)
-                utils.window('emby_online', value="false")
+            if window('emby_online') != "false":
+                log("Server unreachable at: %s" % url, 0)
+                log(e, 2)
+                window('emby_online', value="false")
 
         except requests.exceptions.ConnectTimeout as e:
-            self.logMsg("Server timeout at: %s" % url, 0)
-            self.logMsg(e, 1)
+            log("Server timeout at: %s" % url, 0)
+            log(e, 1)
 
         except requests.exceptions.HTTPError as e:
 
             if r.status_code == 401:
                 # Unauthorized
-                status = utils.window('emby_serverStatus')
+                status = window('emby_serverStatus')
 
                 if 'X-Application-Error-Code' in r.headers:
                     # Emby server errors
                     if r.headers['X-Application-Error-Code'] == "ParentalControl":
                         # Parental control - access restricted
-                        utils.window('emby_serverStatus', value="restricted")
+                        window('emby_serverStatus', value="restricted")
                         xbmcgui.Dialog().notification(
                                                 heading="Emby server",
                                                 message="Access restricted.",
@@ -371,8 +370,8 @@ class DownloadUtils():
 
                 elif status not in ("401", "Auth"):
                     # Tell userclient token has been revoked.
-                    utils.window('emby_serverStatus', value="401")
-                    self.logMsg("HTTP Error: %s" % e, 0)
+                    window('emby_serverStatus', value="401")
+                    log("HTTP Error: %s" % e, 0)
                     xbmcgui.Dialog().notification(
                                             heading="Error connecting",
                                             message="Unauthorized.",
@@ -387,11 +386,11 @@ class DownloadUtils():
                 pass
 
         except requests.exceptions.SSLError as e:
-            self.logMsg("Invalid SSL certificate for: %s" % url, 0)
-            self.logMsg(e, 1)
+            log("Invalid SSL certificate for: %s" % url, 0)
+            log(e, 1)
 
         except requests.exceptions.RequestException as e:
-            self.logMsg("Unknown error connecting to: %s" % url, 0)
-            self.logMsg(e, 1)
+            log("Unknown error connecting to: %s" % url, 0)
+            log(e, 1)
 
         return default_link
\ No newline at end of file
diff --git a/resources/lib/image_cache_thread.py b/resources/lib/image_cache_thread.py
index 626be481..fdf63d63 100644
--- a/resources/lib/image_cache_thread.py
+++ b/resources/lib/image_cache_thread.py
@@ -1,8 +1,14 @@
+# -*- coding: utf-8 -*-
+
+#################################################################################################
+
 import threading
-import utils
-import xbmc
 import requests
 
+from utils import Logging
+
+#################################################################################################
+
 class image_cache_thread(threading.Thread):
 
     urlToProcess = None
@@ -13,28 +19,32 @@ class image_cache_thread(threading.Thread):
     xbmc_username = ""
     xbmc_password = ""
     
+
     def __init__(self):
-        self.monitor = xbmc.Monitor()
+
+        global log
+        log = Logging(self.__class__.__name__).log
+
         threading.Thread.__init__(self)
-         
-    def logMsg(self, msg, lvl=1):
-        className = self.__class__.__name__
-        utils.logMsg("%s" % className, msg, lvl)
+
         
     def setUrl(self, url):
+
         self.urlToProcess = url
         
     def setHost(self, host, port):
+
         self.xbmc_host = host
         self.xbmc_port = port
         
     def setAuth(self, user, pwd):
+
         self.xbmc_username = user
         self.xbmc_password = pwd
          
     def run(self):
         
-        self.logMsg("Image Caching Thread Processing : " + self.urlToProcess, 2)
+        log("Image Caching Thread Processing: %s" % self.urlToProcess, 2)
         
         try:
             response = requests.head(
@@ -46,7 +56,5 @@ class image_cache_thread(threading.Thread):
         # We don't need the result
         except: pass
         
-        self.logMsg("Image Caching Thread Exited", 2)
-        
-        self.isFinished = True
-        
\ No newline at end of file
+        log("Image Caching Thread Exited", 2)
+        self.isFinished = True
\ No newline at end of file
diff --git a/resources/lib/initialsetup.py b/resources/lib/initialsetup.py
index 7bf0dbb9..4b1f63f3 100644
--- a/resources/lib/initialsetup.py
+++ b/resources/lib/initialsetup.py
@@ -9,10 +9,10 @@ import xbmc
 import xbmcgui
 import xbmcaddon
 
-import utils
 import clientinfo
 import downloadutils
 import userclient
+from utils import Logging, settings, language as lang, passwordsXML
 
 #################################################################################################
 
@@ -22,74 +22,67 @@ class InitialSetup():
 
     def __init__(self):
 
-        self.addon = xbmcaddon.Addon()
-        self.__language__ = self.addon.getLocalizedString
+        global log
+        log = Logging(self.__class__.__name__).log
 
         self.clientInfo = clientinfo.ClientInfo()
-        self.addonName = self.clientInfo.getAddonName()
         self.addonId = self.clientInfo.getAddonId()
         self.doUtils = downloadutils.DownloadUtils()
         self.userClient = userclient.UserClient()
-    
-    def logMsg(self, msg, lvl=1):
-
-        className = self.__class__.__name__
-        utils.logMsg("%s %s" % (self.addonName, className), msg, lvl)
 
 
     def setup(self):
         # Check server, user, direct paths, music, direct stream if not direct path.
-        string = self.__language__
         addonId = self.addonId
 
         ##### SERVER INFO #####
         
-        self.logMsg("Initial setup called.", 2)
+        log("Initial setup called.", 2)
         server = self.userClient.getServer()
 
         if server:
-            self.logMsg("Server is already set.", 2)
+            log("Server is already set.", 2)
             return
         
-        self.logMsg("Looking for server...", 2)
+        log("Looking for server...", 2)
         server = self.getServerDetails()
-        self.logMsg("Found: %s" % server, 2)
+        log("Found: %s" % server, 2)
         try:
             prefix, ip, port = server.replace("/", "").split(":")
         except: # Failed to retrieve server information
-            self.logMsg("getServerDetails failed.", 1)
+            log("getServerDetails failed.", 1)
             xbmc.executebuiltin('Addon.OpenSettings(%s)' % addonId)
             return
         else:
             server_confirm = xbmcgui.Dialog().yesno(
                                             heading="Emby for Kodi",
                                             line1="Proceed with the following server?",
-                                            line2="%s %s" % (string(30169), server))
+                                            line2="%s %s" % (lang(30169), server))
             if server_confirm:
                 # Correct server found
-                self.logMsg("Server is selected. Saving the information.", 1)
-                utils.settings('ipaddress', value=ip)
-                utils.settings('port', value=port)
+                log("Server is selected. Saving the information.", 1)
+                settings('ipaddress', value=ip)
+                settings('port', value=port)
 
                 if prefix == "https":
-                    utils.settings('https', value="true")
+                    settings('https', value="true")
             else:
                 # User selected no or cancelled the dialog
-                self.logMsg("No server selected.", 1)
+                log("No server selected.", 1)
                 xbmc.executebuiltin('Addon.OpenSettings(%s)' % addonId)
                 return
 
         ##### USER INFO #####
         
-        self.logMsg("Getting user list.", 1)
+        log("Getting user list.", 1)
         
         url = "%s/emby/Users/Public?format=json" % server
         result = self.doUtils.downloadUrl(url, authenticate=False)
         if result == "":
-            self.logMsg("Unable to connect to %s" % server, 1)
+            log("Unable to connect to %s" % server, 1)
             return
 
-        self.logMsg("Response: %s" % result, 2)
+        log("Response: %s" % result, 2)
         # Process the list of users
         usernames = []
         users_hasPassword = []
@@ -103,14 +96,14 @@ class InitialSetup():
                 name = "%s (secure)" % name
             users_hasPassword.append(name)
 
-        self.logMsg("Presenting user list: %s" % users_hasPassword, 1)
-        user_select = xbmcgui.Dialog().select(string(30200), users_hasPassword)
+        log("Presenting user list: %s" % users_hasPassword, 1)
+        user_select = xbmcgui.Dialog().select(lang(30200), users_hasPassword)
         if user_select > -1:
             selected_user = usernames[user_select]
-            self.logMsg("Selected user: %s" % selected_user, 1)
-            utils.settings('username', value=selected_user)
+            log("Selected user: %s" % selected_user, 1)
+            settings('username', value=selected_user)
         else:
-            self.logMsg("No user selected.", 1)
+            log("No user selected.", 1)
             xbmc.executebuiltin('Addon.OpenSettings(%s)' % addonId)
 
         ##### ADDITIONAL PROMPTS #####
@@ -126,8 +119,8 @@ class InitialSetup():
                             nolabel="Addon (Default)",
                             yeslabel="Native (Direct Paths)")
         if directPaths:
-            self.logMsg("User opted to use direct paths.", 1)
-            utils.settings('useDirectPaths', value="1")
+            log("User opted to use direct paths.", 1)
+            settings('useDirectPaths', value="1")
 
             # ask for credentials
             credentials = dialog.yesno(
@@ -138,15 +131,15 @@ class InitialSetup():
                                     "during the initial scan of your content if Kodi can't "
                                     "locate your content."))
             if credentials:
-                self.logMsg("Presenting network credentials dialog.", 1)
-                utils.passwordsXML()
+                log("Presenting network credentials dialog.", 1)
+                passwordsXML()
         
         musicDisabled = dialog.yesno(
                             heading="Music Library",
                             line1="Disable Emby music library?")
         if musicDisabled:
-            self.logMsg("User opted to disable Emby music library.", 1)
-            utils.settings('enableMusic', value="false")
+            log("User opted to disable Emby music library.", 1)
+            settings('enableMusic', value="false")
         else:
             # Only prompt if the user didn't select direct paths for videos
             if not directPaths:
@@ -157,12 +150,12 @@ class InitialSetup():
                                         "this option only if you plan on listening "
                                         "to music outside of your network."))
                 if musicAccess:
-                    self.logMsg("User opted to direct stream music.", 1)
-                    utils.settings('streamMusic', value="true")
+                    log("User opted to direct stream music.", 1)
+                    settings('streamMusic', value="true")
                 
     def getServerDetails(self):
 
-        self.logMsg("Getting Server Details from Network", 1)
+        log("Getting Server Details from Network", 1)
         
         MULTI_GROUP = ("<broadcast>", 7359)
         MESSAGE = "who is EmbyServer?"
@@ -176,15 +169,15 @@ class InitialSetup():
         sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)
         sock.setsockopt(socket.IPPROTO_IP, socket.SO_REUSEADDR, 1)
         
-        self.logMsg("MultiGroup      : %s" % str(MULTI_GROUP), 2)
-        self.logMsg("Sending UDP Data: %s" % MESSAGE, 2)
+        log("MultiGroup      : %s" % str(MULTI_GROUP), 2)
+        log("Sending UDP Data: %s" % MESSAGE, 2)
         sock.sendto(MESSAGE, MULTI_GROUP)
     
         try:
             data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
-            self.logMsg("Received Response: %s" % data)
+            log("Received Response: %s" % data)
         except:
-            self.logMsg("No UDP Response")
+            log("No UDP Response")
             return None
         else:
             # Get the address
diff --git a/resources/lib/kodidb_functions.py b/resources/lib/kodidb_functions.py
index 6c3dd8b1..86981e7b 100644
--- a/resources/lib/kodidb_functions.py
+++ b/resources/lib/kodidb_functions.py
@@ -7,7 +7,7 @@ import xbmc
 import api
 import artwork
 import clientinfo
-import utils
+from utils import Logging
 
 ##################################################################################################
 
@@ -19,16 +19,14 @@ class Kodidb_Functions():
 
     def __init__(self, cursor):
 
+        global log
+        log = Logging(self.__class__.__name__).log
+        
         self.cursor = cursor
         
         self.clientInfo = clientinfo.ClientInfo()
         self.addonName = self.clientInfo.getAddonName()
         self.artwork = artwork.Artwork()
-
-    def logMsg(self, msg, lvl=1):
-
-        className = self.__class__.__name__
-        utils.logMsg("%s %s" % (self.addonName, className), msg, lvl)
         
 
     def addPath(self, path):
@@ -153,7 +151,7 @@ class Kodidb_Functions():
 
                     query = "INSERT INTO country(country_id, name) values(?, ?)"
                     self.cursor.execute(query, (country_id, country))
-                    self.logMsg("Add country to media, processing: %s" % country, 2)
+                    log("Add country to media, processing: %s" % country, 2)
 
                 finally: # Assign country to content
                     query = (
@@ -187,7 +185,7 @@ class Kodidb_Functions():
 
                     query = "INSERT INTO country(idCountry, strCountry) values(?, ?)"
                     self.cursor.execute(query, (idCountry, country))
-                    self.logMsg("Add country to media, processing: %s" % country, 2)
+                    log("Add country to media, processing: %s" % country, 2)
                 
                 finally:
                     # Only movies have a country field
@@ -232,7 +230,7 @@ class Kodidb_Functions():
 
                     query = "INSERT INTO actor(actor_id, name) values(?, ?)"
                     self.cursor.execute(query, (actorid, name))
-                    self.logMsg("Add people to media, processing: %s" % name, 2)
+                    log("Add people to media, processing: %s" % name, 2)
 
                 finally:
                     # Link person to content
@@ -302,7 +300,7 @@ class Kodidb_Functions():
 
                     query = "INSERT INTO actors(idActor, strActor) values(?, ?)"
                     self.cursor.execute(query, (actorid, name))
-                    self.logMsg("Add people to media, processing: %s" % name, 2)
+                    log("Add people to media, processing: %s" % name, 2)
 
                 finally:
                     # Link person to content
@@ -462,7 +460,7 @@ class Kodidb_Functions():
                     
                     query = "INSERT INTO genre(genre_id, name) values(?, ?)"
                     self.cursor.execute(query, (genre_id, genre))
-                    self.logMsg("Add Genres to media, processing: %s" % genre, 2)
+                    log("Add Genres to media, processing: %s" % genre, 2)
                 
                 finally:
                     # Assign genre to item
@@ -507,7 +505,7 @@ class Kodidb_Functions():
 
                     query = "INSERT INTO genre(idGenre, strGenre) values(?, ?)"
                     self.cursor.execute(query, (idGenre, genre))
-                    self.logMsg("Add Genres to media, processing: %s" % genre, 2)
+                    log("Add Genres to media, processing: %s" % genre, 2)
                 
                 finally:
                     # Assign genre to item
@@ -566,7 +564,7 @@ class Kodidb_Functions():
 
                     query = "INSERT INTO studio(studio_id, name) values(?, ?)"
                     self.cursor.execute(query, (studioid, studio))
-                    self.logMsg("Add Studios to media, processing: %s" % studio, 2)
+                    log("Add Studios to media, processing: %s" % studio, 2)
 
                 finally: # Assign studio to item
                     query = (
@@ -597,7 +595,7 @@ class Kodidb_Functions():
 
                     query = "INSERT INTO studio(idstudio, strstudio) values(?, ?)"
                     self.cursor.execute(query, (studioid, studio))
-                    self.logMsg("Add Studios to media, processing: %s" % studio, 2)
+                    log("Add Studios to media, processing: %s" % studio, 2)
 
                 finally: # Assign studio to item
                     if "movie" in mediatype:
@@ -728,7 +726,7 @@ class Kodidb_Functions():
             self.cursor.execute(query, (kodiid, mediatype))
     
         # Add tags
-        self.logMsg("Adding Tags: %s" % tags, 2)
+        log("Adding Tags: %s" % tags, 2)
         for tag in tags:
             self.addTag(kodiid, tag, mediatype)
 
@@ -750,7 +748,7 @@ class Kodidb_Functions():
             except TypeError:
                 # Create the tag, because it does not exist
                 tag_id = self.createTag(tag)
-                self.logMsg("Adding tag: %s" % tag, 2)
+                log("Adding tag: %s" % tag, 2)
 
             finally:
                 # Assign tag to item
@@ -779,7 +777,7 @@ class Kodidb_Functions():
             except TypeError:
                 # Create the tag
                 tag_id = self.createTag(tag)
-                self.logMsg("Adding tag: %s" % tag, 2)
+                log("Adding tag: %s" % tag, 2)
             
             finally:
                 # Assign tag to item
@@ -815,7 +813,7 @@ class Kodidb_Functions():
 
                 query = "INSERT INTO tag(tag_id, name) values(?, ?)"
                 self.cursor.execute(query, (tag_id, name))
-                self.logMsg("Create tag_id: %s name: %s" % (tag_id, name), 2)
+                log("Create tag_id: %s name: %s" % (tag_id, name), 2)
         else:
             # Kodi Helix
             query = ' '.join((
@@ -835,13 +833,13 @@ class Kodidb_Functions():
 
                 query = "INSERT INTO tag(idTag, strTag) values(?, ?)"
                 self.cursor.execute(query, (tag_id, name))
-                self.logMsg("Create idTag: %s name: %s" % (tag_id, name), 2)
+                log("Create idTag: %s name: %s" % (tag_id, name), 2)
 
         return tag_id
 
     def updateTag(self, oldtag, newtag, kodiid, mediatype):
 
-        self.logMsg("Updating: %s with %s for %s: %s" % (oldtag, newtag, mediatype, kodiid), 2)
+        log("Updating: %s with %s for %s: %s" % (oldtag, newtag, mediatype, kodiid), 2)
         
         if self.kodiversion in (15, 16, 17):
             # Kodi Isengard, Jarvis, Krypton
@@ -858,7 +856,7 @@ class Kodidb_Functions():
             except Exception as e:
                 # The new tag we are going to apply already exists for this item
                 # delete current tag instead
-                self.logMsg("Exception: %s" % e, 1)
+                log("Exception: %s" % e, 1)
                 query = ' '.join((
 
                     "DELETE FROM tag_link",
@@ -882,7 +880,7 @@ class Kodidb_Functions():
             except Exception as e:
                 # The new tag we are going to apply already exists for this item
                 # delete current tag instead
-                self.logMsg("Exception: %s" % e, 1)
+                log("Exception: %s" % e, 1)
                 query = ' '.join((
 
                     "DELETE FROM taglinks",
@@ -943,7 +941,7 @@ class Kodidb_Functions():
 
     def createBoxset(self, boxsetname):
 
-        self.logMsg("Adding boxset: %s" % boxsetname, 2)
+        log("Adding boxset: %s" % boxsetname, 2)
         query = ' '.join((
 
             "SELECT idSet",
diff --git a/resources/lib/kodimonitor.py b/resources/lib/kodimonitor.py
index ea1a4f17..cc217de9 100644
--- a/resources/lib/kodimonitor.py
+++ b/resources/lib/kodimonitor.py
@@ -11,7 +11,7 @@ import clientinfo
 import downloadutils
 import embydb_functions as embydb
 import playbackutils as pbutils
-import utils
+from utils import Logging, window, settings, kodiSQL
 
 #################################################################################################
 
@@ -21,27 +21,25 @@ class KodiMonitor(xbmc.Monitor):
 
     def __init__(self):
 
+        global log
+        log = Logging(self.__class__.__name__).log
+
         self.clientInfo = clientinfo.ClientInfo()
         self.addonName = self.clientInfo.getAddonName()
         self.doUtils = downloadutils.DownloadUtils()
 
-        self.logMsg("Kodi monitor started.", 1)
-
-    def logMsg(self, msg, lvl=1):
-
-        self.className = self.__class__.__name__
-        utils.logMsg("%s %s" % (self.addonName, self.className), msg, lvl)
+        log("Kodi monitor started.", 1)
 
 
     def onScanStarted(self, library):
-        self.logMsg("Kodi library scan %s running." % library, 2)
+        log("Kodi library scan %s running." % library, 2)
         if library == "video":
-            utils.window('emby_kodiScan', value="true")
+            window('emby_kodiScan', value="true")
             
     def onScanFinished(self, library):
-        self.logMsg("Kodi library scan %s finished." % library, 2)
+        log("Kodi library scan %s finished." % library, 2)
         if library == "video":
-            utils.window('emby_kodiScan', clear=True)
+            window('emby_kodiScan', clear=True)
 
     def onSettingsChanged(self):
         # Monitor emby settings
@@ -50,7 +48,7 @@ class KodiMonitor(xbmc.Monitor):
         '''currentPath = utils.settings('useDirectPaths')
         if utils.window('emby_pluginpath') != currentPath:
             # Plugin path value changed. Offer to reset
-            self.logMsg("Changed to playback mode detected", 1)
+            log("Changed to playback mode detected", 1)
             utils.window('emby_pluginpath', value=currentPath)
             resp = xbmcgui.Dialog().yesno(
                                 heading="Playback mode change detected",
@@ -61,17 +59,17 @@ class KodiMonitor(xbmc.Monitor):
             if resp:
                 utils.reset()'''
 
-        currentLog = utils.settings('logLevel')
-        if utils.window('emby_logLevel') != currentLog:
+        currentLog = settings('logLevel')
+        if window('emby_logLevel') != currentLog:
             # The log level changed, set new prop
-            self.logMsg("New log level: %s" % currentLog, 1)
-            utils.window('emby_logLevel', value=currentLog)
+            log("New log level: %s" % currentLog, 1)
+            window('emby_logLevel', value=currentLog)
 
     def onNotification(self, sender, method, data):
 
         doUtils = self.doUtils
         if method not in ("Playlist.OnAdd"):
-            self.logMsg("Method: %s Data: %s" % (method, data), 1)
+            log("Method: %s Data: %s" % (method, data), 1)
             
         if data:
             data = json.loads(data,'utf-8')
@@ -84,23 +82,23 @@ class KodiMonitor(xbmc.Monitor):
                 kodiid = item['id']
                 item_type = item['type']
             except (KeyError, TypeError):
-                self.logMsg("Item is invalid for playstate update.", 1)
+                log("Item is invalid for playstate update.", 1)
             else:
-                if ((utils.settings('useDirectPaths') == "1" and not item_type == "song") or
-                        (item_type == "song" and utils.settings('enableMusic') == "true")):
+                if ((settings('useDirectPaths') == "1" and not item_type == "song") or
+                        (item_type == "song" and settings('enableMusic') == "true")):
                     # Set up properties for player
-                    embyconn = utils.kodiSQL('emby')
+                    embyconn = kodiSQL('emby')
                     embycursor = embyconn.cursor()
                     emby_db = embydb.Embydb_Functions(embycursor)
                     emby_dbitem = emby_db.getItem_byKodiId(kodiid, item_type)
                     try:
                         itemid = emby_dbitem[0]
                     except TypeError:
-                        self.logMsg("No kodiid returned.", 1)
+                        log("No kodiid returned.", 1)
                     else:
                         url = "{server}/emby/Users/{UserId}/Items/%s?format=json" % itemid
                         result = doUtils.downloadUrl(url)
-                        self.logMsg("Item: %s" % result, 2)
+                        log("Item: %s" % result, 2)
 
                         playurl = None
                         count = 0
@@ -114,12 +112,10 @@ class KodiMonitor(xbmc.Monitor):
                                 listItem = xbmcgui.ListItem()
                                 playback = pbutils.PlaybackUtils(result)
 
-                                if item_type == "song" and utils.settings('streamMusic') == "true":
-                                    utils.window('emby_%s.playmethod' % playurl,
-                                        value="DirectStream")
+                                if item_type == "song" and settings('streamMusic') == "true":
+                                    window('emby_%s.playmethod' % playurl, value="DirectStream")
                                 else:
-                                    utils.window('emby_%s.playmethod' % playurl,
-                                        value="DirectPlay")
+                                    window('emby_%s.playmethod' % playurl, value="DirectPlay")
                                 # Set properties for player.py
                                 playback.setProperties(playurl, listItem)
                     finally:
@@ -134,31 +130,31 @@ class KodiMonitor(xbmc.Monitor):
                 kodiid = item['id']
                 item_type = item['type']
             except (KeyError, TypeError):
-                self.logMsg("Item is invalid for playstate update.", 1)
+                log("Item is invalid for playstate update.", 1)
             else:
                 # Send notification to the server.
-                embyconn = utils.kodiSQL('emby')
+                embyconn = kodiSQL('emby')
                 embycursor = embyconn.cursor()
                 emby_db = embydb.Embydb_Functions(embycursor)
                 emby_dbitem = emby_db.getItem_byKodiId(kodiid, item_type)
                 try:
                     itemid = emby_dbitem[0]
                 except TypeError:
-                    self.logMsg("Could not find itemid in emby database.", 1)
+                    log("Could not find itemid in emby database.", 1)
                 else:
                     # Stop from manually marking as watched unwatched, with actual playback.
-                    if utils.window('emby_skipWatched%s' % itemid) == "true":
+                    if window('emby_skipWatched%s' % itemid) == "true":
                         # property is set in player.py
-                        utils.window('emby_skipWatched%s' % itemid, clear=True)
+                        window('emby_skipWatched%s' % itemid, clear=True)
                     else:
                         # notify the server
                         url = "{server}/emby/Users/{UserId}/PlayedItems/%s?format=json" % itemid
                         if playcount != 0:
                             doUtils.downloadUrl(url, action_type="POST")
-                            self.logMsg("Mark as watched for itemid: %s" % itemid, 1)
+                            log("Mark as watched for itemid: %s" % itemid, 1)
                         else:
                             doUtils.downloadUrl(url, action_type="DELETE")
-                            self.logMsg("Mark as unwatched for itemid: %s" % itemid, 1)
+                            log("Mark as unwatched for itemid: %s" % itemid, 1)
                 finally:
                     embycursor.close()
 
@@ -172,7 +168,7 @@ class KodiMonitor(xbmc.Monitor):
                 kodiid = data['id']
                 type = data['type']
             except (KeyError, TypeError):
-                self.logMsg("Item is invalid for emby deletion.", 1)
+                log("Item is invalid for emby deletion.", 1)
             else:
                 # Send the delete action to the server.
                 embyconn = utils.kodiSQL('emby')
@@ -182,19 +178,19 @@ class KodiMonitor(xbmc.Monitor):
                 try:
                     itemid = emby_dbitem[0]
                 except TypeError:
-                    self.logMsg("Could not find itemid in emby database.", 1)
+                    log("Could not find itemid in emby database.", 1)
                 else:
                     if utils.settings('skipContextMenu') != "true":
                         resp = xbmcgui.Dialog().yesno(
                                                 heading="Confirm delete",
                                                 line1="Delete file on Emby Server?")
                         if not resp:
-                            self.logMsg("User skipped deletion.", 1)
+                            log("User skipped deletion.", 1)
                             embycursor.close()
                             return
 
                     url = "{server}/emby/Items/%s?format=json" % itemid
-                    self.logMsg("Deleting request: %s" % itemid)
+                    log("Deleting request: %s" % itemid)
                     doUtils.downloadUrl(url, action_type="DELETE")
                 finally:
                     embycursor.close()'''
@@ -203,13 +199,13 @@ class KodiMonitor(xbmc.Monitor):
         elif method == "System.OnWake":
             # Allow network to wake up
             xbmc.sleep(10000)
-            utils.window('emby_onWake', value="true")
+            window('emby_onWake', value="true")
 
 
         elif method == "GUI.OnScreensaverDeactivated":
-            if utils.settings('dbSyncScreensaver') == "true":
+            if settings('dbSyncScreensaver') == "true":
                 xbmc.sleep(5000);
-                utils.window('emby_onWake', value="true")
+                window('emby_onWake', value="true")
 
 
         elif method == "Playlist.OnClear":
diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py
index 1335f585..6d047148 100644
--- a/resources/lib/librarysync.py
+++ b/resources/lib/librarysync.py
@@ -20,6 +20,7 @@ import kodidb_functions as kodidb
 import read_embyserver as embyserver
 import userclient
 import videonodes
+from utils import Logging, window, settings, language as lang
 
 ##################################################################################################
 
@@ -42,6 +43,9 @@ class LibrarySync(threading.Thread):
 
     def __init__(self):
 
+        global log
+        log = Logging(self.__class__.__name__).log
+
         self.__dict__ = self._shared_state
         self.monitor = xbmc.Monitor()
 
@@ -54,26 +58,20 @@ class LibrarySync(threading.Thread):
 
         threading.Thread.__init__(self)
 
-    def logMsg(self, msg, lvl=1):
-
-        className = self.__class__.__name__
-        utils.logMsg("%s %s" % (self.addonName, className), msg, lvl)
-
 
     def progressDialog(self, title, forced=False):
 
         dialog = None
 
-        if utils.settings('dbSyncIndicator') == "true" or forced:
+        if settings('dbSyncIndicator') == "true" or forced:
             dialog = xbmcgui.DialogProgressBG()
             dialog.create("Emby for Kodi", title)
-            self.logMsg("Show progress dialog: %s" % title, 2)
+            log("Show progress dialog: %s" % title, 2)
 
         return dialog
 
     def startSync(self):
 
-        settings = utils.settings
         # Run at start up - optional to use the server plugin
         if settings('SyncInstallRunDone') == "true":
 
@@ -88,7 +86,7 @@ class LibrarySync(threading.Thread):
 
                 for plugin in result:
                     if plugin['Name'] == "Emby.Kodi Sync Queue":
-                        self.logMsg("Found server plugin.", 2)
+                        log("Found server plugin.", 2)
                         completed = self.fastSync()
                         break
 
@@ -103,37 +101,31 @@ class LibrarySync(threading.Thread):
 
     def fastSync(self):
 
-        lastSync = utils.settings('LastIncrementalSync')
+        lastSync = settings('LastIncrementalSync')
         if not lastSync:
             lastSync = "2010-01-01T00:00:00Z"
 
-        lastSyncTime = utils.convertdate(lastSync)
-        self.logMsg("Last sync run: %s" % lastSyncTime, 1)
+        lastSyncTime = utils.convertDate(lastSync)
+        log("Last sync run: %s" % lastSyncTime, 1)
 
         # get server RetentionDateTime
         result = self.doUtils("{server}/emby/Emby.Kodi.SyncQueue/GetServerDateTime?format=json")
-        retention_time = "2010-01-01T00:00:00Z"
-        if result and result.get('RetentionDateTime'):
-            retention_time = result['RetentionDateTime']
-
-        #Try/except equivalent
-        '''
         try:
             retention_time = result['RetentionDateTime']
         except (TypeError, KeyError):
             retention_time = "2010-01-01T00:00:00Z"
-        '''
 
-        retention_time = utils.convertdate(retention_time)
-        self.logMsg("RetentionDateTime: %s" % retention_time, 1)
+        retention_time = utils.convertDate(retention_time)
+        log("RetentionDateTime: %s" % retention_time, 1)
 
         # if last sync before retention time do a full sync
         if retention_time > lastSyncTime:
-            self.logMsg("Fast sync server retention insufficient, fall back to full sync", 1)
+            log("Fast sync server retention insufficient, fall back to full sync", 1)
             return False
 
         params = {'LastUpdateDT': lastSync}
-        result = self.doUtils("{server}/emby/Emby.Kodi.SyncQueue/{UserId}/GetItems?format=json", parameters=params)
+        url = "{server}/emby/Emby.Kodi.SyncQueue/{UserId}/GetItems?format=json"
+        result = self.doUtils(url, parameters=params)
 
         try:
             processlist = {
@@ -145,11 +137,11 @@ class LibrarySync(threading.Thread):
             }
 
         except (KeyError, TypeError):
-            self.logMsg("Failed to retrieve latest updates using fast sync.", 1)
+            log("Failed to retrieve latest updates using fast sync.", 1)
             return False
 
         else:
-            self.logMsg("Fast sync changes: %s" % result, 1)
+            log("Fast sync changes: %s" % result, 1)
             for action in processlist:
                 self.triage_items(action, processlist[action])
 
@@ -163,60 +155,55 @@ class LibrarySync(threading.Thread):
         result = self.doUtils("{server}/emby/Emby.Kodi.SyncQueue/GetServerDateTime?format=json")
         try: # datetime fails when used more than once, TypeError
             server_time = result['ServerDateTime']
-            server_time = utils.convertdate(server_time)
+            server_time = utils.convertDate(server_time)
 
         except Exception as e:
             # If the server plugin is not installed or an error happened.
-            self.logMsg("An exception occurred: %s" % e, 1)
+            log("An exception occurred: %s" % e, 1)
             time_now = datetime.utcnow()-timedelta(minutes=overlap)
             lastSync = time_now.strftime('%Y-%m-%dT%H:%M:%SZ')
-            self.logMsg("New sync time: client time -%s min: %s" % (overlap, lastSync), 1)
+            log("New sync time: client time -%s min: %s" % (overlap, lastSync), 1)
 
         else:
             lastSync = (server_time - timedelta(minutes=overlap)).strftime('%Y-%m-%dT%H:%M:%SZ')
-            self.logMsg("New sync time: server time -%s min: %s" % (overlap, lastSync), 1)
+            log("New sync time: server time -%s min: %s" % (overlap, lastSync), 1)
 
         finally:
-            utils.settings('LastIncrementalSync', value=lastSync)
+            settings('LastIncrementalSync', value=lastSync)
 
     def shouldStop(self):
         # Checkpoint during the syncing process
         if self.monitor.abortRequested():
             return True
-        elif utils.window('emby_shouldStop') == "true":
+        elif window('emby_shouldStop') == "true":
             return True
         else: # Keep going
             return False
 
     def dbCommit(self, connection):
-
-        window = utils.window
         # Central commit, verifies if Kodi database update is running
         kodidb_scan = window('emby_kodiScan') == "true"
 
         while kodidb_scan:
 
-            self.logMsg("Kodi scan is running. Waiting...", 1)
+            log("Kodi scan is running. Waiting...", 1)
             kodidb_scan = window('emby_kodiScan') == "true"
 
             if self.shouldStop():
-                self.logMsg("Commit unsuccessful. Sync terminated.", 1)
+                log("Commit unsuccessful. Sync terminated.", 1)
                 break
 
             if self.monitor.waitForAbort(1):
                 # Abort was requested while waiting. We should exit
-                self.logMsg("Commit unsuccessful.", 1)
+                log("Commit unsuccessful.", 1)
                 break
         else:
             connection.commit()
-            self.logMsg("Commit successful.", 1)
+            log("Commit successful.", 1)
 
     def fullSync(self, manualrun=False, repair=False, forceddialog=False):
-
-        window = utils.window
-        settings = utils.settings
         # Only run once when first setting up. Can be run manually.
-        music_enabled = utils.settings('enableMusic') == "true"
+        music_enabled = settings('enableMusic') == "true"
 
         xbmc.executebuiltin('InhibitIdleShutdown(true)')
         screensaver = utils.getScreensaver()
@@ -284,7 +271,7 @@ class LibrarySync(threading.Thread):
                 self.dbCommit(kodiconn)
                 embyconn.commit()
                 elapsedTime = datetime.now() - startTime
-                self.logMsg("SyncDatabase (finished %s in: %s)"
+                log("SyncDatabase (finished %s in: %s)"
                     % (itemtype, str(elapsedTime).split('.')[0]), 1)
         else:
             # Close the Kodi cursor
@@ -312,7 +299,7 @@ class LibrarySync(threading.Thread):
                 musicconn.commit()
                 embyconn.commit()
                 elapsedTime = datetime.now() - startTime
-                self.logMsg("SyncDatabase (finished music in: %s)"
+                log("SyncDatabase (finished music in: %s)"
                     % (str(elapsedTime).split('.')[0]), 1)
             musiccursor.close()
 
@@ -335,7 +322,7 @@ class LibrarySync(threading.Thread):
             xbmcgui.Dialog().notification(
                         heading="Emby for Kodi",
                         message="%s %s %s" %
-                                (message, utils.language(33025), str(elapsedtotal).split('.')[0]),
+                                (message, lang(33025), str(elapsedtotal).split('.')[0]),
                         icon="special://home/addons/plugin.video.emby/icon.png",
                         sound=False)
         return True
@@ -378,7 +365,7 @@ class LibrarySync(threading.Thread):
             if view['type'] == "mixed":
                 sorted_views.append(view['name'])
             sorted_views.append(view['name'])
-        self.logMsg("Sorted views: %s" % sorted_views, 1)
+        log("Sorted views: %s" % sorted_views, 1)
 
         # total nodes for window properties
         self.vnodes.clearProperties()
@@ -415,7 +402,8 @@ class LibrarySync(threading.Thread):
                         'Limit': 1,
                         'IncludeItemTypes': emby_mediatypes[mediatype]
                     } # Get one item from server using the folderid
-                    result = self.doUtils("{server}/emby/Users/{UserId}/Items?format=json", parameters=params)
+                    url = "{server}/emby/Users/{UserId}/Items?format=json"
+                    result = self.doUtils(url, parameters=params)
                     try:
                         verifyitem = result['Items'][0]['Id']
                     except (TypeError, IndexError):
@@ -430,14 +418,14 @@ class LibrarySync(threading.Thread):
                                 # Take the userview, and validate the item belong to the view
                                 if self.emby.verifyView(grouped_view['Id'], verifyitem):
                                     # Take the name of the userview
-                                    self.logMsg("Found corresponding view: %s %s"
+                                    log("Found corresponding view: %s %s"
                                         % (grouped_view['Name'], grouped_view['Id']), 1)
                                     foldername = grouped_view['Name']
                                     break
                         else:
                             # Unable to find a match, add the name to our sorted_view list
                             sorted_views.append(foldername)
-                            self.logMsg("Couldn't find corresponding grouped view: %s" % sorted_views, 1)
+                            log("Couldn't find corresponding grouped view: %s" % sorted_views, 1)
 
                 # Failsafe
                 try:
@@ -453,7 +441,7 @@ class LibrarySync(threading.Thread):
                     current_tagid = view[2]
 
                 except TypeError:
-                    self.logMsg("Creating viewid: %s in Emby database." % folderid, 1)
+                    log("Creating viewid: %s in Emby database." % folderid, 1)
                     tagid = kodi_db.createTag(foldername)
                     # Create playlist for the video library
                     if (foldername not in playlists and
@@ -472,7 +460,7 @@ class LibrarySync(threading.Thread):
                     emby_db.addView(folderid, foldername, viewtype, tagid)
 
                 else:
-                    self.logMsg(' '.join((
+                    log(' '.join((
 
                         "Found viewid: %s" % folderid,
                         "viewname: %s" % current_viewname,
@@ -488,7 +476,7 @@ class LibrarySync(threading.Thread):
 
                     # View was modified, update with latest info
                     if current_viewname != foldername:
-                        self.logMsg("viewid: %s new viewname: %s" % (folderid, foldername), 1)
+                        log("viewid: %s new viewname: %s" % (folderid, foldername), 1)
                         tagid = kodi_db.createTag(foldername)
 
                         # Update view with new info
@@ -556,20 +544,19 @@ class LibrarySync(threading.Thread):
             utils.window('Emby.nodes.total', str(totalnodes))
 
             # Remove any old referenced views
-            self.logMsg("Removing views: %s" % current_views, 1)
+            log("Removing views: %s" % current_views, 1)
             for view in current_views:
                 emby_db.removeView(view)
 
     def movies(self, embycursor, kodicursor, pdialog):
 
-        lang = utils.language
         # Get movies from emby
         emby_db = embydb.Embydb_Functions(embycursor)
         movies = itemtypes.Movies(embycursor, kodicursor)
 
         views = emby_db.getView_byType('movies')
         views += emby_db.getView_byType('mixed')
-        self.logMsg("Media folders: %s" % views, 1)
+        log("Media folders: %s" % views, 1)
 
         ##### PROCESS MOVIES #####
         for view in views:
@@ -604,7 +591,7 @@ class LibrarySync(threading.Thread):
                     count += 1
                 movies.add_update(embymovie, view['name'], view['id'])
         else:
-            self.logMsg("Movies finished.", 2)
+            log("Movies finished.", 2)
 
 
         ##### PROCESS BOXSETS #####
@@ -631,7 +618,7 @@ class LibrarySync(threading.Thread):
                 count += 1
             movies.add_updateBoxset(boxset)
         else:
-            self.logMsg("Boxsets finished.", 2)
+            log("Boxsets finished.", 2)
 
         return True
 
@@ -642,7 +629,7 @@ class LibrarySync(threading.Thread):
         mvideos = itemtypes.MusicVideos(embycursor, kodicursor)
 
         views = emby_db.getView_byType('musicvideos')
-        self.logMsg("Media folders: %s" % views, 1)
+        log("Media folders: %s" % views, 1)
 
         for view in views:
 
@@ -656,7 +643,7 @@ class LibrarySync(threading.Thread):
             if pdialog:
                 pdialog.update(
                         heading="Emby for Kodi",
-                        message="%s %s..." % (utils.language(33019), viewName))
+                        message="%s %s..." % (lang(33019), viewName))
 
             # Initial or repair sync
             all_embymvideos = self.emby.getMusicVideos(viewId, dialog=pdialog)
@@ -679,7 +666,7 @@ class LibrarySync(threading.Thread):
                     count += 1
                 mvideos.add_update(embymvideo, viewName, viewId)
         else:
-            self.logMsg("MusicVideos finished.", 2)
+            log("MusicVideos finished.", 2)
 
         return True
 
@@ -691,7 +678,7 @@ class LibrarySync(threading.Thread):
 
         views = emby_db.getView_byType('tvshows')
         views += emby_db.getView_byType('mixed')
-        self.logMsg("Media folders: %s" % views, 1)
+        log("Media folders: %s" % views, 1)
 
         for view in views:
 
@@ -702,7 +689,7 @@ class LibrarySync(threading.Thread):
             if pdialog:
                 pdialog.update(
                         heading="Emby for Kodi",
-                        message="%s %s..." % (utils.language(33020), view['name']))
+                        message="%s %s..." % (lang(33020), view['name']))
 
             all_embytvshows = self.emby.getShows(view['id'], dialog=pdialog)
             total = all_embytvshows['TotalRecordCount']
@@ -737,7 +724,7 @@ class LibrarySync(threading.Thread):
                         pdialog.update(percentage, message="%s - %s" % (title, episodetitle))
                     tvshows.add_updateEpisode(episode)
         else:
-            self.logMsg("TVShows finished.", 2)
+            log("TVShows finished.", 2)
 
         return True
 
@@ -757,7 +744,7 @@ class LibrarySync(threading.Thread):
             if pdialog:
                 pdialog.update(
                     heading="Emby for Kodi",
-                    message="%s %s..." % (utils.language(33021), itemtype))
+                    message="%s %s..." % (lang(33021), itemtype))
 
             all_embyitems = process[itemtype][0](dialog=pdialog)
             total = all_embyitems['TotalRecordCount']
@@ -778,7 +765,7 @@ class LibrarySync(threading.Thread):
 
                 process[itemtype][1](embyitem)
             else:
-                self.logMsg("%s finished." % itemtype, 2)
+                log("%s finished." % itemtype, 2)
 
         return True
 
@@ -799,7 +786,7 @@ class LibrarySync(threading.Thread):
                     itemids.append(item['ItemId'])
                 items = itemids
 
-            self.logMsg("Queue %s: %s" % (process, items), 1)
+            log("Queue %s: %s" % (process, items), 1)
             processlist[process].extend(items)
 
     def incrementalSync(self):
@@ -833,7 +820,7 @@ class LibrarySync(threading.Thread):
         }
         for process_type in ['added', 'update', 'userdata', 'remove']:
 
-            if process[process_type] and utils.window('emby_kodiScan') != "true":
+            if process[process_type] and window('emby_kodiScan') != "true":
 
                 listItems = list(process[process_type])
                 del process[process_type][:] # Reset class list
@@ -871,7 +858,7 @@ class LibrarySync(threading.Thread):
 
         if update_embydb:
             update_embydb = False
-            self.logMsg("Updating emby database.", 1)
+            log("Updating emby database.", 1)
             embyconn.commit()
             self.saveLastSync()
 
@@ -880,8 +867,8 @@ class LibrarySync(threading.Thread):
             self.forceLibraryUpdate = False
             self.dbCommit(kodiconn)
 
-            self.logMsg("Updating video library.", 1)
-            utils.window('emby_kodiScan', value="true")
+            log("Updating video library.", 1)
+            window('emby_kodiScan', value="true")
             xbmc.executebuiltin('UpdateLibrary(video)')
 
         if pDialog:
@@ -893,7 +880,7 @@ class LibrarySync(threading.Thread):
 
     def compareDBVersion(self, current, minimum):
         # It returns True is database is up to date. False otherwise.
-        self.logMsg("current: %s minimum: %s" % (current, minimum), 1)
+        log("current: %s minimum: %s" % (current, minimum), 1)
         currMajor, currMinor, currPatch = current.split(".")
         minMajor, minMinor, minPatch = minimum.split(".")
 
@@ -911,7 +898,7 @@ class LibrarySync(threading.Thread):
         try:
             self.run_internal()
         except Exception as e:
-            utils.window('emby_dbScan', clear=True)
+            window('emby_dbScan', clear=True)
             xbmcgui.Dialog().ok(
                         heading="Emby for Kodi",
                         line1=(
@@ -922,14 +909,11 @@ class LibrarySync(threading.Thread):
 
     def run_internal(self):
 
-        lang = utils.language
-        window = utils.window
-        settings = utils.settings
         dialog = xbmcgui.Dialog()
 
         startupComplete = False
 
-        self.logMsg("---===### Starting LibrarySync ###===---", 0)
+        log("---===### Starting LibrarySync ###===---", 0)
 
         while not self.monitor.abortRequested():
 
@@ -947,12 +931,12 @@ class LibrarySync(threading.Thread):
                 uptoDate = self.compareDBVersion(currentVersion, minVersion)
 
                 if not uptoDate:
-                    self.logMsg("Database version out of date: %s minimum version required: %s"
+                    log("Database version out of date: %s minimum version required: %s"
                         % (currentVersion, minVersion), 0)
 
                     resp = dialog.yesno("Emby for Kodi", lang(33022))
                     if not resp:
-                        self.logMsg("Database version is out of date! USER IGNORED!", 0)
+                        log("Database version is out of date! USER IGNORED!", 0)
                         dialog.ok("Emby for Kodi", lang(33023))
                     else:
                         utils.reset()
@@ -967,7 +951,7 @@ class LibrarySync(threading.Thread):
                 videoDb = utils.getKodiVideoDBPath()
                 if not xbmcvfs.exists(videoDb):
                     # Database does not exists
-                    self.logMsg(
+                    log(
                         "The current Kodi version is incompatible "
                         "with the Emby for Kodi add-on. Please visit "
                         "https://github.com/MediaBrowser/Emby.Kodi/wiki "
@@ -979,12 +963,12 @@ class LibrarySync(threading.Thread):
                     break
 
                 # Run start up sync
-                self.logMsg("Database version: %s" % settings('dbCreatedWithVersion'), 0)
-                self.logMsg("SyncDatabase (started)", 1)
+                log("Database version: %s" % settings('dbCreatedWithVersion'), 0)
+                log("SyncDatabase (started)", 1)
                 startTime = datetime.now()
                 librarySync = self.startSync()
                 elapsedTime = datetime.now() - startTime
-                self.logMsg("SyncDatabase (finished in: %s) %s"
+                log("SyncDatabase (finished in: %s) %s"
                     % (str(elapsedTime).split('.')[0], librarySync), 1)
                 # Only try the initial sync once per kodi session regardless
                 # This will prevent an infinite loop in case something goes wrong.
@@ -999,32 +983,32 @@ class LibrarySync(threading.Thread):
                 # Set in kodimonitor.py
                 window('emby_onWake', clear=True)
                 if window('emby_syncRunning') != "true":
-                    self.logMsg("SyncDatabase onWake (started)", 0)
+                    log("SyncDatabase onWake (started)", 0)
                     librarySync = self.startSync()
-                    self.logMsg("SyncDatabase onWake (finished) %s" % librarySync, 0)
+                    log("SyncDatabase onWake (finished) %s" % librarySync, 0)
 
             if self.stop_thread:
                 # Set in service.py
-                self.logMsg("Service terminated thread.", 2)
+                log("Service terminated thread.", 2)
                 break
 
             if self.monitor.waitForAbort(1):
                 # Abort was requested while waiting. We should exit
                 break
 
-        self.logMsg("###===--- LibrarySync Stopped ---===###", 0)
+        log("###===--- LibrarySync Stopped ---===###", 0)
 
     def stopThread(self):
         self.stop_thread = True
-        self.logMsg("Ending thread...", 2)
+        log("Ending thread...", 2)
 
     def suspendThread(self):
         self.suspend_thread = True
-        self.logMsg("Pausing thread...", 0)
+        log("Pausing thread...", 0)
 
     def resumeThread(self):
         self.suspend_thread = False
-        self.logMsg("Resuming thread...", 0)
+        log("Resuming thread...", 0)
 
 
 class ManualSync(LibrarySync):
@@ -1041,14 +1025,13 @@ class ManualSync(LibrarySync):
 
     def movies(self, embycursor, kodicursor, pdialog):
 
-        lang = utils.language
         # Get movies from emby
         emby_db = embydb.Embydb_Functions(embycursor)
         movies = itemtypes.Movies(embycursor, kodicursor)
 
         views = emby_db.getView_byType('movies')
         views += emby_db.getView_byType('mixed')
-        self.logMsg("Media folders: %s" % views, 1)
+        log("Media folders: %s" % views, 1)
 
         # Pull the list of movies and boxsets in Kodi
         try:
@@ -1095,7 +1078,7 @@ class ManualSync(LibrarySync):
                     # Only update if movie is not in Kodi or checksum is different
                     updatelist.append(itemid)
 
-            self.logMsg("Movies to update for %s: %s" % (viewName, updatelist), 1)
+            log("Movies to update for %s: %s" % (viewName, updatelist), 1)
             embymovies = self.emby.getFullItems(updatelist)
             total = len(updatelist)
             del updatelist[:]
@@ -1137,7 +1120,7 @@ class ManualSync(LibrarySync):
                 updatelist.append(itemid)
                 embyboxsets.append(boxset)
 
-        self.logMsg("Boxsets to update: %s" % updatelist, 1)
+        log("Boxsets to update: %s" % updatelist, 1)
         total = len(updatelist)
 
         if pdialog:
@@ -1161,13 +1144,13 @@ class ManualSync(LibrarySync):
             if kodimovie not in all_embymoviesIds:
                 movies.remove(kodimovie)
         else:
-            self.logMsg("Movies compare finished.", 1)
+            log("Movies compare finished.", 1)
 
         for boxset in all_kodisets:
             if boxset not in all_embyboxsetsIds:
                 movies.remove(boxset)
         else:
-            self.logMsg("Boxsets compare finished.", 1)
+            log("Boxsets compare finished.", 1)
 
         return True
 
@@ -1178,7 +1161,7 @@ class ManualSync(LibrarySync):
         mvideos = itemtypes.MusicVideos(embycursor, kodicursor)
 
         views = emby_db.getView_byType('musicvideos')
-        self.logMsg("Media folders: %s" % views, 1)
+        log("Media folders: %s" % views, 1)
 
         # Pull the list of musicvideos in Kodi
         try:
@@ -1201,7 +1184,7 @@ class ManualSync(LibrarySync):
             if pdialog:
                 pdialog.update(
                         heading="Emby for Kodi",
-                        message="%s %s..." % (utils.language(33028), viewName))
+                        message="%s %s..." % (lang(33028), viewName))
 
             all_embymvideos = self.emby.getMusicVideos(viewId, basic=True, dialog=pdialog)
             for embymvideo in all_embymvideos['Items']:
@@ -1218,7 +1201,7 @@ class ManualSync(LibrarySync):
                     # Only update if musicvideo is not in Kodi or checksum is different
                     updatelist.append(itemid)
 
-            self.logMsg("MusicVideos to update for %s: %s" % (viewName, updatelist), 1)
+            log("MusicVideos to update for %s: %s" % (viewName, updatelist), 1)
             embymvideos = self.emby.getFullItems(updatelist)
             total = len(updatelist)
             del updatelist[:]
@@ -1245,20 +1228,19 @@ class ManualSync(LibrarySync):
             if kodimvideo not in all_embymvideosIds:
                 mvideos.remove(kodimvideo)
         else:
-            self.logMsg("MusicVideos compare finished.", 1)
+            log("MusicVideos compare finished.", 1)
 
         return True
 
     def tvshows(self, embycursor, kodicursor, pdialog):
 
-        lang = utils.language
         # Get shows from emby
         emby_db = embydb.Embydb_Functions(embycursor)
         tvshows = itemtypes.TVShows(embycursor, kodicursor)
 
         views = emby_db.getView_byType('tvshows')
         views += emby_db.getView_byType('mixed')
-        self.logMsg("Media folders: %s" % views, 1)
+        log("Media folders: %s" % views, 1)
 
         # Pull the list of tvshows and episodes in Kodi
         try:
@@ -1305,7 +1287,7 @@ class ManualSync(LibrarySync):
                     # Only update if movie is not in Kodi or checksum is different
                     updatelist.append(itemid)
 
-            self.logMsg("TVShows to update for %s: %s" % (viewName, updatelist), 1)
+            log("TVShows to update for %s: %s" % (viewName, updatelist), 1)
             embytvshows = self.emby.getFullItems(updatelist)
             total = len(updatelist)
             del updatelist[:]
@@ -1349,7 +1331,7 @@ class ManualSync(LibrarySync):
                         # Only update if movie is not in Kodi or checksum is different
                         updatelist.append(itemid)
 
-                self.logMsg("Episodes to update for %s: %s" % (viewName, updatelist), 1)
+                log("Episodes to update for %s: %s" % (viewName, updatelist), 1)
                 embyepisodes = self.emby.getFullItems(updatelist)
                 total = len(updatelist)
                 del updatelist[:]
@@ -1374,13 +1356,13 @@ class ManualSync(LibrarySync):
             if koditvshow not in all_embytvshowsIds:
                 tvshows.remove(koditvshow)
         else:
-            self.logMsg("TVShows compare finished.", 1)
+            log("TVShows compare finished.", 1)
 
         for kodiepisode in all_kodiepisodes:
             if kodiepisode not in all_embyepisodesIds:
                 tvshows.remove(kodiepisode)
         else:
-            self.logMsg("Episodes compare finished.", 1)
+            log("Episodes compare finished.", 1)
 
         return True
 
@@ -1421,7 +1403,7 @@ class ManualSync(LibrarySync):
             if pdialog:
                 pdialog.update(
                         heading="Emby for Kodi",
-                        message="%s %s..." % (utils.language(33031), data_type))
+                        message="%s %s..." % (lang(33031), data_type))
             if data_type != "artists":
                 all_embyitems = process[data_type][0](basic=True, dialog=pdialog)
             else:
@@ -1446,7 +1428,7 @@ class ManualSync(LibrarySync):
                     if all_kodisongs.get(itemid) != API.getChecksum():
                         # Only update if songs is not in Kodi or checksum is different
                         updatelist.append(itemid)
-            self.logMsg("%s to update: %s" % (data_type, updatelist), 1)
+            log("%s to update: %s" % (data_type, updatelist), 1)
             embyitems = self.emby.getFullItems(updatelist)
             total = len(updatelist)
             del updatelist[:]
@@ -1467,15 +1449,15 @@ class ManualSync(LibrarySync):
             if kodiartist not in all_embyartistsIds and all_kodiartists[kodiartist] is not None:
                 music.remove(kodiartist)
         else:
-            self.logMsg("Artist compare finished.", 1)
+            log("Artist compare finished.", 1)
         for kodialbum in all_kodialbums:
             if kodialbum not in all_embyalbumsIds:
                 music.remove(kodialbum)
         else:
-            self.logMsg("Albums compare finished.", 1)
+            log("Albums compare finished.", 1)
         for kodisong in all_kodisongs:
             if kodisong not in all_embysongsIds:
                 music.remove(kodisong)
         else:
-            self.logMsg("Songs compare finished.", 1)
-        return True
+            log("Songs compare finished.", 1)
+        return True
\ No newline at end of file
diff --git a/resources/lib/musicutils.py b/resources/lib/musicutils.py
index b058c5c5..dd44e830 100644
--- a/resources/lib/musicutils.py
+++ b/resources/lib/musicutils.py
@@ -14,20 +14,18 @@ from mutagen import id3
 import base64
 
 import read_embyserver as embyserver
-import utils
+from utils import Logging, window
 
 #################################################################################################
 
 # Helper for the music library, intended to fix missing song ID3 tags on Emby
-
-def logMsg(msg, lvl=1):
-    utils.logMsg("%s %s" % ("Emby", "musictools"), msg, lvl)
+log = Logging('MusicTools').log
 
 def getRealFileName(filename, isTemp=False):
     #get the filename path accessible by python if possible...
     
     if not xbmcvfs.exists(filename):
-        logMsg( "File does not exist! %s" %(filename), 0)
+        log("File does not exist! %s" % filename, 0)
         return (False, "")
     
     #if we use os.path method on older python versions (sunch as some android builds), we need to pass arguments as string
@@ -104,7 +102,7 @@ def getAdditionalSongTags(embyid, emby_rating, API, kodicursor, emby_db, enablei
     elif file_rating is None and not currentvalue:
         return (emby_rating, comment, False)
     
-    logMsg("getAdditionalSongTags --> embyid: %s - emby_rating: %s - file_rating: %s - current rating in kodidb: %s" %(embyid, emby_rating, file_rating, currentvalue))
+    log("getAdditionalSongTags --> embyid: %s - emby_rating: %s - file_rating: %s - current rating in kodidb: %s" %(embyid, emby_rating, file_rating, currentvalue))
     
     updateFileRating = False
     updateEmbyRating = False
@@ -171,7 +169,7 @@ def getAdditionalSongTags(embyid, emby_rating, API, kodicursor, emby_db, enablei
     if updateEmbyRating and enableexportsongrating:
         # sync details to emby server. Translation needed between ID3 rating and emby likes/favourites:
         like, favourite, deletelike = getEmbyRatingFromKodiRating(rating)
-        utils.window("ignore-update-%s" %embyid, "true") #set temp windows prop to ignore the update from webclient update
+        window("ignore-update-%s" %embyid, "true") #set temp windows prop to ignore the update from webclient update
         emby.updateUserRating(embyid, like, favourite, deletelike)
     
     return (rating, comment, hasEmbeddedCover)
@@ -183,7 +181,7 @@ def getSongTags(file):
     hasEmbeddedCover = False
     
     isTemp,filename = getRealFileName(file)
-    logMsg( "getting song ID3 tags for " + filename)
+    log( "getting song ID3 tags for " + filename)
     
     try:
         ###### FLAC FILES #############
@@ -217,14 +215,14 @@ def getSongTags(file):
                     #POPM rating is 0-255 and needs to be converted to 0-5 range
                     if rating > 5: rating = (rating / 255) * 5
         else:
-            logMsg( "Not supported fileformat or unable to access file: %s" %(filename))
+            log( "Not supported fileformat or unable to access file: %s" %(filename))
         
         #the rating must be a round value
         rating = int(round(rating,0))
     
     except Exception as e:
         #file in use ?
-        utils.logMsg("Exception in getSongTags", str(e),0)
+        log("Exception in getSongTags", str(e),0)
         rating = None
     
     #remove tempfile if needed....
@@ -246,7 +244,7 @@ def updateRatingToFile(rating, file):
     xbmcvfs.copy(file, tempfile)
     tempfile = xbmc.translatePath(tempfile).decode("utf-8")
     
-    logMsg( "setting song rating: %s for filename: %s - using tempfile: %s" %(rating,file,tempfile))
+    log( "setting song rating: %s for filename: %s - using tempfile: %s" %(rating,file,tempfile))
     
     if not tempfile:
         return
@@ -263,7 +261,7 @@ def updateRatingToFile(rating, file):
             audio.add(id3.POPM(email="Windows Media Player 9 Series", rating=calcrating, count=1))
             audio.save()
         else:
-            logMsg( "Not supported fileformat: %s" %(tempfile))
+            log( "Not supported fileformat: %s" %(tempfile))
             
         #once we have succesfully written the flags we move the temp file to destination, otherwise not proceeding and just delete the temp
         #safety check: we check the file size of the temp file before proceeding with overwite of original file
@@ -274,14 +272,14 @@ def updateRatingToFile(rating, file):
             xbmcvfs.delete(file)
             xbmcvfs.copy(tempfile,file)
         else:
-            logMsg( "Checksum mismatch for filename: %s - using tempfile: %s  -  not proceeding with file overwite!" %(rating,file,tempfile))
+            log( "Checksum mismatch for filename: %s - using tempfile: %s  -  not proceeding with file overwite!" %(rating,file,tempfile))
         
         #always delete the tempfile
         xbmcvfs.delete(tempfile)
             
     except Exception as e:
         #file in use ?
-        logMsg("Exception in updateRatingToFile %s" %e,0)
+        log("Exception in updateRatingToFile %s" %e,0)
         
     
     
\ No newline at end of file
diff --git a/resources/lib/player.py b/resources/lib/player.py
index 7f323460..1cc187bb 100644
--- a/resources/lib/player.py
+++ b/resources/lib/player.py
@@ -7,11 +7,11 @@ import json
 import xbmc
 import xbmcgui
 
-import utils
 import clientinfo
 import downloadutils
 import kodidb_functions as kodidb
 import websocket_client as wsc
+from utils import Logging, window, settings, language as lang
 
 #################################################################################################
 
@@ -28,6 +28,9 @@ class Player(xbmc.Player):
 
     def __init__(self):
 
+        global log
+        log = Logging(self.__class__.__name__).log
+
         self.__dict__ = self._shared_state
 
         self.clientInfo = clientinfo.ClientInfo()
@@ -36,20 +39,13 @@ class Player(xbmc.Player):
         self.ws = wsc.WebSocket_Client()
         self.xbmcplayer = xbmc.Player()
 
-        self.logMsg("Starting playback monitor.", 2)
-
-    def logMsg(self, msg, lvl=1):
-        
-        self.className = self.__class__.__name__
-        utils.logMsg("%s %s" % (self.addonName, self.className), msg, lvl)
+        log("Starting playback monitor.", 2)
 
 
     def GetPlayStats(self):
         return self.playStats
 
     def onPlayBackStarted(self):
-
-        window = utils.window
         # Will be called when xbmc starts playing a file
         self.stopAll()
 
@@ -67,7 +63,7 @@ class Player(xbmc.Player):
                 except: pass
 
                 if count == 5: # try 5 times
-                    self.logMsg("Cancelling playback report...", 1)
+                    log("Cancelling playback report...", 1)
                     break
                 else: count += 1
 
@@ -84,12 +80,12 @@ class Player(xbmc.Player):
                 xbmc.sleep(200)
                 itemId = window("emby_%s.itemid" % currentFile)
                 if tryCount == 20: # try 20 times or about 10 seconds
-                    self.logMsg("Could not find itemId, cancelling playback report...", 1)
+                    log("Could not find itemId, cancelling playback report...", 1)
                     break
                 else: tryCount += 1
             
             else:
-                self.logMsg("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId), 0)
+                log("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId), 0)
 
                 # Only proceed if an itemId was found.
                 embyitem = "emby_%s" % currentFile
@@ -102,7 +98,7 @@ class Player(xbmc.Player):
                 customseek = window('emby_customPlaylist.seektime')
                 if window('emby_customPlaylist') == "true" and customseek:
                     # Start at, when using custom playlist (play to Kodi from webclient)
-                    self.logMsg("Seeking to: %s" % customseek, 1)
+                    log("Seeking to: %s" % customseek, 1)
                     self.xbmcplayer.seekTime(int(customseek)/10000000.0)
                     window('emby_customPlaylist.seektime', clear=True)
 
@@ -189,7 +185,7 @@ class Player(xbmc.Player):
 
                         if mapping: # Set in playbackutils.py
                             
-                            self.logMsg("Mapping for external subtitles index: %s" % mapping, 2)
+                            log("Mapping for external subtitles index: %s" % mapping, 2)
                             externalIndex = json.loads(mapping)
 
                             if externalIndex.get(str(indexSubs)):
@@ -207,7 +203,7 @@ class Player(xbmc.Player):
                 
 
                 # Post playback to server
-                self.logMsg("Sending POST play started: %s." % postdata, 2)
+                log("Sending POST play started: %s." % postdata, 2)
                 self.doUtils(url, postBody=postdata, action_type="POST")
                 
                 # Ensure we do have a runtime
@@ -215,7 +211,7 @@ class Player(xbmc.Player):
                     runtime = int(runtime)
                 except ValueError:
                     runtime = self.xbmcplayer.getTotalTime()
-                    self.logMsg("Runtime is missing, Kodi runtime: %s" % runtime, 1)
+                    log("Runtime is missing, Kodi runtime: %s" % runtime, 1)
 
                 # Save data map for updates and position calls
                 data = {
@@ -232,7 +228,7 @@ class Player(xbmc.Player):
                 }
                 
                 self.played_info[currentFile] = data
-                self.logMsg("ADDING_FILE: %s" % self.played_info, 1)
+                log("ADDING_FILE: %s" % self.played_info, 1)
 
                 # log some playback stats
                 '''if(itemType != None):
@@ -251,7 +247,7 @@ class Player(xbmc.Player):
 
     def reportPlayback(self):
         
-        self.logMsg("reportPlayback Called", 2)
+        log("reportPlayback Called", 2)
 
         # Get current file
         currentFile = self.currentFile
@@ -345,11 +341,11 @@ class Player(xbmc.Player):
                     
                     # Number of audiotracks to help get Emby Index
                     audioTracks = len(xbmc.Player().getAvailableAudioStreams())
-                    mapping = utils.window("emby_%s.indexMapping" % currentFile)
+                    mapping = window("emby_%s.indexMapping" % currentFile)
 
                     if mapping: # Set in PlaybackUtils.py
                         
-                        self.logMsg("Mapping for external subtitles index: %s" % mapping, 2)
+                        log("Mapping for external subtitles index: %s" % mapping, 2)
                         externalIndex = json.loads(mapping)
 
                         if externalIndex.get(str(indexSubs)):
@@ -369,13 +365,13 @@ class Player(xbmc.Player):
 
             # Report progress via websocketclient
             postdata = json.dumps(postdata)
-            self.logMsg("Report: %s" % postdata, 2)
+            log("Report: %s" % postdata, 2)
             self.ws.sendProgressUpdate(postdata)
 
     def onPlayBackPaused(self):
 
         currentFile = self.currentFile
-        self.logMsg("PLAYBACK_PAUSED: %s" % currentFile, 2)
+        log("PLAYBACK_PAUSED: %s" % currentFile, 2)
 
         if self.played_info.get(currentFile):
             self.played_info[currentFile]['paused'] = True
@@ -385,7 +381,7 @@ class Player(xbmc.Player):
     def onPlayBackResumed(self):
 
         currentFile = self.currentFile
-        self.logMsg("PLAYBACK_RESUMED: %s" % currentFile, 2)
+        log("PLAYBACK_RESUMED: %s" % currentFile, 2)
 
         if self.played_info.get(currentFile):
             self.played_info[currentFile]['paused'] = False
@@ -395,7 +391,7 @@ class Player(xbmc.Player):
     def onPlayBackSeek(self, time, seekOffset):
         # Make position when seeking a bit more accurate
         currentFile = self.currentFile
-        self.logMsg("PLAYBACK_SEEK: %s" % currentFile, 2)
+        log("PLAYBACK_SEEK: %s" % currentFile, 2)
 
         if self.played_info.get(currentFile):
             position = self.xbmcplayer.getTime()
@@ -404,39 +400,34 @@ class Player(xbmc.Player):
             self.reportPlayback()
     
     def onPlayBackStopped(self):
-        
-        window = utils.window
         # Will be called when user stops xbmc playing a file
-        self.logMsg("ONPLAYBACK_STOPPED", 2)
+        log("ONPLAYBACK_STOPPED", 2)
         window('emby_customPlaylist', clear=True)
         window('emby_customPlaylist.seektime', clear=True)
         window('emby_playbackProps', clear=True)
-        self.logMsg("Clear playlist properties.", 1)
+        log("Clear playlist properties.", 1)
         self.stopAll()
 
     def onPlayBackEnded(self):
         # Will be called when xbmc stops playing a file
-        self.logMsg("ONPLAYBACK_ENDED", 2)
-        utils.window('emby_customPlaylist.seektime', clear=True)
+        log("ONPLAYBACK_ENDED", 2)
+        window('emby_customPlaylist.seektime', clear=True)
         self.stopAll()
 
     def stopAll(self):
 
-        lang = utils.language
-        settings = utils.settings
-
         if not self.played_info:
             return 
             
-        self.logMsg("Played_information: %s" % self.played_info, 1)
+        log("Played_information: %s" % self.played_info, 1)
         # Process each items
         for item in self.played_info:
             
             data = self.played_info.get(item)
             if data:
                 
-                self.logMsg("Item path: %s" % item, 2)
-                self.logMsg("Item data: %s" % data, 2)
+                log("Item path: %s" % item, 2)
+                log("Item data: %s" % data, 2)
 
                 runtime = data['runtime']
                 currentPosition = data['currentPosition']
@@ -447,7 +438,7 @@ class Player(xbmc.Player):
                 playMethod = data['playmethod']
 
                 # Prevent manually mark as watched in Kodi monitor
-                utils.window('emby_skipWatched%s' % itemid, value="true")
+                window('emby_skipWatched%s' % itemid, value="true")
 
                 if currentPosition and runtime:
                     try:
@@ -457,7 +448,7 @@ class Player(xbmc.Player):
                         percentComplete = 0
                         
                     markPlayedAt = float(settings('markPlayed')) / 100
-                    self.logMsg("Percent complete: %s Mark played at: %s"
+                    log("Percent complete: %s Mark played at: %s"
                         % (percentComplete, markPlayedAt), 1)
 
                     # Send the delete action to the server.
@@ -475,18 +466,18 @@ class Player(xbmc.Player):
                     if percentComplete >= markPlayedAt and offerDelete:
                         resp = xbmcgui.Dialog().yesno(lang(30091), lang(33015), autoclose=120000)
                         if not resp:
-                            self.logMsg("User skipped deletion.", 1)
+                            log("User skipped deletion.", 1)
                             continue
 
                         url = "{server}/emby/Items/%s?format=json" % itemid
-                        self.logMsg("Deleting request: %s" % itemid, 1)
+                        log("Deleting request: %s" % itemid, 1)
                         self.doUtils(url, action_type="DELETE")
 
                 self.stopPlayback(data)
 
                 # Stop transcoding
                 if playMethod == "Transcode":
-                    self.logMsg("Transcoding for %s terminated." % itemid, 1)
+                    log("Transcoding for %s terminated." % itemid, 1)
                     deviceId = self.clientInfo.getDeviceId()
                     url = "{server}/emby/Videos/ActiveEncodings?DeviceId=%s" % deviceId
                     self.doUtils(url, action_type="DELETE")
@@ -495,7 +486,7 @@ class Player(xbmc.Player):
     
     def stopPlayback(self, data):
         
-        self.logMsg("stopPlayback called", 2)
+        log("stopPlayback called", 2)
         
         itemId = data['item_id']
         currentPosition = data['currentPosition']
diff --git a/resources/lib/utils.py b/resources/lib/utils.py
index dd2d04d4..203a7dee 100644
--- a/resources/lib/utils.py
+++ b/resources/lib/utils.py
@@ -188,7 +188,7 @@ def setScreensaver(value):
     result = xbmc.executeJSONRPC(json.dumps(query))
     log("Toggling screensaver: %s %s" % (value, result), 1)
 
-def convertdate(date):
+def convertDate(date):
     try:
         date = datetime.strptime(date, "%Y-%m-%dT%H:%M:%SZ")
     except TypeError: