def end(self): if util.DEBUG: xbmc.sleep(500) #Give threads a chance to finish import threading util.LOG('Remaining Threads:') for t in threading.enumerate(): util.LOG(' {0}'.format(t.name))
def start(self): self.checkNewVersion() try: while (not xbmc.abortRequested) and (not self.stop): #Interface reader mode while self.readerOn and (not xbmc.abortRequested) and ( not self.stop): xbmc.sleep(self.interval) try: self.checkForText() except RuntimeError: util.ERROR('start()', hide_tb=True) except SystemExit: if util.DEBUG: util.ERROR('SystemExit: Quitting') else: util.LOG('SystemExit: Quitting') break except TTSClosedException: util.LOG('TTSCLOSED') except: #Because we don't want to kill speech on an error util.ERROR('start()', notify=True) self.initState( ) #To help keep errors from repeating on the loop #Idle mode while (not self.readerOn) and (not xbmc.abortRequested) and ( not self.stop): try: text, interrupt = self.noticeQueue.get_nowait() self.sayText(text, interrupt) self.noticeQueue.task_done() except Queue.Empty: pass except RuntimeError: util.ERROR('start()', hide_tb=True) except SystemExit: if util.DEBUG: util.ERROR('SystemExit: Quitting') else: util.LOG('SystemExit: Quitting') break except TTSClosedException: util.LOG('TTSCLOSED') except: #Because we don't want to kill speech on an error util.ERROR('start()', notify=True) self.initState( ) #To help keep errors from repeating on the loop for x in range( 5 ): #Check the queue every 100ms, check state every 500ms if self.noticeQueue.empty(): xbmc.sleep(100) finally: self._tts._close() self.end() util.playSound('off') util.LOG('SERVICE STOPPED') if self.disable: import enabler enabler.disableAddon()
def _read_status(self): ## Do non-blocking checks for server response until something arrives. setStoppable(True) try: while True: sel = select.select([self.fp.fileno()], [], [], 0) if len(sel[0]) > 0: break ## <--- Right here, check to see whether thread has requested to stop ## Also check to see whether timeout has elapsed if util.abortRequested(): if DEBUG: util.LOG(' -- XBMC requested abort during wait for server response: raising exception -- ') raise AbortRequestedException('httplib.HTTPResponse._read_status') elif STOP_REQUESTED: if DEBUG: util.LOG('Stop requested during wait for server response: raising exception') resetStopRequest() raise StopRequestedException('httplib.HTTPResponse._read_status') if self._prog_callback: if not self._prog_callback(-1): resetStopRequest() raise StopRequestedException('httplib.HTTPResponse._read_status') time.sleep(0.1) return httplib.HTTPResponse._read_status(self) finally: setStoppable(False) resetStopRequest()
def update(self): self.setPlayer(self.setting('player')) self.setMode(self.getMode()) self.setHTTPURL() self.perlServer = self.setting( 'perl_server') #Not really currently used version = self.getVersion() if version.startswith('speech.server'): if self.perlServer: util.LOG( 'Perl server not detected. Switch to speech.server mode.') self.perlServer = False elif version.startswith('perl.server'): if not self.perlServer: util.LOG( 'speech.server not detected. Switch to Perl server mode.') self.perlServer = True else: util.LOG('No server detected. Flagging as dead.') self.flagAsDead(reason=version) if self.perlServer: self.voice = self.setting('voice') else: self.engine = self.setting('engine') voice = self.setting('voice.{0}'.format(self.engine)) if voice: voice = '{0}.{1}'.format(self.engine, voice) self.voice = voice self.remote_pitch = self.setting('remote_pitch') self.remote_speed = self.setting('remote_speed') self.setSpeed(self.setting('player_speed')) self.remote_volume = self.setting('remote_volume') self.setVolume(self.setting('player_volume'))
def setMountForRecording(self, mount): if not self.removeRecordingsDir(): return util.LOG('Setting recording mount to: {0}'.format(util.cleanStrRepr(mount))) self.mount = mount self.mountPath = os.path.join(self.MEDIA_DIR_PATH, mount) self.recordingsPath = os.path.join(self.mountPath, 'recordings') self.timeshiftPath = os.path.join(self.mountPath, 'timeshift') self.mountID = self.writeID(mount) if not self.mountID: util.LOG('Failed to set recording mount to: {0}'.format(util.cleanStrRepr(mount))) return self.initRecordingMount() if not os.path.exists(self.recordingsPath): os.makedirs(self.recordingsPath) if not os.path.exists(self.timeshiftPath): os.makedirs(self.timeshiftPath) os.symlink(self.recordingsPath, self.RECORDINGS_PATH) self.save() self.enableRecording()
def preInstalledFirstRun(): if not util.isPreInstalled(): #Do as little as possible if there is no pre-install if util.wasPreInstalled(): util.LOG('PRE INSTALL: REMOVED') # Set version to 0.0.0 so normal first run will execute and fix the keymap util.setSetting('version','0.0.0') import enabler enabler.markPreOrPost() # Update the install status return False import enabler lastVersion = util.getSetting('version') if not enabler.isPostInstalled() and util.wasPostInstalled(): util.LOG('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 util.setSetting('version','0.0.0') util.LOG('PRE-INSTALLED FIRST RUN') util.LOG('Installing basic keymap') # Install keymap with just F12 enabling included from lib import keymapeditor keymapeditor.installBasicKeymap() util.LOG('Pre-installed - DISABLING') enabler.disableAddon() return True
def __init__(self): self._pollInterval = 5 self._nextDayChange = time.time() + (24 * 3600) self._nextHourChange = time.time() + 3600 self.recordingDriveWatcher = RecordingDriveWatcher() util.LOG('SERVICE START') self.start() util.LOG('SERVICE STOP')
def checkStop(): if util.abortRequested(): if DEBUG: util.LOG(' -- XBMC requested abort during wait for connection to server: raising exception -- ') raise AbortRequestedException('socket[asyncconnections].create_connection') elif STOP_REQUESTED: if DEBUG: util.LOG('Stop requested during wait for connection to server: raising exception') resetStopRequest() raise StopRequestedException('socket[asyncconnections].create_connection')
def cleanBadRecordings(cls): util.LOG('Cleaning un-authorized recordings') if os.path.exists(cls.RECORDINGS): cls.emptyDirectory(cls.RECORDINGS) else: util.LOG('Returning recording path to default state') try: os.unlink(cls.RECORDINGS) except: pass os.makedirs(cls.RECORDINGS)
def setEnabled(enable=True): global OLD_socket_create_connection, AsyncHTTPResponse, Handler if enable: if DEBUG: util.LOG('Asynchronous connections: Enabled') socket.create_connection = create_connection AsyncHTTPResponse = _AsyncHTTPResponse Handler = _Handler else: if DEBUG: util.LOG('Asynchronous connections: Disabled') AsyncHTTPResponse = httplib.HTTPResponse Handler = urllib2.HTTPHandler if OLD_socket_create_connection: socket.create_connection = OLD_socket_create_connection
def check(cls): try: if cls.checkValid(): util.LOG('Check oscam.server: VALID') return True util.LOG('Check oscam.server: INVALID!') cls.reactToInvalid() return False except: util.ERROR() return True
def setMode(self, mode): assert isinstance(mode, int), 'Bad mode' if mode == self.PIPE: if self.player.canPipe(): util.LOG('Mode: PIPE') else: mode = self.WAVOUT self.mode = mode if mode == self.WAVOUT: util.LOG('Mode: WAVOUT') elif mode == self.ENGINESPEAK: audio.load_snd_bm2835() util.LOG('Mode: ENGINESPEAK')
def freshenDirectory(path, days=7): if not os.path.exists(path): return util.LOG('emptyDirectory: {0} does not exist'.format(util.cleanStrRepr(path))) threshold = time.time() - days * 86400 for f in os.listdir(path): full = os.path.join(path, f) try: if os.stat(full).st_atime < threshold: if os.path.isfile(full): util.LOG('Removing file: {0}'.format(util.cleanStrRepr(full))) os.remove(full) except: util.ERROR()
def _handleQueue(self): util.LOG('Threaded TTS Started: {0}'.format(self.provider)) while self.active and not util.abortRequested(): try: text = self.queue.get(timeout=0.5) self.queue.task_done() if isinstance(text, int): time.sleep(text / 1000.0) else: self._threadedIsSpeaking = True self.threadedSay(text) self._threadedIsSpeaking = False except Queue.Empty: pass util.LOG('Threaded TTS Finished: {0}'.format(self.provider))
def emptyDirectory(path): if not os.path.exists(path): return util.LOG('emptyDirectory: {0} does not exist'.format(util.cleanStrRepr(path))) for sub in os.listdir(path): full = os.path.join(path, sub) try: if os.path.isfile(full): util.LOG('Removing file: {0}'.format(util.cleanStrRepr(full))) os.unlink(full) elif os.path.isdir(full): util.LOG('Removing dir: {0}'.format(util.cleanStrRepr(full))) shutil.rmtree(full) except Exception: util.ERROR()
def newMount(self, mount): mountPath = os.path.join(self.MEDIA_DIR_PATH, mount) if not os.path.ismount(mountPath): return False self.mounts.append(mount) self.save() util.LOG('New mount detected ({0}): {1}'.format(os.stat(mountPath).st_dev, util.cleanStrRepr(mount))) if mount == self.mount and self.mountID == self.getID(mount): util.LOG('Restoring recording mount: {0}'.format(util.cleanStrRepr(mount))) self.setMountForRecording(mount) return True
def setPlayer(self, preferred=None, advanced=None): if preferred == self._player.ID or preferred == self.preferred: return self._player self.preferred = preferred if advanced == None: advanced = self.advanced old = self._player player = None if preferred: player = self.getPlayerID(preferred) if player: self._player = player() elif advanced and self.hasAdvancedPlayer: for p in self.availablePlayers: if p._advanced: self._player = p() break elif self.availablePlayers: self._player = self.availablePlayers[0]() else: self._player = AudioPlayer() if self._player and old.ID != self._player: util.LOG('Player: %s' % self._player.name) if not self._player.ID == 'PlaySFX': load_snd_bm2835() #For Raspberry Pi return self._player
def StopConnection(): global STOP_REQUESTED if not STOPPABLE: STOP_REQUESTED = False return util.LOG('User requsted stop of connection') STOP_REQUESTED = True
def checkWindow(self, newN): winID = xbmcgui.getCurrentWindowId() dialogID = xbmcgui.getCurrentWindowDialogId() if dialogID != 9999: winID = dialogID if winID == self.winID: return newN self.winID = winID self.updateWindowReader() if util.DEBUG: util.LOG('Window ID: {0} Handler: {1} File: {2}'.format( winID, self.windowReader.ID, xbmc.getInfoLabel('Window.Property(xmlfile)'))) name = self.windowReader.getName() if name: self.sayText(u'{0}: {1}'.format(T(32105), name), interrupt=not newN) self.insertPause() else: self.sayText(u' ', interrupt=not newN) heading = self.windowReader.getHeading() if heading: self.sayText(heading) self.insertPause() texts = self.windowReader.getWindowTexts() if texts: self.insertPause() for t in texts: self.sayText(t) self.insertPause() return True
def cleanThumbnails(cls): util.LOG('Cleaning old thumbnails') for sub in cls.THUMB_SUBS: full = os.path.join(cls.THUMBNAILS, sub) if not os.path.exists(full): continue cls.freshenDirectory(full)
def fallbackTTS(self,reason=None): if reason == 'RESET': return resetAddon() backend = backends.getBackendFallback() util.LOG('Backend falling back to: {0}'.format(backend.provider)) self.initTTS(backend) self.sayText(T(32102).format(backend.displayName),interrupt=True) if reason: self.sayText(u'{0}: {1}'.format(T(32103),reason),interrupt=False)
def checker(self,*args,**kwargs): if not self.valid: util.LOG('SAPI: Broken - ignoring {0}'.format(func.__name__)) return None try: return func(self,*args,**kwargs) except self.COMError,e: self.logSAPIError(e,func.__name__)
def resetAddon(): global RESET if RESET: return RESET = True util.LOG('Resetting addon...') xbmc.executebuiltin( 'XBMC.RunScript(special://home/addons/service.xbmc.tts/enabler.py,RESET)' )
def setOutDir(self): tmpfs = util.getTmpfs() if util.getSetting('use_tmpfs', True) and tmpfs: util.LOG('Using tmpfs at: {0}'.format(tmpfs)) self.outDir = os.path.join(tmpfs, 'xbmc_speech') else: self.outDir = os.path.join(util.profileDirectory(), 'xbmc_speech') if not os.path.exists(self.outDir): os.makedirs(self.outDir)
def update(cls): if cls.currentVersion() == cls.ADVANCED_SETTINGS_VERSION: util.LOG('advancedsettings.xml up to date') return util.LOG('Updating advancedsettings.xml to version {0}...'.format(cls.ADVANCED_SETTINGS_VERSION)) source = os.path.join(ADDON_PATH, 'resources', 'advancedsettings.xml') advancedSettingsFile = os.path.join(KODI_PROFILE, 'advancedsettings.xml') with open(advancedSettingsFile, 'w') as f: with open(source, 'r') as s: f.write(s.read()) advancedSettingsVersion = os.path.join(KODI_PROFILE, 'advancedsettings.version') with open(advancedSettingsVersion, 'w') as f: f.write(str(cls.ADVANCED_SETTINGS_VERSION)) util.LOG('Update finished') cls.askReboot()
def credentialsUpdated(self): token = util.getSetting('token') deviceID = util.getSetting('device_iden') if not self.targetsBox: if token and deviceID: return True else: return None if token != self.targetsBox.token: util.LOG('TOKEN CHANGED') return True if deviceID != self.targetsBox.deviceID: util.LOG('DEVICE CHANGED FROM: {0} TO: {1}'.format( self.targetsBox.deviceName, util.getSetting('device_name'))) return True return False
def checkControl(self, newW): if not self.winID: return newW controlID = self.window().getFocusId() if controlID == self.controlID: return newW if util.DEBUG: util.LOG('Control: %s' % controlID) self.controlID = controlID if not controlID: return newW return True
def restoreConnman(cls): util.LOG('Restoring connman') try: if not os.path.exists(cls.CONNMAN_SOURCE_PATH): util.LOG('Not found!') return False if os.path.exists(cls.CONNMAN_DEST_PATH): shutil.rmtree(cls.CONNMAN_DEST_PATH) shutil.copytree(cls.CONNMAN_SOURCE_PATH, cls.CONNMAN_DEST_PATH) shutil.rmtree(cls.CONNMAN_SOURCE_PATH) return True except: util.ERROR() return False
def restoreRecordingsDir(self): if os.path.exists(self.RECORDINGS_PATH): if os.path.islink(self.RECORDINGS_PATH): os.unlink(self.RECORDINGS_PATH) util.LOG('Removed unexpected dead recordings symlink') elif os.path.isdir(self.RECORDINGS_PATH): return if not os.path.exists(self.RECORDINGS_PATH): os.makedirs(self.RECORDINGS_PATH)
def volumeDown(self): if not self.settings or not 'volume' in self.settings: return util.T(32180) vol = self.setting('volume') vol -= self.volumeStep if vol < self.volumeExternalEndpoints[0]: vol = self.volumeExternalEndpoints[0] util.setSetting('{0}.{1}'.format('volume', self.provider), vol) if util.DEBUG: util.LOG('Volume DOWN: {0}'.format(vol)) return u'{0} {1}'.format(vol, self.volumeSuffix)