def init_globals(self, argv):
     """Initialized globally used module variables. Needs to be called at start of each plugin instance!"""
     # IS_ADDON_FIRSTRUN: specifies if the add-on has been initialized for the first time
     #                    (reuseLanguageInvoker not used yet)
     self.IS_ADDON_FIRSTRUN = self.IS_ADDON_FIRSTRUN is None
     self.IS_ADDON_EXTERNAL_CALL = False
     # xbmcaddon.Addon must be created at every instance otherwise it does not read any new changes to the settings
     self.ADDON = xbmcaddon.Addon()
     self.URL = urlparse(argv[0])
     self.REQUEST_PATH = unquote(self.URL[2][1:])
     try:
         self.PARAM_STRING = argv[2][1:]
     except IndexError:
         self.PARAM_STRING = ''
     self.REQUEST_PARAMS = dict(parse_qsl(self.PARAM_STRING))
     if self.IS_ADDON_FIRSTRUN:
         # Global variables that do not need to be generated at every instance
         self.ADDON_ID = self.ADDON.getAddonInfo('id')
         self.PLUGIN = self.ADDON.getAddonInfo('name')
         self.VERSION_RAW = self.ADDON.getAddonInfo('version')
         self.VERSION = remove_ver_suffix(self.VERSION_RAW)
         self.ICON = self.ADDON.getAddonInfo('icon')
         self.DEFAULT_FANART = self.ADDON.getAddonInfo('fanart')
         self.ADDON_DATA_PATH = self.ADDON.getAddonInfo(
             'path')  # Add-on folder
         self.DATA_PATH = self.ADDON.getAddonInfo(
             'profile')  # Add-on user data folder
         self.CACHE_PATH = os.path.join(self.DATA_PATH, 'cache')
         self.COOKIES_PATH = os.path.join(self.DATA_PATH, 'COOKIES')
         try:
             self.PLUGIN_HANDLE = int(argv[1])
             self.IS_SERVICE = False
             self.BASE_URL = '{scheme}://{netloc}'.format(
                 scheme=self.URL[0], netloc=self.URL[1])
         except IndexError:
             self.PLUGIN_HANDLE = 0
             self.IS_SERVICE = True
             self.BASE_URL = '{scheme}://{netloc}'.format(
                 scheme='plugin', netloc=self.ADDON_ID)
         from resources.lib.common.kodi_ops import GetKodiVersion
         self.KODI_VERSION = GetKodiVersion()
     # Initialize the log
     from resources.lib.utils.logging import LOG
     LOG.initialize(self.ADDON_ID, self.PLUGIN_HANDLE,
                    self.ADDON.getSettingBool('enable_debug'),
                    self.ADDON.getSettingBool('enable_timing'))
     if self.IS_ADDON_FIRSTRUN:
         self.init_database()
         # Initialize the cache
         if self.IS_SERVICE:
             from resources.lib.services.cache_management import CacheManagement
             self.CACHE_MANAGEMENT = CacheManagement()
             self.CACHE = self.CACHE_MANAGEMENT
             from resources.lib.services.settings_monitor import SettingsMonitor
             self.SETTINGS_MONITOR = SettingsMonitor()
         else:
             from resources.lib.common.cache import Cache
             self.CACHE = Cache()
     self.IPC_OVER_HTTP = self.ADDON.getSettingBool('enable_ipc_over_http')
    def init_globals(self,
                     argv,
                     reinitialize_database=False,
                     reload_settings=False):
        """Initialized globally used module variables. Needs to be called at start of each plugin instance!"""
        # IS_ADDON_FIRSTRUN: specifies if the add-on has been initialized for the first time
        #                    (reuseLanguageInvoker not used yet)
        self.IS_ADDON_FIRSTRUN = self.IS_ADDON_FIRSTRUN is None
        self.IS_ADDON_EXTERNAL_CALL = False
        # xbmcaddon.Addon must be created at every instance otherwise it does not read any new changes to the settings
        self.ADDON = xbmcaddon.Addon()
        self.URL = urlparse(argv[0])
        self.REQUEST_PATH = G.py2_decode(unquote(self.URL[2][1:]))
        try:
            self.PARAM_STRING = argv[2][1:]
        except IndexError:
            self.PARAM_STRING = ''
        self.REQUEST_PARAMS = dict(parse_qsl(self.PARAM_STRING))
        if self.IS_ADDON_FIRSTRUN:
            # Global variables that do not need to be generated at every instance
            self.ADDON_ID = self.py2_decode(self.ADDON.getAddonInfo('id'))
            self.PLUGIN = self.py2_decode(self.ADDON.getAddonInfo('name'))
            self.VERSION_RAW = self.py2_decode(
                self.ADDON.getAddonInfo('version'))
            self.VERSION = self.remove_ver_suffix(self.VERSION_RAW)
            self.ICON = self.py2_decode(self.ADDON.getAddonInfo('icon'))
            self.DEFAULT_FANART = self.py2_decode(
                self.ADDON.getAddonInfo('fanart'))
            self.ADDON_DATA_PATH = self.py2_decode(
                self.ADDON.getAddonInfo('path'))  # Add-on folder
            self.DATA_PATH = self.py2_decode(
                self.ADDON.getAddonInfo('profile'))  # Add-on user data folder
            self.CACHE_PATH = os.path.join(self.DATA_PATH, 'cache')
            self.COOKIE_PATH = os.path.join(self.DATA_PATH, 'COOKIE')
            try:
                self.PLUGIN_HANDLE = int(argv[1])
                self.IS_SERVICE = False
                self.BASE_URL = '{scheme}://{netloc}'.format(
                    scheme=self.URL[0], netloc=self.URL[1])
            except IndexError:
                self.PLUGIN_HANDLE = 0
                self.IS_SERVICE = True
                self.BASE_URL = '{scheme}://{netloc}'.format(
                    scheme='plugin', netloc=self.ADDON_ID)
        # Add absolute paths of embedded py packages (packages not supplied by Kodi)
        packages_paths = [
            os.path.join(self.ADDON_DATA_PATH, 'packages',
                         'mysql-connector-python')
        ]
        # On PY2 sys.path list can contains values as unicode type and string type at same time,
        #   here we will add only unicode type so filter values by unicode.
        #   This fixes comparison errors between str/unicode
        sys_path_filtered = [
            value for value in sys.path if isinstance(value, unicode)
        ]
        for path in packages_paths:  # packages_paths has unicode type values
            path = G.py2_decode(xbmc.translatePath(path))
            if path not in sys_path_filtered:
                # Add embedded package path to python system directory
                # The "path" will add an unicode type to avoids problems with OS using symbolic characters
                sys.path.insert(0, path)

        # Initialize the log
        from resources.lib.utils.logging import LOG
        LOG.initialize(self.ADDON_ID, self.PLUGIN_HANDLE,
                       self.ADDON.getSettingString('debug_log_level'),
                       self.ADDON.getSettingBool('enable_timing'))

        self._init_database(self.IS_ADDON_FIRSTRUN or reinitialize_database)

        if self.IS_ADDON_FIRSTRUN or reload_settings:
            # Put here all the global variables that need to be updated when the user changes the add-on settings
            self.IPC_OVER_HTTP = self.ADDON.getSettingBool(
                'enable_ipc_over_http')
            # Initialize the cache
            self.CACHE_TTL = self.ADDON.getSettingInt('cache_ttl') * 60
            self.CACHE_MYLIST_TTL = self.ADDON.getSettingInt(
                'cache_mylist_ttl') * 60
            self.CACHE_METADATA_TTL = self.ADDON.getSettingInt(
                'cache_metadata_ttl') * 24 * 60 * 60
            if self.IS_SERVICE:
                from resources.lib.services.cache.cache_management import CacheManagement
                self.CACHE_MANAGEMENT = CacheManagement()
            from resources.lib.common.cache import Cache
            self.CACHE = Cache()
        self.settings_monitor_suspend(
            False)  # Reset the value in case of addon crash
        from resources.lib.common.kodi_ops import GetKodiVersion
        self.KODI_VERSION = GetKodiVersion()
    def _on_change(self):
        # Reinitialize the log settings
        LOG.initialize(G.ADDON_ID, G.PLUGIN_HANDLE,
                       G.ADDON.getSettingBool('enable_debug'),
                       G.ADDON.getSettingBool('enable_timing'))
        LOG.debug(
            'SettingsMonitor: settings have been changed, started checks')
        reboot_addon = False
        clean_buckets = []

        use_mysql = G.ADDON.getSettingBool('use_mysql')
        use_mysql_old = G.LOCAL_DB.get_value('use_mysql', False,
                                             TABLE_SETTINGS_MONITOR)
        use_mysql_turned_on = use_mysql and not use_mysql_old

        # Update global settings
        G.IPC_OVER_HTTP = G.ADDON.getSettingBool('enable_ipc_over_http')
        if use_mysql != use_mysql_old:
            G.init_database()
            clean_buckets.append(
                CACHE_COMMON
            )  # Need to be cleaned to reload the Exported menu content
        G.CACHE_MANAGEMENT.load_ttl_values()

        # Verify the MySQL connection status after execute init_database()
        use_mysql_after = G.ADDON.getSettingBool('use_mysql')
        if use_mysql_turned_on and use_mysql_after:
            G.LOCAL_DB.set_value('use_mysql', True, TABLE_SETTINGS_MONITOR)
            ui.show_notification(G.ADDON.getLocalizedString(30202))
        if not use_mysql_after and use_mysql_old:
            G.LOCAL_DB.set_value('use_mysql', False, TABLE_SETTINGS_MONITOR)

        # Check menu settings changes
        for menu_id, menu_data in G.MAIN_MENU_ITEMS.items():
            # Check settings changes in show/hide menu
            if menu_data.get('has_show_setting', True):
                show_menu_new_setting = bool(
                    G.ADDON.getSettingBool('_'.join(('show_menu', menu_id))))
                show_menu_old_setting = G.LOCAL_DB.get_value(
                    'menu_{}_show'.format(menu_id), True,
                    TABLE_SETTINGS_MONITOR)
                if show_menu_new_setting != show_menu_old_setting:
                    G.LOCAL_DB.set_value('menu_{}_show'.format(menu_id),
                                         show_menu_new_setting,
                                         TABLE_SETTINGS_MONITOR)
                    reboot_addon = True
            # Check settings changes in sort order of menu
            if menu_data.get('has_sort_setting'):
                menu_sortorder_new_setting = int(
                    G.ADDON.getSettingInt('menu_sortorder_' +
                                          menu_data['path'][1]))
                menu_sortorder_old_setting = G.LOCAL_DB.get_value(
                    'menu_{}_sortorder'.format(menu_id), 0,
                    TABLE_SETTINGS_MONITOR)
                if menu_sortorder_new_setting != menu_sortorder_old_setting:
                    G.LOCAL_DB.set_value('menu_{}_sortorder'.format(menu_id),
                                         menu_sortorder_new_setting,
                                         TABLE_SETTINGS_MONITOR)
                    clean_buckets += [CACHE_COMMON, CACHE_MYLIST, CACHE_SEARCH]

        # Checks for settings changes that require cache invalidation
        page_results = G.ADDON.getSettingInt('page_results')
        page_results_old = G.LOCAL_DB.get_value('page_results', 90,
                                                TABLE_SETTINGS_MONITOR)
        if page_results != page_results_old:
            G.LOCAL_DB.set_value('page_results', page_results,
                                 TABLE_SETTINGS_MONITOR)
            clean_buckets += [CACHE_COMMON, CACHE_MYLIST, CACHE_SEARCH]

        _check_msl_profiles(clean_buckets)
        _check_watched_status_sync()

        # Clean cache buckets if needed (to get new results and so on...)
        if clean_buckets:
            G.CACHE.clear([
                dict(t) for t in {tuple(d.items())
                                  for d in clean_buckets}
            ])  # Remove duplicates
        # Avoid perform these operations when the add-on is installed from scratch and there are no credentials
        if reboot_addon and not common.check_credentials():
            reboot_addon = False
        if reboot_addon:
            LOG.debug('SettingsMonitor: addon will be rebooted')
            # Open root page
            common.container_update(
                common.build_url(['root'], mode=G.MODE_DIRECTORY))