diff --git a/addon.xml b/addon.xml
index 8d848b4a..ab62d8ca 100644
--- a/addon.xml
+++ b/addon.xml
@@ -15,6 +15,13 @@
+
+ -
+
+ Settings for the Plex Server
+ [!IsEmpty(ListItem.DBID) + !StringCompare(ListItem.DBID,-1) | !IsEmpty(ListItem.Property(plexid))] + !IsEmpty(Window(10000).Property(plex_context))
+
+
all
en
diff --git a/contextmenu.py b/contextmenu.py
index d4549829..df6de3fd 100644
--- a/contextmenu.py
+++ b/contextmenu.py
@@ -1,175 +1,52 @@
# -*- coding: utf-8 -*-
-#################################################################################################
+###############################################################################
import logging
import os
import sys
-import urlparse
import xbmc
import xbmcaddon
-import xbmcgui
-#################################################################################################
+###############################################################################
-_addon = xbmcaddon.Addon(id='plugin.video.emby')
-_addon_path = _addon.getAddonInfo('path').decode('utf-8')
-_base_resource = xbmc.translatePath(os.path.join(_addon_path, 'resources', 'lib')).decode('utf-8')
+_addon = xbmcaddon.Addon(id='plugin.video.plexkodiconnect')
+try:
+ _addon_path = _addon.getAddonInfo('path').decode('utf-8')
+except TypeError:
+ _addon_path = _addon.getAddonInfo('path').decode()
+try:
+ _base_resource = xbmc.translatePath(os.path.join(
+ _addon_path,
+ 'resources',
+ 'lib')).decode('utf-8')
+except TypeError:
+ _base_resource = xbmc.translatePath(os.path.join(
+ _addon_path,
+ 'resources',
+ 'lib')).decode()
sys.path.append(_base_resource)
-#################################################################################################
-
-import api
-import artwork
-import downloadutils
-import librarysync
-import read_embyserver as embyserver
-import embydb_functions as embydb
-import kodidb_functions as kodidb
-import musicutils as musicutils
-from utils import settings, language as lang, kodiSQL
-
-#################################################################################################
+###############################################################################
import loghandler
+from context_entry import ContextMenu
+
+###############################################################################
loghandler.config()
-log = logging.getLogger("EMBY.contextmenu")
+log = logging.getLogger("PLEX.contextmenu")
-#################################################################################################
+###############################################################################
-# Kodi contextmenu item to configure the emby settings
-if __name__ == '__main__':
+if __name__ == "__main__":
- kodiId = xbmc.getInfoLabel('ListItem.DBID').decode('utf-8')
- itemType = xbmc.getInfoLabel('ListItem.DBTYPE').decode('utf-8')
- itemId = ""
-
- if not itemType:
-
- if xbmc.getCondVisibility("Container.Content(albums)"):
- itemType = "album"
- elif xbmc.getCondVisibility("Container.Content(artists)"):
- itemType = "artist"
- elif xbmc.getCondVisibility("Container.Content(songs)"):
- itemType = "song"
- elif xbmc.getCondVisibility("Container.Content(pictures)"):
- itemType = "picture"
- else:
- log.info("ItemType is unknown.")
-
- if (not kodiId or kodiId == "-1") and xbmc.getInfoLabel("ListItem.Property(embyid)"):
- itemId = xbmc.getInfoLabel("ListItem.Property(embyid)")
-
- elif kodiId and itemType:
- embyconn = kodiSQL('emby')
- embycursor = embyconn.cursor()
- emby_db = embydb.Embydb_Functions(embycursor)
- item = emby_db.getItem_byKodiId(kodiId, itemType)
- embycursor.close()
- try:
- itemId = item[0]
- except TypeError:
- pass
-
-
- log.info("Found ItemId: %s ItemType: %s" % (itemId, itemType))
- if itemId:
-
- dialog = xbmcgui.Dialog()
-
- emby = embyserver.Read_EmbyServer()
- item = emby.getItem(itemId)
- API = api.API(item)
- userdata = API.getUserData()
- likes = userdata['Likes']
- favourite = userdata['Favorite']
-
- options = []
-
- if favourite:
- # Remove from emby favourites
- options.append(lang(30406))
- else:
- # Add to emby favourites
- options.append(lang(30405))
-
- if itemType == "song":
- # Set custom song rating
- options.append(lang(30407))
-
- # Refresh item
- options.append(lang(30410))
- # Delete item
- options.append(lang(30409))
- # Addon settings
- options.append(lang(30408))
-
- # Display select dialog and process results
- resp = xbmcgui.Dialog().select(lang(30401), options)
- if resp > -1:
- selected = options[resp]
-
- if selected == lang(30410):
- # Refresh item
- emby.refreshItem(itemId)
- elif selected == lang(30405):
- # Add favourite
- emby.updateUserRating(itemId, favourite=True)
- elif selected == lang(30406):
- # Delete favourite
- emby.updateUserRating(itemId, favourite=False)
- elif selected == lang(30407):
- # Update song rating
- kodiconn = kodiSQL('music')
- kodicursor = kodiconn.cursor()
- query = "SELECT rating FROM song WHERE idSong = ?"
- kodicursor.execute(query, (kodiId,))
- try:
- value = kodicursor.fetchone()[0]
- current_value = int(round(float(value),0))
- except TypeError:
- pass
- else:
- new_value = dialog.numeric(0, lang(30411), str(current_value))
- if new_value > -1:
-
- new_value = int(new_value)
- if new_value > 5:
- new_value = 5
-
- if settings('enableUpdateSongRating') == "true":
- musicutils.updateRatingToFile(new_value, API.getFilePath())
-
- query = "UPDATE song SET rating = ? WHERE idSong = ?"
- kodicursor.execute(query, (new_value, kodiId,))
- kodiconn.commit()
-
- '''if settings('enableExportSongRating') == "true":
- like, favourite, deletelike = musicutils.getEmbyRatingFromKodiRating(new_value)
- emby.updateUserRating(itemId, like, favourite, deletelike)'''
- finally:
- kodicursor.close()
-
- elif selected == lang(30408):
- # Open addon settings
- xbmc.executebuiltin("Addon.OpenSettings(plugin.video.emby)")
-
- elif selected == lang(30409):
- # delete item from the server
- delete = True
- if settings('skipContextMenu') != "true":
- resp = dialog.yesno(
- heading=lang(29999),
- line1=lang(33041))
- if not resp:
- log.info("User skipped deletion for: %s." % itemId)
- delete = False
-
- if delete:
- log.info("Deleting request: %s" % itemId)
- emby.deleteItem(itemId)
-
- xbmc.sleep(500)
- xbmc.executebuiltin('Container.Refresh')
\ No newline at end of file
+ try:
+ # Start the context menu
+ ContextMenu()
+ except Exception as error:
+ log.exception(error)
+ import traceback
+ log.exception("Traceback:\n%s" % traceback.format_exc())
+ raise
diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml
index 913a3512..4a35817e 100644
--- a/resources/language/English/strings.xml
+++ b/resources/language/English/strings.xml
@@ -1,6 +1,7 @@
+ PlexKodiConnect
Server Address (IP)
Preferred playback method
Log level
@@ -260,7 +261,11 @@
Remove from Plex favorites
Set custom song rating
Plex addon settings
- Delete item from the server
+ Delete item from server
+ Refresh this item
+ Set custom song rating (0-5)
+ Force transcode
+ Enable Plex context menu in Kodi
Verify Host SSL Certificate (more secure)
@@ -283,7 +288,7 @@
[COLOR yellow]Enter network credentials[/COLOR]
Enable Plex Trailers (Plexpass is needed)
Ask to play trailers
- Skip Emby delete confirmation for the context menu (use at your own risk)
+ Skip Plex delete confirmation for the context menu (use at your own risk)
Jump back on resume (in seconds)
Force transcode H265
Music metadata options (not compatible with direct stream)
@@ -344,6 +349,7 @@
Comparing:
Failed to generate a new device Id. See your logs for more information.
Kodi will now restart to apply the changes.
+ Delete file(s) from Plex Server? This will also delete the file(s) from disk!
- Number of trailers to play before a movie
diff --git a/resources/language/German/strings.xml b/resources/language/German/strings.xml
index 789debcf..6263abb0 100644
--- a/resources/language/German/strings.xml
+++ b/resources/language/German/strings.xml
@@ -1,5 +1,6 @@
+ PlexKodiConnect
IP-Adresse des Servers
Automatisches Öffnen von Ordnern mit einem Eintrag
Gewünschte Wiedergabe-Methode
@@ -21,6 +22,7 @@
Netzwerk Credentials eingeben
PlexKodiConnect Start Verzögerung (in Sekunden)
Extras ignorieren, wenn Nächste Episode gespielt wird
+ Sicherheitsabfrage bei Löschen des Plex Elements deaktivieren
Bei Wiederaufnahme zurückspulen (in Sekunden)
[COLOR yellow]Anzahl Login-Versuche zurücksetzen[/COLOR]
@@ -282,7 +284,24 @@
Musikstücke
Kanäle
+
+ Plex Optionen
+ Clear like for this item
+ Like this item
+ Dislike this item
+ Add to Plex favorites
+ Remove from Plex favorites
+ Set custom song rating
+ Plex Addon Optionen
+ Element in Plex Server löschen
+ Element neu laden
+ Set custom song rating (0-5)
+ Transkodieren erzwingen
+ Plex Kontextmenu in Kodi aktivieren
+
+
Kodi wird jetzt neu gestartet um die Änderungen anzuwenden.
+ Eintrag vom Plex Server löschen? Dies wird die Dateien auch endgültig von der Festplatte löschen!
- Anzahl abzuspielender Trailer vor einem Film
diff --git a/resources/lib/PlexFunctions.py b/resources/lib/PlexFunctions.py
index ba42e254..1d008e54 100644
--- a/resources/lib/PlexFunctions.py
+++ b/resources/lib/PlexFunctions.py
@@ -526,3 +526,22 @@ def scrobble(ratingKey, state):
return
downloadutils.DownloadUtils().downloadUrl(url)
log.info("Toggled watched state for Plex item %s" % ratingKey)
+
+
+def delete_item_from_pms(plexid):
+ """
+ Deletes the item plexid from the Plex Media Server (and the harddrive!).
+ Do make sure that the currently logged in user has the credentials
+
+ Returns True if successful, False otherwise
+ """
+ xml = downloadutils.DownloadUtils().downloadUrl(
+ '{server}/library/metadata/%s' % plexid,
+ action_type="DELETE")
+ try:
+ xml.attrib
+ except AttributeError:
+ log.error('Could not delete Plex id %s' % plexid)
+ return False
+ log.info(xml.dump)
+ return True
diff --git a/resources/lib/context_entry.py b/resources/lib/context_entry.py
new file mode 100644
index 00000000..65c386ee
--- /dev/null
+++ b/resources/lib/context_entry.py
@@ -0,0 +1,194 @@
+# -*- coding: utf-8 -*-
+
+###############################################################################
+
+import logging
+
+import xbmc
+import xbmcaddon
+
+import PlexAPI
+from PlexFunctions import GetPlexMetadata, delete_item_from_pms
+import embydb_functions as embydb
+from utils import settings, dialog, language as lang, kodiSQL
+from dialogs import context
+
+###############################################################################
+
+log = logging.getLogger("PLEX."+__name__)
+addonName = 'PlexKodiConnect'
+
+OPTIONS = {
+ 'Refresh': lang(30410),
+ 'Delete': lang(30409),
+ 'Addon': lang(30408),
+ # 'AddFav': lang(30405),
+ # 'RemoveFav': lang(30406),
+ # 'RateSong': lang(30407),
+ 'Transcode': lang(30412)
+}
+
+###############################################################################
+
+
+class ContextMenu(object):
+
+ _selected_option = None
+
+ def __init__(self):
+ self.kodi_id = xbmc.getInfoLabel('ListItem.DBID').decode('utf-8')
+ self.item_type = self._get_item_type()
+ self.item_id = self._get_item_id(self.kodi_id, self.item_type)
+
+ log.info("Found item_id: %s item_type: %s"
+ % (self.item_id, self.item_type))
+
+ if not self.item_id:
+ return
+
+ self.item = GetPlexMetadata(self.item_id)
+ self.api = PlexAPI.API(self.item)
+
+ if self._select_menu():
+ self._action_menu()
+
+ if self._selected_option in (OPTIONS['Delete'],
+ OPTIONS['Refresh']):
+ log.info("refreshing container")
+ xbmc.sleep(500)
+ xbmc.executebuiltin('Container.Refresh')
+
+ @classmethod
+ def _get_item_type(cls):
+ item_type = xbmc.getInfoLabel('ListItem.DBTYPE').decode('utf-8')
+
+ if not item_type:
+ if xbmc.getCondVisibility('Container.Content(albums)'):
+ item_type = "album"
+ elif xbmc.getCondVisibility('Container.Content(artists)'):
+ item_type = "artist"
+ elif xbmc.getCondVisibility('Container.Content(songs)'):
+ item_type = "song"
+ elif xbmc.getCondVisibility('Container.Content(pictures)'):
+ item_type = "picture"
+ else:
+ log.info("item_type is unknown")
+
+ return item_type
+
+ @classmethod
+ def _get_item_id(cls, kodi_id, item_type):
+ item_id = xbmc.getInfoLabel('ListItem.Property(plexid)')
+ if not item_id and kodi_id and item_type:
+ with embydb.GetEmbyDB() as emby_db:
+ item = emby_db.getItem_byKodiId(kodi_id, item_type)
+ try:
+ item_id = item[0]
+ except TypeError:
+ log.error('Could not get the Plex id for context menu')
+ return item_id
+
+ def _select_menu(self):
+ # Display select dialog
+ options = []
+
+ if self.item_type in ("movie", "episode", "song"):
+ options.append(OPTIONS['Transcode'])
+
+ # userdata = self.api.getUserData()
+ # if userdata['Favorite']:
+ # # Remove from emby favourites
+ # options.append(OPTIONS['RemoveFav'])
+ # else:
+ # # Add to emby favourites
+ # options.append(OPTIONS['AddFav'])
+
+ # if self.item_type == "song":
+ # # Set custom song rating
+ # options.append(OPTIONS['RateSong'])
+
+ # Refresh item
+ options.append(OPTIONS['Refresh'])
+ # Delete item, only if the Plex Home main user is logged in
+ if settings('plex_restricteduser') != 'true':
+ options.append(OPTIONS['Delete'])
+ # Addon settings
+ options.append(OPTIONS['Addon'])
+
+ addon = xbmcaddon.Addon('plugin.video.plexkodiconnect')
+ context_menu = context.ContextMenu("script-emby-context.xml",
+ addon.getAddonInfo('path'),
+ "default", "1080i")
+ context_menu.set_options(options)
+ context_menu.doModal()
+
+ if context_menu.is_selected():
+ self._selected_option = context_menu.get_selected()
+
+ return self._selected_option
+
+ def _action_menu(self):
+
+ selected = self._selected_option
+
+ if selected == OPTIONS['Transcode']:
+ pass
+
+ elif selected == OPTIONS['Refresh']:
+ self.emby.refreshItem(self.item_id)
+
+ # elif selected == OPTIONS['AddFav']:
+ # self.emby.updateUserRating(self.item_id, favourite=True)
+
+ # elif selected == OPTIONS['RemoveFav']:
+ # self.emby.updateUserRating(self.item_id, favourite=False)
+
+ # elif selected == OPTIONS['RateSong']:
+ # self._rate_song()
+
+ elif selected == OPTIONS['Addon']:
+ xbmc.executebuiltin('Addon.OpenSettings(plugin.video.plexkodiconnect)')
+
+ elif selected == OPTIONS['Delete']:
+ self._delete_item()
+
+ def _rate_song(self):
+
+ conn = kodiSQL('music')
+ cursor = conn.cursor()
+ query = "SELECT rating FROM song WHERE idSong = ?"
+ cursor.execute(query, (self.kodi_id,))
+ try:
+ value = cursor.fetchone()[0]
+ current_value = int(round(float(value), 0))
+ except TypeError:
+ pass
+ else:
+ new_value = dialog("numeric", 0, lang(30411), str(current_value))
+ if new_value > -1:
+
+ new_value = int(new_value)
+ if new_value > 5:
+ new_value = 5
+
+ if settings('enableUpdateSongRating') == "true":
+ musicutils.updateRatingToFile(new_value, self.api.get_file_path())
+
+ query = "UPDATE song SET rating = ? WHERE idSong = ?"
+ cursor.execute(query, (new_value, self.kodi_id,))
+ conn.commit()
+ finally:
+ cursor.close()
+
+ def _delete_item(self):
+
+ delete = True
+ if settings('skipContextMenu') != "true":
+
+ if not dialog(type_="yesno", heading=addonName, line1=lang(33041)):
+ log.info("User skipped deletion for: %s", self.item_id)
+ delete = False
+
+ if delete:
+ log.info("Deleting Plex item with id %s", self.item_id)
+ delete_item_from_pms(self.item_id)
diff --git a/resources/lib/dialog/__init__.py b/resources/lib/dialog/__init__.py
deleted file mode 100644
index b93054b3..00000000
--- a/resources/lib/dialog/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# Dummy file to make this directory a package.
diff --git a/resources/lib/dialog/loginconnect.py b/resources/lib/dialog/loginconnect.py
deleted file mode 100644
index f12eab0f..00000000
--- a/resources/lib/dialog/loginconnect.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# -*- coding: utf-8 -*-
-
-##################################################################################################
-
-import os
-
-import xbmcgui
-import xbmcaddon
-
-##################################################################################################
-
-addon = xbmcaddon.Addon('plugin.video.plexkodiconnect')
-
-ACTION_BACK = 92
-SIGN_IN = 200
-REMIND_LATER = 201
-
-
-class LoginConnect(xbmcgui.WindowXMLDialog):
-
-
- def __init__(self, *args, **kwargs):
-
- xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
-
- def __add_editcontrol(self, x, y, height, width, password=0):
-
- media = os.path.join(addon.getAddonInfo('path'), 'resources', 'skins', 'default', 'media')
- control = xbmcgui.ControlEdit(0,0,0,0,
- label="User",
- font="font10",
- textColor="ff464646",
- focusTexture=os.path.join(media, "button-focus.png"),
- noFocusTexture=os.path.join(media, "button-focus.png"),
- isPassword=password)
-
- control.setPosition(x,y)
- control.setHeight(height)
- control.setWidth(width)
-
- self.addControl(control)
- return control
-
- def onInit(self):
-
- self.user_field = self.__add_editcontrol(685,385,40,500)
- self.setFocus(self.user_field)
- self.password_field = self.__add_editcontrol(685,470,40,500, password=1)
- self.signin_button = self.getControl(SIGN_IN)
- self.remind_button = self.getControl(REMIND_LATER)
-
- self.user_field.controlUp(self.remind_button)
- self.user_field.controlDown(self.password_field)
- self.password_field.controlUp(self.user_field)
- self.password_field.controlDown(self.signin_button)
- self.signin_button.controlUp(self.password_field)
- self.remind_button.controlDown(self.user_field)
-
- def onClick(self, control):
-
- if control == SIGN_IN:
- # Sign in to emby connect
- self.user = self.user_field.getText()
- __password = self.password_field.getText()
-
- ### REVIEW ONCE CONNECT MODULE IS MADE
- self.close()
-
- elif control == REMIND_LATER:
- # Remind me later
- self.close()
-
- def onAction(self, action):
-
- if action == ACTION_BACK:
- self.close()
\ No newline at end of file
diff --git a/resources/lib/dialogs/__init__.py b/resources/lib/dialogs/__init__.py
new file mode 100644
index 00000000..92c6f42a
--- /dev/null
+++ b/resources/lib/dialogs/__init__.py
@@ -0,0 +1,6 @@
+# Dummy file to make this directory a package.
+# from serverconnect import ServerConnect
+# from usersconnect import UsersConnect
+# from loginconnect import LoginConnect
+# from loginmanual import LoginManual
+# from servermanual import ServerManual
diff --git a/resources/lib/dialogs/context.py b/resources/lib/dialogs/context.py
new file mode 100644
index 00000000..4ee9f038
--- /dev/null
+++ b/resources/lib/dialogs/context.py
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+
+###############################################################################
+
+import logging
+import os
+
+import xbmcgui
+import xbmcaddon
+
+from utils import window
+
+###############################################################################
+
+log = logging.getLogger("PLEX."+__name__)
+addon = xbmcaddon.Addon('plugin.video.plexkodiconnect')
+
+ACTION_PARENT_DIR = 9
+ACTION_PREVIOUS_MENU = 10
+ACTION_BACK = 92
+ACTION_SELECT_ITEM = 7
+ACTION_MOUSE_LEFT_CLICK = 100
+LIST = 155
+USER_IMAGE = 150
+
+###############################################################################
+
+
+class ContextMenu(xbmcgui.WindowXMLDialog):
+
+ _options = []
+ selected_option = None
+
+
+ def __init__(self, *args, **kwargs):
+
+ xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
+
+ def set_options(self, options=[]):
+ self._options = options
+
+ def is_selected(self):
+ return True if self.selected_option else False
+
+ def get_selected(self):
+ return self.selected_option
+
+ def onInit(self):
+
+ if window('PlexUserImage'):
+ self.getControl(USER_IMAGE).setImage(window('PlexUserImage'))
+
+ height = 479 + (len(self._options) * 55)
+ log.info("options: %s", self._options)
+ self.list_ = self.getControl(LIST)
+
+ for option in self._options:
+ self.list_.addItem(self._add_listitem(option))
+
+ self.background = self._add_editcontrol(730, height, 30, 450)
+ self.setFocus(self.list_)
+
+ def onAction(self, action):
+
+ if action in (ACTION_BACK, ACTION_PARENT_DIR, ACTION_PREVIOUS_MENU):
+ self.close()
+
+ if action in (ACTION_SELECT_ITEM, ACTION_MOUSE_LEFT_CLICK):
+
+ if self.getFocusId() == LIST:
+ option = self.list_.getSelectedItem()
+ self.selected_option = option.getLabel()
+ log.info('option selected: %s', self.selected_option)
+
+ self.close()
+
+ def _add_editcontrol(self, x, y, height, width, password=0):
+
+ media = os.path.join(addon.getAddonInfo('path'), 'resources', 'skins', 'default', 'media')
+ control = xbmcgui.ControlImage(0, 0, 0, 0,
+ filename=os.path.join(media, "white.png"),
+ aspectRatio=0,
+ colorDiffuse="ff111111")
+ control.setPosition(x, y)
+ control.setHeight(height)
+ control.setWidth(width)
+
+ self.addControl(control)
+ return control
+
+ @classmethod
+ def _add_listitem(cls, label):
+ return xbmcgui.ListItem(label)
diff --git a/resources/lib/dialogs/loginconnect.py b/resources/lib/dialogs/loginconnect.py
new file mode 100644
index 00000000..db7c39cc
--- /dev/null
+++ b/resources/lib/dialogs/loginconnect.py
@@ -0,0 +1,136 @@
+# -*- coding: utf-8 -*-
+
+##################################################################################################
+
+import logging
+import os
+
+import xbmcgui
+import xbmcaddon
+
+from utils import language as lang
+
+##################################################################################################
+
+log = logging.getLogger("EMBY."+__name__)
+addon = xbmcaddon.Addon('plugin.video.emby')
+
+ACTION_PARENT_DIR = 9
+ACTION_PREVIOUS_MENU = 10
+ACTION_BACK = 92
+SIGN_IN = 200
+CANCEL = 201
+ERROR_TOGGLE = 202
+ERROR_MSG = 203
+ERROR = {
+ 'Invalid': 1,
+ 'Empty': 2
+}
+
+##################################################################################################
+
+
+class LoginConnect(xbmcgui.WindowXMLDialog):
+
+ _user = None
+ error = None
+
+
+ def __init__(self, *args, **kwargs):
+
+ xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
+
+ def set_connect_manager(self, connect_manager):
+ self.connect_manager = connect_manager
+
+ def is_logged_in(self):
+ return True if self._user else False
+
+ def get_user(self):
+ return self._user
+
+
+ def onInit(self):
+
+ self.user_field = self._add_editcontrol(725, 385, 40, 500)
+ self.setFocus(self.user_field)
+ self.password_field = self._add_editcontrol(725, 470, 40, 500, password=1)
+ self.signin_button = self.getControl(SIGN_IN)
+ self.remind_button = self.getControl(CANCEL)
+ self.error_toggle = self.getControl(ERROR_TOGGLE)
+ self.error_msg = self.getControl(ERROR_MSG)
+
+ self.user_field.controlUp(self.remind_button)
+ self.user_field.controlDown(self.password_field)
+ self.password_field.controlUp(self.user_field)
+ self.password_field.controlDown(self.signin_button)
+ self.signin_button.controlUp(self.password_field)
+ self.remind_button.controlDown(self.user_field)
+
+ def onClick(self, control):
+
+ if control == SIGN_IN:
+ # Sign in to emby connect
+ self._disable_error()
+
+ user = self.user_field.getText()
+ password = self.password_field.getText()
+
+ if not user or not password:
+ # Display error
+ self._error(ERROR['Empty'], lang(30608))
+ log.error("Username or password cannot be null")
+
+ elif self._login(user, password):
+ self.close()
+
+ elif control == CANCEL:
+ # Remind me later
+ self.close()
+
+ def onAction(self, action):
+
+ if (self.error == ERROR['Empty']
+ and self.user_field.getText() and self.password_field.getText()):
+ self._disable_error()
+
+ if action in (ACTION_BACK, ACTION_PARENT_DIR, ACTION_PREVIOUS_MENU):
+ self.close()
+
+ def _add_editcontrol(self, x, y, height, width, password=0):
+
+ media = os.path.join(addon.getAddonInfo('path'), 'resources', 'skins', 'default', 'media')
+ control = xbmcgui.ControlEdit(0, 0, 0, 0,
+ label="User",
+ font="font10",
+ textColor="ff525252",
+ focusTexture=os.path.join(media, "button-focus.png"),
+ noFocusTexture=os.path.join(media, "button-focus.png"),
+ isPassword=password)
+ control.setPosition(x, y)
+ control.setHeight(height)
+ control.setWidth(width)
+
+ self.addControl(control)
+ return control
+
+ def _login(self, username, password):
+
+ result = self.connect_manager.loginToConnect(username, password)
+ if result is False:
+ self._error(ERROR['Invalid'], lang(33009))
+ return False
+ else:
+ self._user = result
+ return True
+
+ def _error(self, state, message):
+
+ self.error = state
+ self.error_msg.setLabel(message)
+ self.error_toggle.setVisibleCondition('True')
+
+ def _disable_error(self):
+
+ self.error = None
+ self.error_toggle.setVisibleCondition('False')
diff --git a/resources/lib/dialogs/loginmanual.py b/resources/lib/dialogs/loginmanual.py
new file mode 100644
index 00000000..7db1adcf
--- /dev/null
+++ b/resources/lib/dialogs/loginmanual.py
@@ -0,0 +1,145 @@
+# -*- coding: utf-8 -*-
+
+##################################################################################################
+
+import logging
+import os
+
+import xbmcgui
+import xbmcaddon
+
+import read_embyserver as embyserver
+from utils import language as lang
+
+##################################################################################################
+
+log = logging.getLogger("EMBY."+__name__)
+addon = xbmcaddon.Addon('plugin.video.emby')
+
+ACTION_PARENT_DIR = 9
+ACTION_PREVIOUS_MENU = 10
+ACTION_BACK = 92
+SIGN_IN = 200
+CANCEL = 201
+ERROR_TOGGLE = 202
+ERROR_MSG = 203
+ERROR = {
+ 'Invalid': 1,
+ 'Empty': 2
+}
+
+##################################################################################################
+
+
+class LoginManual(xbmcgui.WindowXMLDialog):
+
+ _user = None
+ error = None
+ username = None
+
+
+ def __init__(self, *args, **kwargs):
+
+ self.emby = embyserver.Read_EmbyServer()
+ xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
+
+ def is_logged_in(self):
+ return True if self._user else False
+
+ def set_server(self, server):
+ self.server = server
+
+ def set_user(self, user):
+ self.username = user or {}
+
+ def get_user(self):
+ return self._user
+
+ def onInit(self):
+
+ self.signin_button = self.getControl(SIGN_IN)
+ self.cancel_button = self.getControl(CANCEL)
+ self.error_toggle = self.getControl(ERROR_TOGGLE)
+ self.error_msg = self.getControl(ERROR_MSG)
+ self.user_field = self._add_editcontrol(725, 400, 40, 500)
+ self.password_field = self._add_editcontrol(725, 475, 40, 500, password=1)
+
+ if self.username:
+ self.user_field.setText(self.username)
+ self.setFocus(self.password_field)
+ else:
+ self.setFocus(self.user_field)
+
+ self.user_field.controlUp(self.cancel_button)
+ self.user_field.controlDown(self.password_field)
+ self.password_field.controlUp(self.user_field)
+ self.password_field.controlDown(self.signin_button)
+ self.signin_button.controlUp(self.password_field)
+ self.cancel_button.controlDown(self.user_field)
+
+ def onClick(self, control):
+
+ if control == SIGN_IN:
+ # Sign in to emby connect
+ self._disable_error()
+
+ user = self.user_field.getText()
+ password = self.password_field.getText()
+
+ if not user:
+ # Display error
+ self._error(ERROR['Empty'], lang(30613))
+ log.error("Username cannot be null")
+
+ elif self._login(user, password):
+ self.close()
+
+ elif control == CANCEL:
+ # Remind me later
+ self.close()
+
+ def onAction(self, action):
+
+ if self.error == ERROR['Empty'] and self.user_field.getText():
+ self._disable_error()
+
+ if action in (ACTION_BACK, ACTION_PARENT_DIR, ACTION_PREVIOUS_MENU):
+ self.close()
+
+ def _add_editcontrol(self, x, y, height, width, password=0):
+
+ media = os.path.join(addon.getAddonInfo('path'), 'resources', 'skins', 'default', 'media')
+ control = xbmcgui.ControlEdit(0, 0, 0, 0,
+ label="User",
+ font="font10",
+ textColor="ff525252",
+ focusTexture=os.path.join(media, "button-focus.png"),
+ noFocusTexture=os.path.join(media, "button-focus.png"),
+ isPassword=password)
+ control.setPosition(x, y)
+ control.setHeight(height)
+ control.setWidth(width)
+
+ self.addControl(control)
+ return control
+
+ def _login(self, username, password):
+
+ result = self.emby.loginUser(self.server, username, password)
+ if not result:
+ self._error(ERROR['Invalid'], lang(33009))
+ return False
+ else:
+ self._user = result
+ return True
+
+ def _error(self, state, message):
+
+ self.error = state
+ self.error_msg.setLabel(message)
+ self.error_toggle.setVisibleCondition('True')
+
+ def _disable_error(self):
+
+ self.error = None
+ self.error_toggle.setVisibleCondition('False')
diff --git a/resources/lib/dialogs/serverconnect.py b/resources/lib/dialogs/serverconnect.py
new file mode 100644
index 00000000..541ca6f9
--- /dev/null
+++ b/resources/lib/dialogs/serverconnect.py
@@ -0,0 +1,145 @@
+# -*- coding: utf-8 -*-
+
+##################################################################################################
+
+import logging
+
+import xbmc
+import xbmcgui
+
+import connect.connectionmanager as connectionmanager
+from utils import language as lang
+
+##################################################################################################
+
+log = logging.getLogger("EMBY."+__name__)
+
+CONN_STATE = connectionmanager.ConnectionState
+ACTION_PARENT_DIR = 9
+ACTION_PREVIOUS_MENU = 10
+ACTION_BACK = 92
+ACTION_SELECT_ITEM = 7
+ACTION_MOUSE_LEFT_CLICK = 100
+USER_IMAGE = 150
+USER_NAME = 151
+LIST = 155
+CANCEL = 201
+MESSAGE_BOX = 202
+MESSAGE = 203
+BUSY = 204
+EMBY_CONNECT = 205
+MANUAL_SERVER = 206
+
+##################################################################################################
+
+
+class ServerConnect(xbmcgui.WindowXMLDialog):
+
+ username = ""
+ user_image = None
+ servers = []
+
+ _selected_server = None
+ _connect_login = False
+ _manual_server = False
+
+
+ def __init__(self, *args, **kwargs):
+
+ xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
+
+ def set_args(self, **kwargs):
+ # connect_manager, username, user_image, servers, emby_connect
+ for key, value in kwargs.iteritems():
+ setattr(self, key, value)
+
+ def is_server_selected(self):
+ return True if self._selected_server else False
+
+ def get_server(self):
+ return self._selected_server
+
+ def is_connect_login(self):
+ return self._connect_login
+
+ def is_manual_server(self):
+ return self._manual_server
+
+
+ def onInit(self):
+
+ self.message = self.getControl(MESSAGE)
+ self.message_box = self.getControl(MESSAGE_BOX)
+ self.busy = self.getControl(BUSY)
+ self.list_ = self.getControl(LIST)
+
+ for server in self.servers:
+ server_type = "wifi" if server.get('ExchangeToken') else "network"
+ self.list_.addItem(self._add_listitem(server['Name'], server['Id'], server_type))
+
+ self.getControl(USER_NAME).setLabel("%s %s" % (lang(33000), self.username.decode('utf-8')))
+
+ if self.user_image is not None:
+ self.getControl(USER_IMAGE).setImage(self.user_image)
+
+ if not self.emby_connect: # Change connect user
+ self.getControl(EMBY_CONNECT).setLabel("[UPPERCASE][B]"+lang(30618)+"[/B][/UPPERCASE]")
+
+ if self.servers:
+ self.setFocus(self.list_)
+
+ @classmethod
+ def _add_listitem(cls, label, server_id, server_type):
+
+ item = xbmcgui.ListItem(label)
+ item.setProperty('id', server_id)
+ item.setProperty('server_type', server_type)
+
+ return item
+
+ def onAction(self, action):
+
+ if action in (ACTION_BACK, ACTION_PREVIOUS_MENU, ACTION_PARENT_DIR):
+ self.close()
+
+ if action in (ACTION_SELECT_ITEM, ACTION_MOUSE_LEFT_CLICK):
+
+ if self.getFocusId() == LIST:
+ server = self.list_.getSelectedItem()
+ selected_id = server.getProperty('id')
+ log.info('Server Id selected: %s', selected_id)
+
+ if self._connect_server(selected_id):
+ self.message_box.setVisibleCondition('False')
+ self.close()
+
+ def onClick(self, control):
+
+ if control == EMBY_CONNECT:
+ self.connect_manager.clearData()
+ self._connect_login = True
+ self.close()
+
+ elif control == MANUAL_SERVER:
+ self._manual_server = True
+ self.close()
+
+ elif control == CANCEL:
+ self.close()
+
+ def _connect_server(self, server_id):
+
+ server = self.connect_manager.getServerInfo(server_id)
+ self.message.setLabel("%s %s..." % (lang(30610), server['Name']))
+ self.message_box.setVisibleCondition('True')
+ self.busy.setVisibleCondition('True')
+ result = self.connect_manager.connectToServer(server)
+
+ if result['State'] == CONN_STATE['Unavailable']:
+ self.busy.setVisibleCondition('False')
+ self.message.setLabel(lang(30609))
+ return False
+ else:
+ xbmc.sleep(1000)
+ self._selected_server = result['Servers'][0]
+ return True
diff --git a/resources/lib/dialogs/servermanual.py b/resources/lib/dialogs/servermanual.py
new file mode 100644
index 00000000..d54199eb
--- /dev/null
+++ b/resources/lib/dialogs/servermanual.py
@@ -0,0 +1,145 @@
+# -*- coding: utf-8 -*-
+
+##################################################################################################
+
+import logging
+import os
+
+import xbmcgui
+import xbmcaddon
+
+import connect.connectionmanager as connectionmanager
+from utils import language as lang
+
+##################################################################################################
+
+log = logging.getLogger("EMBY."+__name__)
+addon = xbmcaddon.Addon('plugin.video.emby')
+
+CONN_STATE = connectionmanager.ConnectionState
+ACTION_PARENT_DIR = 9
+ACTION_PREVIOUS_MENU = 10
+ACTION_BACK = 92
+CONNECT = 200
+CANCEL = 201
+ERROR_TOGGLE = 202
+ERROR_MSG = 203
+ERROR = {
+ 'Invalid': 1,
+ 'Empty': 2
+}
+
+##################################################################################################
+
+
+class ServerManual(xbmcgui.WindowXMLDialog):
+
+ _server = None
+ error = None
+
+
+ def __init__(self, *args, **kwargs):
+
+ xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
+
+ def set_connect_manager(self, connect_manager):
+ self.connect_manager = connect_manager
+
+ def is_connected(self):
+ return True if self._server else False
+
+ def get_server(self):
+ return self._server
+
+ def onInit(self):
+
+ self.connect_button = self.getControl(CONNECT)
+ self.cancel_button = self.getControl(CANCEL)
+ self.error_toggle = self.getControl(ERROR_TOGGLE)
+ self.error_msg = self.getControl(ERROR_MSG)
+ self.host_field = self._add_editcontrol(725, 400, 40, 500)
+ self.port_field = self._add_editcontrol(725, 525, 40, 500)
+
+ self.port_field.setText('8096')
+ self.setFocus(self.host_field)
+
+ self.host_field.controlUp(self.cancel_button)
+ self.host_field.controlDown(self.port_field)
+ self.port_field.controlUp(self.host_field)
+ self.port_field.controlDown(self.connect_button)
+ self.connect_button.controlUp(self.port_field)
+ self.cancel_button.controlDown(self.host_field)
+
+ def onClick(self, control):
+
+ if control == CONNECT:
+ # Sign in to emby connect
+ self._disable_error()
+
+ server = self.host_field.getText()
+ port = self.port_field.getText()
+
+ if not server or not port:
+ # Display error
+ self._error(ERROR['Empty'], lang(30617))
+ log.error("Server or port cannot be null")
+
+ elif self._connect_to_server(server, port):
+ self.close()
+
+ elif control == CANCEL:
+ # Remind me later
+ self.close()
+
+ def onAction(self, action):
+
+ if self.error == ERROR['Empty'] and self.host_field.getText() and self.port_field.getText():
+ self._disable_error()
+
+ if action in (ACTION_BACK, ACTION_PARENT_DIR, ACTION_PREVIOUS_MENU):
+ self.close()
+
+ def _add_editcontrol(self, x, y, height, width):
+
+ media = os.path.join(addon.getAddonInfo('path'), 'resources', 'skins', 'default', 'media')
+ control = xbmcgui.ControlEdit(0, 0, 0, 0,
+ label="User",
+ font="font10",
+ textColor="ffc2c2c2",
+ focusTexture=os.path.join(media, "button-focus.png"),
+ noFocusTexture=os.path.join(media, "button-focus.png"))
+ control.setPosition(x, y)
+ control.setHeight(height)
+ control.setWidth(width)
+
+ self.addControl(control)
+ return control
+
+ def _connect_to_server(self, server, port):
+
+ server_address = "%s:%s" % (server, port)
+ self._message("%s %s..." % (lang(30610), server_address))
+ result = self.connect_manager.connectToAddress(server_address)
+
+ if result['State'] == CONN_STATE['Unavailable']:
+ self._message(lang(30609))
+ return False
+ else:
+ self._server = result['Servers'][0]
+ return True
+
+ def _message(self, message):
+
+ self.error_msg.setLabel(message)
+ self.error_toggle.setVisibleCondition('True')
+
+ def _error(self, state, message):
+
+ self.error = state
+ self.error_msg.setLabel(message)
+ self.error_toggle.setVisibleCondition('True')
+
+ def _disable_error(self):
+
+ self.error = None
+ self.error_toggle.setVisibleCondition('False')
diff --git a/resources/lib/dialogs/usersconnect.py b/resources/lib/dialogs/usersconnect.py
new file mode 100644
index 00000000..770b0a2c
--- /dev/null
+++ b/resources/lib/dialogs/usersconnect.py
@@ -0,0 +1,104 @@
+# -*- coding: utf-8 -*-
+
+##################################################################################################
+
+import logging
+
+import xbmc
+import xbmcgui
+
+##################################################################################################
+
+log = logging.getLogger("EMBY."+__name__)
+
+ACTION_PARENT_DIR = 9
+ACTION_PREVIOUS_MENU = 10
+ACTION_BACK = 92
+ACTION_SELECT_ITEM = 7
+ACTION_MOUSE_LEFT_CLICK = 100
+LIST = 155
+MANUAL = 200
+CANCEL = 201
+
+##################################################################################################
+
+
+class UsersConnect(xbmcgui.WindowXMLDialog):
+
+ _user = None
+ _manual_login = False
+
+
+ def __init__(self, *args, **kwargs):
+
+ self.kodi_version = int(xbmc.getInfoLabel('System.BuildVersion')[:2])
+ xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
+
+ def set_server(self, server):
+ self.server = server
+
+ def set_users(self, users):
+ self.users = users
+
+ def is_user_selected(self):
+ return True if self._user else False
+
+ def get_user(self):
+ return self._user
+
+ def is_manual_login(self):
+ return self._manual_login
+
+
+ def onInit(self):
+
+ self.list_ = self.getControl(LIST)
+ for user in self.users:
+ user_image = ("userflyoutdefault2.png" if 'PrimaryImageTag' not in user
+ else self._get_user_artwork(user['Id'], 'Primary'))
+ self.list_.addItem(self._add_listitem(user['Name'], user['Id'], user_image))
+
+ self.setFocus(self.list_)
+
+ def _add_listitem(self, label, user_id, user_image):
+
+ item = xbmcgui.ListItem(label)
+ item.setProperty('id', user_id)
+ if self.kodi_version > 15:
+ item.setArt({'Icon': user_image})
+ else:
+ item.setIconImage(user_image)
+
+ return item
+
+ def onAction(self, action):
+
+ if action in (ACTION_BACK, ACTION_PREVIOUS_MENU, ACTION_PARENT_DIR):
+ self.close()
+
+ if action in (ACTION_SELECT_ITEM, ACTION_MOUSE_LEFT_CLICK):
+
+ if self.getFocusId() == LIST:
+ user = self.list_.getSelectedItem()
+ selected_id = user.getProperty('id')
+ log.info('User Id selected: %s', selected_id)
+
+ for user in self.users:
+ if user['Id'] == selected_id:
+ self._user = user
+ break
+
+ self.close()
+
+ def onClick(self, control):
+
+ if control == MANUAL:
+ self._manual_login = True
+ self.close()
+
+ elif control == CANCEL:
+ self.close()
+
+ def _get_user_artwork(self, user_id, item_type):
+ # Load user information set by UserClient
+ return "%s/emby/Users/%s/Images/%s?Format=original" % (self.server, user_id, item_type)
diff --git a/resources/lib/kodimonitor.py b/resources/lib/kodimonitor.py
index 5cac1315..589115d6 100644
--- a/resources/lib/kodimonitor.py
+++ b/resources/lib/kodimonitor.py
@@ -42,28 +42,18 @@ class KodiMonitor(xbmc.Monitor):
window('plex_kodiScan', clear=True)
def onSettingsChanged(self):
- # Monitor emby settings
- # Review reset setting at a later time, need to be adjusted to account for initial setup
- # changes.
- '''currentPath = settings('useDirectPaths')
- if window('plex_pluginpath') != currentPath:
- # Plugin path value changed. Offer to reset
- log.info("Changed to playback mode detected")
- window('plex_pluginpath', value=currentPath)
- resp = xbmcgui.Dialog().yesno(
- heading="Playback mode change detected",
- line1=(
- "Detected the playback mode has changed. The database "
- "needs to be recreated for the change to be applied. "
- "Proceed?"))
- if resp:
- utils.reset()'''
-
+ """
+ Monitor the PKC settings for changes made by the user
+ """
currentLog = settings('logLevel')
if window('plex_logLevel') != currentLog:
# The log level changed, set new prop
log.debug("New log level: %s" % currentLog)
window('plex_logLevel', value=currentLog)
+ current_context = "true" if settings('enableContext') == "true" else ""
+ if window('plex_context') != current_context:
+ log.info("New context setting: %s", current_context)
+ window('plex_context', value=current_context)
@CatchExceptions(warnuser=False)
def onNotification(self, sender, method, data):
diff --git a/resources/lib/utils.py b/resources/lib/utils.py
index ceae438a..61666041 100644
--- a/resources/lib/utils.py
+++ b/resources/lib/utils.py
@@ -73,6 +73,29 @@ def language(stringid):
return ADDON.getLocalizedString(stringid)
+def dialog(type_, *args, **kwargs):
+
+ d = xbmcgui.Dialog()
+
+ if "icon" in kwargs:
+ kwargs['icon'] = kwargs['icon'].replace(
+ "{plex}",
+ "special://home/addons/plugin.video.plexkodiconnect/icon.png")
+ if "heading" in kwargs:
+ kwargs['heading'] = kwargs['heading'].replace("{plex}",
+ language(29999))
+
+ types = {
+ 'yesno': d.yesno,
+ 'ok': d.ok,
+ 'notification': d.notification,
+ 'input': d.input,
+ 'select': d.select,
+ 'numeric': d.numeric
+ }
+ return types[type_](*args, **kwargs)
+
+
def tryEncode(uniString, encoding='utf-8'):
"""
Will try to encode uniString (in unicode) to encoding. This possibly
diff --git a/resources/settings.xml b/resources/settings.xml
index 9c18a978..bcaca8be 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -38,6 +38,8 @@
+
+
@@ -117,7 +119,6 @@
-
- 320
- 30
- left
- 40
- 100%
- font16
- ffeeeeee
-
-
-
- separator
- -10
- 103
- 101%
- 1
- separator.png
-
-
- 50
- 600
- vertical
- left
- 20
-
-
- 8
- 8012
- 8012
- 100
- 785
- left
- 70
- radio-on.png
- radio-off.png
- white.png
- 750
- 32
- 32
- 30
- B3dddddd
-
-
-
-
-
-
- separator
- 70
- -10
- 101%
- 1
- separator.png
-
-
- Save
- 150
- 20
- 230
- 8011
- 8013
- 8013
- font14
-
- FFededed
- B3dddddd
- FF000000
- 40
- ff333333
- box.png
- box.png
-
-
- Cancel
- 430
- 20
- 230
- 8011
- 8012
- 8012
- font14
-
- FFededed
- B3dddddd
- FF000000
- 40
- ff333333
- box.png
- box.png
-
-
-
-
-
\ No newline at end of file
diff --git a/resources/skins/default/media/emby-icon.png b/resources/skins/default/media/emby-icon.png
new file mode 100644
index 00000000..52a30539
Binary files /dev/null and b/resources/skins/default/media/emby-icon.png differ
diff --git a/resources/skins/default/media/separator.png b/resources/skins/default/media/emby-separator.png
similarity index 100%
rename from resources/skins/default/media/separator.png
rename to resources/skins/default/media/emby-separator.png
diff --git a/resources/skins/default/media/fading_circle.png b/resources/skins/default/media/fading_circle.png
new file mode 100644
index 00000000..56aea399
Binary files /dev/null and b/resources/skins/default/media/fading_circle.png differ
diff --git a/resources/skins/default/media/network.png b/resources/skins/default/media/network.png
new file mode 100644
index 00000000..7cd11ddf
Binary files /dev/null and b/resources/skins/default/media/network.png differ
diff --git a/resources/skins/default/media/user_image.png b/resources/skins/default/media/user_image.png
new file mode 100644
index 00000000..194a78b1
Binary files /dev/null and b/resources/skins/default/media/user_image.png differ
diff --git a/resources/skins/default/media/userflyoutdefault.png b/resources/skins/default/media/userflyoutdefault.png
new file mode 100644
index 00000000..046676e5
Binary files /dev/null and b/resources/skins/default/media/userflyoutdefault.png differ
diff --git a/resources/skins/default/media/userflyoutdefault2.png b/resources/skins/default/media/userflyoutdefault2.png
new file mode 100644
index 00000000..24d771eb
Binary files /dev/null and b/resources/skins/default/media/userflyoutdefault2.png differ
diff --git a/resources/skins/default/media/wifi.png b/resources/skins/default/media/wifi.png
new file mode 100644
index 00000000..2a646c55
Binary files /dev/null and b/resources/skins/default/media/wifi.png differ
diff --git a/service.py b/service.py
index efdbd2d8..799b91cd 100644
--- a/service.py
+++ b/service.py
@@ -50,7 +50,7 @@ import PlexCompanion
import loghandler
loghandler.config()
-log = logging.getLogger("PLEX.default")
+log = logging.getLogger("PLEX.service")
addonName = 'PlexKodiConnect'
###############################################################################
@@ -77,6 +77,8 @@ class Service():
window('plex_logLevel', value=str(logLevel))
window('plex_kodiProfile',
value=xbmc.translatePath("special://profile"))
+ window('plex_context',
+ value='true' if settings('enableContext') == "true" else "")
# Initial logging
log.warn("======== START %s ========" % addonName)