def reloadSettings(self): self.readerOn = not Settings.getSetting(Settings.READER_OFF, False) # OldLogger.reload() self.speakListCount = Settings.getSetting(Settings.SPEAK_LIST_COUNT, True) self.autoItemExtra = False if Settings.getSetting(Settings.AUTO_ITEM_EXTRA, False): self.autoItemExtra = Settings.getSetting( Settings.AUTO_ITEM_EXTRA_DELAY, 2)
def preInstalledFirstRun(): if not SystemQueries.isPreInstalled( ): # Do as little as possible if there is no pre-install if SystemQueries.wasPreInstalled(): module_logger.info('PRE INSTALL: REMOVED') # Set version to 0.0.0 so normal first run will execute and fix the # keymap Settings.setSetting('version', '0.0.0') enabler.markPreOrPost() # Update the install status return False lastVersion = Settings.getSetting('version') if not enabler.isPostInstalled() and SystemQueries.wasPostInstalled(): module_logger.info('POST INSTALL: UN-INSTALLED OR REMOVED') # Add-on was removed. Assume un-installed and treat this as a # pre-installed first run to disable the addon elif lastVersion: enabler.markPreOrPost() # Update the install status return False # Set version to 0.0.0 so normal first run will execute on first enable Settings.setSetting('version', '0.0.0') module_logger.info('PRE-INSTALLED FIRST RUN') module_logger.info('Installing basic keymap') # Install keymap with just F12 enabling included from utils import keymapeditor keymapeditor.installBasicKeymap() module_logger.info('Pre-installed - DISABLING') enabler.disableAddon() return True
def save_sound_file(cls, text_to_voice, # type: str suffix, # type: str voiced_text # type: bytes ): # type: (str, str, bytes) -> None """ Write the given voiced text to the cache """ path = VoiceCache.get_path_to_voice_file(text_to_voice, suffix) cache_directory = Settings.getSetting(Settings.CACHE_PATH, Constants.DEFAULT_CACHE_DIRECTORY) try: if not os.path.exists(cache_directory): try: os.makedirs(cache_directory) except Exception as e: cls._logger.error( 'Can not create cache directory: {}'.format(cache_directory)) if os.path.exists(path) and not os.access(path, os.W_OK): cls._logger.error('Can not write cache file: {}'.format(path)) with io.open(path, mode='wb') as cacheFile: cacheFile.write(voiced_text) cacheFile.flush() except Exception as e: cls._logger.error('Can not write cache file: {}'.format(path))
def checkNewVersion(self): try: # Fails on Helix beta 1 on OpenElec #1103 from distutils.version import LooseVersion except ImportError: def LooseVersion(v): comp = [int(x) for x in re.split(r'a|b', v)[0].split(".")] fourth = 2 fifth = 0 if 'b' in v: fourth = 1 fifth = int(v.split('b')[-1] or 0) elif 'a' in 'v': fourth = 0 fifth = int(v.split('a')[-1] or 0) comp.append(fourth) comp.append(fifth) return comp lastVersion = Settings.getSetting('version', '0.0.0') Settings.setSetting(Settings.VERSION, __version__) if lastVersion == '0.0.0': self.firstRun() return True elif LooseVersion(lastVersion) < LooseVersion(__version__): self.queueNotice('{0}... {1}'.format( Messages.get_msg(Messages.NEW_TTS_VERSION), __version__)) return True return False
def selectSetting(cls, provider, setting, *args): import backends settingsList = backends.getSettingsList(provider, setting, *args) if not settingsList: xbmcgui.Dialog().ok(T(32182), T(32186)) return displays = [] for ID, display in settingsList: displays.append(display) # xbmcgui.Dialog().select((heading, list[, autoclose, preselect, # useDetails]) auto_close = -1 current_value = Settings.getSetting(setting) current_index = -1 if current_value is not None: current_index = displays.index(str(current_value)) idx = xbmcgui.Dialog().select(T(32187), displays, auto_close, current_index) if idx < 0: return choice = displays[idx] cls._logger.info('Setting {0} for {1} set to: {2}'.format( setting, provider, choice)) Settings.setSetting('{0}.{1}'.format(setting, provider), choice)
def setSetting(cls, key: str, value: Union[None, str, List, bool, int, float] ) -> bool: """ Saves a setting to addon's settings.xml A convenience method for Settings.setSetting(key + '.' + cls.provider, value) :param key: :param value: :return: """ if (not cls.isSettingSupported(key) and cls._logger.isEnabledFor(LazyLogger.WARNING)): cls._logger.warning('Setting: {}, not supported by voicing engine: {}' .format(key, cls.get_provider_name())) fully_qualified_key = key if key not in Settings.TOP_LEVEL_SETTINGS: fully_qualified_key = '{}.{}'.format(key, cls.provider) previous_value = Settings.getSetting(fully_qualified_key, None, setting_type=type(value)) changed = False if previous_value != value: changed = True Settings.setSetting(fully_qualified_key, value) return changed
def setOutDir(self): tmpfs = utils.getTmpfs() if Settings.getSetting(Settings.USE_TEMPFS, True) and tmpfs: self._logger.debug_extra_verbose( 'Using tmpfs at: {0}'.format(tmpfs)) self.outDir = os.path.join(tmpfs, 'kodi_speech') else: self.outDir = os.path.join(Constants.PROFILE_PATH, 'kodi_speech') if not os.path.exists(self.outDir): os.makedirs(self.outDir)
def visible(self): visible = self._visible() if visible: if not Settings.getSetting(Settings.SPEAK_BACKGROUND_PROGRESS, False): return False else: if self._win: return True return visible
def get_engine(self): # Deliberately using Settings.getSetting here if self.engine is None or self.settings_changed: self.engine = Settings.getSetting( Settings.BACKEND, Settings.BACKEND_DEFAULT) # type: str if self.engine == Settings.BACKEND_DEFAULT: # 'auto' self.engine = backends.getAvailableBackends()[0].provider self.set_backend(self.engine) return self.engine
def getBackend(provider: str = Settings.BACKEND_DEFAULT) -> TTSBackendBase: if module_logger.isEnabledFor(LazyLogger.DEBUG_VERBOSE): module_logger.debug_verbose('backends.__init__.getBackend provider: {}' .format(str(provider))) provider = Settings.getSetting('backend') or provider b = getBackendByProvider(provider) if not b or not b._available(): for b in backendsByPriority: if b._available(): break return b
def clean_cache(cls, purge=False): return dummy_cached_file = VoiceCache.get_path_to_voice_file('', '') cache_directory, _ = os.path.split(dummy_cached_file) expiration_time = time.time() - \ Settings.getSetting( 'cache_expiration_days', 30) * 86400 for root, dirs, files in os.walk(cache_directory, topdown=False): for file in files: try: path = os.path.join(root, file) if purge or os.stat(path).st_mtime < expiration_time: cls._logger.debug_verbose('Deleting: {}'.format(path)) os.remove(path) except Exception as e: pass
def getSetting(cls, key, default=None): """ Gets a setting from addon's settings.xml A convenience method equivalent to Settings.getSetting(key + '.'. + cls.provider, default, useFullSettingName). :param key: :param default: :param useFullSettingName: :return: """ fully_qualified_key = key if key not in Settings.TOP_LEVEL_SETTINGS: fully_qualified_key = '{}.{}'.format(key, cls.provider) if default is None: default = cls.get_setting_default(key) return Settings.getSetting(fully_qualified_key, default)
def get_sound_file_path(cls, text_to_voice, suffix): path = VoiceCache.get_path_to_voice_file(text_to_voice, suffix) exception_occurred = False file_exists = False try: if not os.path.exists(path): cls._logger.debug_verbose( 'Not cached: {} {}'.format(text_to_voice, path)) return path, file_exists if not os.access(path, os.R_OK): cls._logger.debug_verbose( 'VoiceCache.get_sound_file- Can not read cache file: {}'.format(path)) return path, file_exists expiration_time = time.time() - \ datetime.timedelta(Settings.getSetting( Settings.CACHE_EXPIRATION_DAYS, Settings.CACHE_EXPIRATION_DEFAULT)).total_seconds() if os.stat(path).st_mtime < expiration_time: cls._logger.debug_verbose( 'VoiceCache.get_sound_file- Expired sound file: {}'.format(path)) return path, file_exists except Exception as e: cls._logger.error( 'Exception accessing voice file: {}'.format(path)) cls._logger.error(str(e)) exception_occurred = True try: # Blow away bad cache file if exception_occurred and path is not None: os.remove(path) except Exception as e: cls._logger.error('Trying to delete bad cache file.') file_exists = True return path, file_exists
def _available(cls): if cls.broken and Settings.getSetting(Settings.DISABLE_BROKEN_BACKENDS, True): return False return cls.available()
def processCommand(self, command, data=None): from utils import util # Earlier import apparently not seen when called via NotifyAll self._logger.debug('command', command) if command == 'REPEAT': self.repeatText() elif command == 'EXTRA': self.sayExtra() elif command == 'ITEM_EXTRA': self.sayItemExtra() elif command == 'VOL_UP': self.volumeUp() elif command == 'VOL_DOWN': self.volumeDown() elif command == 'STOP': self.stopSpeech() elif command == 'SHUTDOWN': self.shutdown() elif command == 'SAY': if not data: return args = json.loads(data) if not args: return text = args.get('text') if text: self.queueNotice(text, args.get('interrupt')) if command == 'PREPARE_TO_SAY': # Used to preload text cache when caller anticipates text will be voiced if not data: return args = json.loads(data) if not args: return text = args.get('text') if text: self.queueNotice(text, interrupt=False, preload_cache=True) elif command == 'SETTINGS.BACKEND_GUI': util.runInThread(SettingsGUI.launch, name='SETTINGS.BACKEND_GUI') elif command == 'SETTINGS.BACKEND_DIALOG': util.runInThread(ConfigUtils.selectBackend, name='SETTINGS.BACKEND_DIALOG') elif command == 'SETTINGS.PLAYER_DIALOG': # if not data: # return # args = json.loads(data) # if not args: # return # backend = args.get('backend') provider = Settings.getSetting('backend') ConfigUtils.selectPlayer(provider) elif command == 'SETTINGS.SETTING_DIALOG': if not data: return provider = Settings.getSetting('backend') args = json.loads(data) if args[0] == 'voice': voice = args[0] ConfigUtils.selectSetting(provider, voice) elif args[0] == 'language': language = args[0] ConfigUtils.selectSetting(provider, language) elif args[0] == 'gender': ConfigUtils.selectGenderSetting(provider) elif command == 'SETTINGS.SETTING_SLIDER': if not data: return args = json.loads(data) provider = Settings.getSetting('backend') if args[0] == 'volume': ConfigUtils.selectVolumeSetting(provider, *args) elif command == 'RELOAD_ENGINE': self.checkBackend()
def __init__(self, *args, **kwargs): # type: (*Any, **Any) -> None """ :param args: """ # xbmc.executebuiltin('Skin.ToggleDebug') self._logger = module_logger.getChild( self.__class__.__name__) # type: LazyLogger self._initialized = False self.exit_dialog = False super().__init__(*args) self.api_key = None self.engine = None self.backend_instance = None self.backend_class = None self.backend_changed = False self.gender = None self.language = None self.pitch = None self.player = None self.speed = None self.volume = None self._configure_temp_settings_enabled = False self.settings_changed = False self.previous_backend = None initial_backend = Settings.getSetting(Settings.BACKEND, Settings.BACKEND_DEFAULT) if initial_backend == Settings.BACKEND_DEFAULT: # 'auto' initial_backend = backends.getAvailableBackends()[0].provider self.set_backend(initial_backend) else: self.get_backend_class(backend_id=initial_backend) self._logger.debug_extra_verbose('SettingsDialog.__init__') self.header = None # type: Union[None, xbmcgui.ControlLabel] self.engine_tab = None # type: Union[None, xbmcgui.ControlButton] self.options_tab = None # type: Union[None, xbmcgui.ControlButton] self.keymap_tab = None # type: Union[None, xbmcgui.ControlButton] self.advanced_tab = None # type: Union[None, xbmcgui.ControlButton] self.engine_group = None # type: Union[None, xbmcgui.Control] self.options_group = None # type: Union[None, xbmcgui.ControlGroup] self.keymap_group = None # type: Union[None, xbmcgui.ControlGroup] self.advanced_group = None # type: Union[None, xbmcgui.ControlGroup] self.ok_button = None # type: Union[None, xbmcgui.ControlButton] self.cancel_button = None # type: Union[None, xbmcgui.ControlButton] self.defaults_button = None # type: Union[None, xbmcgui.ControlButton] # type: Union[None, xbmcgui.ControlButton] self.engine_engine_button = None # type: Union[None, xbmcgui.ControlLabel] self.engine_engine_value: Union[None, xbmcgui.ControlButton] = None self.engine_language_group = None self.engine_language_button = None # type: Union[None, xbmcgui.ControlLabel] self.engine_language_value = None # type: Union[None, xbmcgui.ControlButton] self.engine_voice_button = None # type: Union[None, xbmcgui.ControlLabel] self.engine_voice_value = None # type: Union[None, xbmcgui.ControlButton] self.engine_gender_button = None # type: Union[None, xbmcgui.ControlLabel] self.engine_gender_value = None # type: Union[None, xbmcgui.ControlGroup] self.engine_pitch_group = None # type: Union[None, xbmcgui.ControlSlider] self.engine_pitch_slider = None # type: Union[None, xbmcgui.ControlLabel] self.engine_pitch_label = None # type: Union[None, xbmcgui.ControlButton] self.engine_player_button = None # type: Union[None, xbmcgui.ControlLabel] self.engine_player_value = None # type: Union[None, xbmcgui.ControlGroup] self.engine_pipe_audio_group = None # type: Union[None, xbmcgui.ControlRadioButton] self.engine_pipe_audio_radio_button = None # type: Union[None, xbmcgui.ControlGroup] self.engine_speed_group = None # type: Union[None, xbmcgui.ControlSlider] self.engine_speed_slider = None # type: Union[None, xbmcgui.ControlLabel] self.engine_speed_label = None # type: Union[None, xbmcgui.ControlGroup] self.engine_volume_group = None # type: Union[None, xbmcgui.ControlSlider] self.engine_volume_slider = None # type: Union[None, xbmcgui.ControlLabel] # type: Union[None, xbmcgui.ControlLabel] self.engine_volume_label = None # type: Union[None, xbmcgui.ControlGroup] self.engine_api_key_group = None # self.engine_api_key_label = None # type: Union[None, xbmcgui.ControlEdit] # type: Union[None, xbmcgui.ControlEdit] self.engine_api_key_edit = None self.options_dummy_button = None # type: Union[None, xbmcgui.ControlButton] self.keymap_dummy_button = None # type: Union[None, xbmcgui.ControlButton] self.advanced_dummy_button = None self._initialized = False
def checkBackend(self): provider = Settings.getSetting('backend', None) if provider == self.backendProvider: return self.initTTS(changed=True)
def loadAddonsMD5(): module_logger.debug_verbose('addoninfo.loadAddonsMD5') return Settings.getSetting('addons_MD5')
def updateInterval(self): if Settings.getSetting(Settings.OVERRIDE_POLL_INTERVAL, False): self.interval = Settings.getSetting(Settings.POLL_INTERVAL, self.tts.interval) else: self.interval = self.tts.interval
def getSetting(key, default=None): return Settings.getSetting(key, default)
def updateFromSettings(self): self.last = 0 self.interval = Settings.getSetting( Settings.BACKGROUND_PROGRESS_INTERVAL, 5) self.playDuringMedia = Settings.getSetting( Settings.SPEAK_BACKGROUND_PROGRESS_DURING_MEDIA, False)
def get_path_to_voice_file(text_to_voice, suffix): file_name = VoiceCache.get_hash(text_to_voice) + suffix cache_directory = Settings.getSetting(Settings.CACHE_PATH) cache_directory = xbmcvfs.translatePath(cache_directory) path = os.path.join(cache_directory, file_name) return path