class BaseThread(threading.Thread): def __init__(self): threading.Thread.__init__(self) if has_attribute(self, 'daemon'): self.daemon = True else: self.setDaemon(True) self._stopped_event = Event() if not has_attribute(self._stopped_event, 'is_set'): self._stopped_event.is_set = self._stopped_event.isSet @property def stopped_event(self): return self._stopped_event def should_keep_running(self): return not self._stopped_event.is_set() def on_thread_stop(self): pass def stop(self): self._stopped_event.set() self.on_thread_stop() def on_thread_start(self): pass def start(self): self.on_thread_start() threading.Thread.start(self)
class BaseThread(threading.Thread): """ Convenience class for creating stoppable threads. """ def __init__(self): threading.Thread.__init__(self) if has_attribute(self, 'daemon'): self.daemon = True else: self.setDaemon(True) self._stopped_event = Event() if not has_attribute(self._stopped_event, 'is_set'): self._stopped_event.is_set = self._stopped_event.isSet @property def stopped_event(self): return self._stopped_event def should_keep_running(self): """Determines whether the thread should continue running.""" return not self._stopped_event.is_set() def on_thread_stop(self): """Override this method instead of :meth:`stop()`. :meth:`stop()` calls this method. This method is called immediately after the thread is signaled to stop. """ pass def stop(self): """Signals the thread to stop.""" self._stopped_event.set() self.on_thread_stop() def on_thread_start(self): """Override this method instead of :meth:`start()`. :meth:`start()` calls this method. This method is called right before this thread is started and this object’s run() method is invoked. """ pass def start(self): self.on_thread_start() threading.Thread.start(self)
class XBMCIF(threading.Thread): """Wrapper around the builtins to make sure no two commands are executed at the same time (xbmc will cancel previous if not finished) """ def __init__(self): threading.Thread.__init__(self) self._stop_event = Event() self._cmd_queue = utils.OrderedSetQueue() def stop(self): self._stop_event.set() self._cmd_queue.put("stop") # unblock wait def queue_scan(self, library, path=None): path = escape_param(path) if path else "" cmd = "UpdateLibrary(%s,%s,%s)" % (library, path, settings.SHOW_PROGRESS_DIALOG) self._cmd_queue.put(cmd) def queue_clean(self, library): self._cmd_queue.put("CleanLibrary(%s,%s)" % (library, settings.SHOW_PROGRESS_DIALOG)) def queue_remove(self, library, path=None): if settings.REMOVAL_ENABLED: if settings.PER_FILE_REMOVE and path and library == 'video': videolibrary.remove_video(path) else: self._cmd_queue.put("CleanLibrary(%s,%s)" % (library, settings.SHOW_PROGRESS_DIALOG)) def run(self): player = xbmc.Player() while True: self._cmd_queue.wait() if self._stop_event.wait(settings.SCAN_DELAY): return while player.isPlaying(): self._stop_event.wait(1) if self._stop_event.is_set(): return # Remove item right before it's executed so that any duplicates of # this commands gets flushed from the queue. cmd = self._cmd_queue.get_nowait() log("[xbmcif] executing builtin: '%s'" % cmd) xbmc.executebuiltin(cmd) # wait for scan to start. we need a timeout or else we a screwed # if we missed it. # TODO: replace this crap with Monitor callbacks in Helix log("[xbmcif] waiting for scan/clean start..") timeout = 3000 while not xbmc.getCondVisibility('Library.IsScanning') \ and not self._stop_event.is_set(): xbmc.sleep(100) timeout -= 100 if timeout <= 0: log("[xbmcif] wait for scan/clean timed out.") break log("[xbmcif] scan/clean started.") log("[xbmcif] waiting for scan/clean end..") # wait for scan to end while xbmc.getCondVisibility('Library.IsScanning') \ and not self._stop_event.is_set(): xbmc.sleep(100) log("[xbmcif] scan/clean ended.")
class XBMCIF(threading.Thread): """Wrapper around the builtins to make sure no two commands a executed at the same time (xbmc will cancel previous if not finished) """ def __init__(self): threading.Thread.__init__(self) self._stop_event = Event() self._cmd_queue = utils.OrderedSetQueue() def stop(self): self._stop_event.set() self._cmd_queue.put("stop") # unblock wait def queue_scan(self, library, path=None): path = escape_param(path) if path else "" cmd = "UpdateLibrary(%s,%s,%s)" % (library, path, settings.SHOW_PROGRESS_DIALOG) self._cmd_queue.put(cmd) def queue_clean(self, library): self._cmd_queue.put("CleanLibrary(%s,%s)" % (library, settings.SHOW_PROGRESS_DIALOG)) def queue_remove(self, library, path=None): if settings.REMOVAL_ENABLED: if settings.PER_FILE_REMOVE and path and library == 'video': videolibrary.remove_video(path) else: self._cmd_queue.put("CleanLibrary(%s,%s)" % (library, settings.SHOW_PROGRESS_DIALOG)) def run(self): player = xbmc.Player() while True: self._cmd_queue.wait() if self._stop_event.wait(settings.SCAN_DELAY): return while player.isPlaying(): self._stop_event.wait(1) if self._stop_event.is_set(): return # Remove item right before it's executed so that any duplicates of # this commands gets flushed from the queue. cmd = self._cmd_queue.get_nowait() log("[xbmcif] executing builtin: '%s'" % cmd) xbmc.executebuiltin(cmd.encode('utf-8')) # wait for scan to start. we need a timeout or else we a screwed # if we missed it. # TODO: replace this crap with Monitor callbacks in Helix log("[xbmcif] waiting for scan/clean start..") timeout = 3000 while not xbmc.getCondVisibility('Library.IsScanning') \ and not self._stop_event.is_set(): xbmc.sleep(100) timeout -= 100 if timeout <= 0: log("[xbmcif] wait for scan/clean timed out.") break log("[xbmcif] scan/clean started.") log("[xbmcif] waiting for scan/clean end..") # wait for scan to end while xbmc.getCondVisibility('Library.IsScanning') \ and not self._stop_event.is_set(): xbmc.sleep(100) log("[xbmcif] scan/clean ended.")