class GIFPlayer(LoggingComponent): """GIF Player with configurable output""" def __init__(self, settings): super(GIFPlayer, self).__init__() self.log('Player initializing') pygame.display.init() self.config = settings self.factor = 1 self.delta = 0.0 self.frames = [] self.durations = [] self.clients = [] self.timer = None self.worker = Worker(process=False, workers=2, channel="gifimport_" + self.uniquename).register(self) # if transparency < 255: # self.log('Setting alpha to %i' % transparency) # for frame in self.frames: # frame[0].set_alpha(transparency) self.cur = 0 self.ptime = 0 self.playing = False self.breakpoint = 0 self.startpoint = 0 self.direction = True self.fireEvent(cli_register_event("test_gifplayer", cli_test_gifplayer)) if self.config['immediately']: self.get_frames() def cli_test_gifplayer(self, *args): if 'stop' in args: self.log("Stopping test video") self.stop() else: self.log('Running test video') self.config['filename'] = os.path.abspath( os.path.join(__file__, "../../test.gif")) self.get_frames() self.timer = Timer(self.config['delay'] / 1000.0, render(), persist=True).register(self) def update(self, settings): self.log('Updating', self.playing, self.config['playing']) if self.config['delay'] != settings['delay']: self.set_speed(settings['delay']) if self.config['bounds'] != settings['bounds']: self.set_bounds(*settings['bounds']) self.config = settings if self.config['playing'] is True: if self.playing is False: self.log('Beginning playback') self.play() else: if self.playing is True: self.log('Beginning playback') self.stop() def started(self, event, thing): self.log('Converting image') self.get_frames() def get_frames(self): self.log('Getting frames') if self.config['filename'] in (None, ""): self.log('No filename, cannot load gif') return try: # frames, durations, log = \ scale = (self.config['scale']['height'], self.config['scale']['width']) data = self.config['filename'], self.config[ 'ignore_timings'], scale self.fireEvent(task(load_image, data), "gifimport_" + self.uniquename) self.log('Worker started', lvl=verbose) except Exception as e: self.log("[GIF_WORKERS]", e, type(e), exc=True) def task_success(self, event, call, result): self.log("Worker finished:", event.channels[0], pretty=True, lvl=verbose) if event.channels[0] != "gifimport_" + self.uniquename: self.log("Not for us.", lvl=verbose) return if len(result) == 3: frames, durations, log = result else: self.log("Unexpected result:", result, pretty=True) return if len(frames) > 0: self.frames = frames self.durations = durations self.cur = 0 self.breakpoint = len(self.frames) - 1 self.startpoint = 0 else: self.log("No frames extracted:", log, lvl=warn) def render(self): # pos = self.x, self.y # self.log('Rendering %s' % self.config['filename'], lvl=verbose) if self.playing: self.delta += time.time() - self.ptime if self.delta > self.frames[self.cur][1]: # TODO: Rebuild this without loop, i.e. calculate the distance to jump while self.delta > self.frames[self.cur][1]: self.delta -= self.frames[self.cur][1] if self.config['reverse'] or (self.config['bounce'] and self.direction == -1): self.cur -= 1 if self.cur < self.startpoint: self.cur = self.breakpoint if not self.config['loop']: self.stop() if self.config['bounce']: self.direction = +1 else: self.cur += 1 if self.cur > self.breakpoint: self.cur = self.startpoint if not self.config['loop']: self.stop() if self.config['bounce']: self.direction = -1 if self.frames[self.cur][1] == 0: break self.ptime = time.time() try: frame = self.frames[self.cur][0] # self.log('Firing event', frame) if len(self.clients) > 0: self._broadcast(frame) self.fireEvent(mix_image(self.config['channel'], frame), "AVIO") except IndexError: pass def _broadcast(self, frame): # TODO: Maybe only transmit necessary data, not statics like length or always # the whole config message = { 'component': 'avio.gifplayer', 'action': 'frame_update', 'data': { 'channel': self.config['channel'], 'config': self.config, 'current': self.cur, 'length': self.breakpoint - self.startpoint, 'frame': frame.tolist() } } self.fireEvent(broadcast("clientgroup", message, group=self.clients), "isomer-web") def set_speed(self, factor): self.log('Setting new speed: %f' % factor) for i, duration in enumerate(self.durations): self.frames[i][1] = duration * factor def seek(self, num): self.cur = num if self.cur < 0: self.cur = 0 if self.cur >= len(self.frames): self.cur = len(self.frames) - 1 def set_bounds(self, start, end): length = len(self.frames) # TODO: I think, the outer min/max operations can be safely omitted self.startpoint = max(0, int(length * (max(0, start) / 100.0))) self.breakpoint = min(int(length * (min(100, end) / 100)), length) - 1 def stop(self): self.log('Stop!', lvl=debug) self.playing = False if self.timer is not None: self.timer.stop() self.timer.unregister() self.timer = None self._broadcast(self.frames[self.cur][0]) def play(self): self.log('Play!', lvl=debug) self.playing = True if self.timer is None: self.ptime = time.time() self.timer = Timer(self.config['delay'] / 1000.0, render(), persist=True).register(self) def rewind(self): self.seek(0) def fastforward(self): self.seek(self.length() - 1) def get_height(self): return self.image.size[1] def get_width(self): return self.image.size[0] def get_size(self): return self.image.size def length(self): return len(self.frames) def reverse(self): self.reversed = not self.reversed def reset(self): self.cur = 0 self.ptime = time.time() self.reversed = False
class Manager(ConfigurableComponent): """ Handles camera updates, subscriptions and broadcasts """ channel = "cam" def __init__(self, maxcams=16, *args): super(Manager, self).__init__("CAM", *args) self._cameras = {} self._subscribers = {} self._filming = True self._frame_count = 0 self._frames = {} if opencv is not None: self.log("Checking opencv for cameras.", lvl=debug) for cam in range(maxcams): video = opencv.VideoCapture(cam) if video.isOpened(): camera = { 'uuid': str(uuid4()), 'name': 'Camera' + str(cam), 'cam': video } self._cameras[cam] = camera self.log("Found camera [", cam, "]: ", camera) if len(self._cameras) > 0: self.log("Starting timer") self.timer = Timer(0.05, Event.create("rec"), persist=True).register(self) self.log("Found cameras: ", self._cameras, lvl=debug) else: self.log("No opencv, no cameras.") self.log("Started") def rec(self): """Records a single snapshot""" try: self._snapshot() except Exception as e: self.log("Timer error: ", e, type(e), lvl=error) def _snapshot(self): try: for cam_id, cam in self._cameras.items(): if cam['uuid'] in self._subscribers: # self.log("Taking input of ", cam) success, cvresult = cam['cam'].read() # self.log("Result: ", cvresult) if success: cam_packet_header = { 'component': 'isomer.camera.manager' + str(cam_id), 'action': 'update' } # TODO: Kick out 2.x compat if six.PY3: # noinspection PyArgumentList cam_packet = bytes(str(cam_packet_header), encoding="UTF8") + \ cvresult.tostring() else: cam_packet = bytes( str(cam_packet_header)) + cvresult.tostring() self._broadcast(cam_packet, cam['uuid']) else: self.log("Failed to get an image.", success, cvresult) self._frame_count += 1 if self._frame_count > 0 and self._frame_count % 100 == 0: self.log("", self._frame_count, " frames taken.", lvl=debug) except Exception as e: self.log("Error: ", e, type(e), lvl=error) def _toggle_filming(self): """Toggles the camera system recording state""" if self._filming: self.log("Stopping operation") self._filming = False self.timer.stop() else: self.log("Starting operation") self._filming = True self.timer.start() def _broadcast(self, camera_packet, camera_uuid): try: for recipient in self._subscribers[camera_uuid]: self.fireEvent(send(recipient, camera_packet, raw=True), "isomer-web") except Exception as e: self.log("Failed broadcast: ", e, type(e), lvl=error) def _generate_camera_list(self): try: result = {} for item in self._cameras.values(): result[item['name']] = item['uuid'] return result except Exception as e: self.log("Error during list retrieval:", e, type(e), lvl=error) def _unsubscribe(self, client_uuid, camera_uuid=None): # TODO: Verify everything and send a response if not camera_uuid: for subscribers in self._subscribers.values(): if client_uuid in subscribers: subscribers.remove(client_uuid) self.log("Subscription removed: ", client_uuid, lvl=debug) else: self._subscribers[camera_uuid].remove(client_uuid) if len(self._subscribers[camera_uuid]) == 0: del (self._subscribers[camera_uuid]) self.log("Subscription deleted: ", camera_uuid, client_uuid) def client_disconnect(self, event): """ A client has disconnected, update possible subscriptions accordingly. :param event: """ self.log("Removing disconnected client from subscriptions", lvl=debug) client_uuid = event.clientuuid self._unsubscribe(client_uuid) @handler(camera_list, channel='isomer-web') def camera_list(self, event): try: client_uuid = event.client.uuid db_list = self._generate_camera_list() self.fireEvent( send( client_uuid, { 'component': 'isomer.camera.manager', 'action': 'list', 'data': db_list }), "isomer-web") except Exception as e: self.log("Listing error: ", e, type(e), lvl=error) @handler(camera_subscribe, channel='isomer-web') def camera_subscribe(self, event): # TODO: Verify everything and send response try: data = event.data client_uuid = event.client.uuid if data in self._subscribers: if client_uuid not in self._subscribers[data]: self._subscribers[data].append(client_uuid) else: self._subscribers[data] = [client_uuid] self.log("Subscription registered: ", data, client_uuid) return except Exception as e: self.log("Subscription Error:", e, type(e), lvl=error) @handler(camera_unsubscribe, channel='isomer-web') def camera_unsubscribe(self, event): try: client_uuid = event.client.uuid data = event.data self._unsubscribe(client_uuid, data) return except Exception as e: self.log("Global Error: '%s' %s" % (e, type(e)), lvl=error)
class CameraManager(Component): """ Handles camera updates, subscriptions and broadcasts """ channel = "cam" def __init__(self, maxcams=16, *args): super(CameraManager, self).__init__(*args) self._cameras = {} self._subscribers = {} self._filming = True self._framecount = 0 self._frames = {} hfoslog("[CAM] Checking opencv for cameras.", lvl=debug) for cam in range(maxcams): video = opencv.VideoCapture(cam) if video.isOpened(): camera = { 'uuid': str(uuid4()), 'name': 'Camera' + str(cam), 'cam': video } self._cameras[cam] = camera hfoslog("[CAM] Found camera [", cam, "]: ", camera) hfoslog("[CAM] Starting timer") self.timer = Timer(0.05, Event.create("rec"), persist=True).register(self) hfoslog("[CAM] Found cameras: ", self._cameras, lvl=debug) hfoslog("[CAM] Started") def rec(self): """Records a single snapshot""" try: self._snapshot() except Exception as e: hfoslog("[CAM] Timer error: ", e, type(e), lvl=error) def _snapshot(self): self._framecount += 1 try: for camid, cam in self._cameras.items(): if cam['uuid'] in self._subscribers: # hfoslog("[CAM] Taking input of ", cam) success, cvresult = cam['cam'].read() # hfoslog("[CAM] Result: ", cvresult) if success: campacketheader = { 'component': 'camera' + str(camid), 'action': 'update', } if six.PY3: # noinspection PyArgumentList campacket = bytes( str(campacketheader), encoding="UTF8") + cvresult.tostring() else: campacket = bytes( str(campacketheader)) + cvresult.tostring() self._broadcast(campacket, cam['uuid']) else: hfoslog("[CAM] Failed to get an image.", success, cvresult) except Exception as e: hfoslog("[CAM] Error: ", e, type(e), lvl=error) if self._framecount % 100 == 0: hfoslog("[CAM] ", self._framecount, " frames taken.", lvl=debug) def toggleFilming(self): """Toggles the camera system recording state""" if self._filming: hfoslog("[CAM] Stopping operation") self._filming = False self.timer.stop() else: hfoslog("[CAM] Starting operation") self._filming = True self.timer.start() def _broadcast(self, camerapacket, camerauuid): try: for recipient in self._subscribers[camerauuid]: self.fireEvent(send(recipient, camerapacket, raw=True), "hfosweb") except Exception as e: hfoslog("[CAM] Failed broadcast: ", e, type(e), lvl=error) def _generatecameralist(self): try: result = {} for item in self._cameras.values(): result[item['name']] = item['uuid'] return result except Exception as e: hfoslog("[CAM] Error during list retrieval:", e, type(e), lvl=error) def _unsubscribe(self, clientuuid, camerauuid=None): # TODO: Verify everything and send a response if not camerauuid: for subscribers in self._subscribers.values(): if clientuuid in subscribers: subscribers.remove(clientuuid) hfoslog("[CAM] Subscription removed: ", clientuuid, lvl=debug) else: self._subscribers[camerauuid].remove(clientuuid) if len(self._subscribers[camerauuid]) == 0: del (self._subscribers[camerauuid]) hfoslog("[CAM] Subscription deleted: ", camerauuid, clientuuid) def client_disconnect(self, event): """ A client has disconnected, update possible subscriptions accordingly. :param event: """ hfoslog("[CAM] Removing disconnected client from subscriptions", lvl=debug) clientuuid = event.clientuuid self._unsubscribe(clientuuid) @handler("camerarequest", channel="hfosweb") def camerarequest(self, event): """ Handles new camera category requests :param event: CameraRequest with actions * subscribe * unsubscribe * update """ hfoslog("[CAM] Event: '%s'" % event.__dict__) try: try: action = event.action data = event.data clientuuid = event.client.uuid except Exception as e: raise ValueError("[CAM] Problem during event unpacking:", e, type(e)) if action == 'list': try: dblist = self._generatecameralist() self.fireEvent( send( clientuuid, { 'component': 'camera', 'action': 'list', 'data': dblist }), "hfosweb") except Exception as e: hfoslog("[CAM] Listing error: ", e, type(e), lvl=error) return elif action == 'get': return elif action == 'subscribe': # TODO: Verify everything and send a response if data in self._subscribers: if clientuuid not in self._subscribers[data]: self._subscribers[data].append(clientuuid) else: self._subscribers[data] = [clientuuid] hfoslog("[CAM] Subscription registered: ", data, clientuuid) return elif action == 'unsubscribe': self._unsubscribe(clientuuid, data) return except Exception as e: hfoslog("[CAM] Global Error: '%s' %s" % (e, type(e)), lvl=error)
class CameraManager(Component): """ Handles camera updates, subscriptions and broadcasts """ channel = "cam" def __init__(self, maxcams=16, *args): super(CameraManager, self).__init__(*args) self._cameras = {} self._subscribers = {} self._filming = True self._framecount = 0 self._frames = {} hfoslog("[CAM] Checking opencv for cameras.", lvl=debug) for cam in range(maxcams): video = opencv.VideoCapture(cam) if video.isOpened(): camera = {'uuid': str(uuid4()), 'name': 'Camera' + str(cam), 'cam': video } self._cameras[cam] = camera hfoslog("[CAM] Found camera [", cam, "]: ", camera) hfoslog("[CAM] Starting timer") self.timer = Timer(0.05, Event.create("rec"), persist=True).register(self) hfoslog("[CAM] Found cameras: ", self._cameras, lvl=debug) hfoslog("[CAM] Started") def rec(self): """Records a single snapshot""" try: self._snapshot() except Exception as e: hfoslog("[CAM] Timer error: ", e, type(e), lvl=error) def _snapshot(self): self._framecount += 1 try: for camid, cam in self._cameras.items(): if cam['uuid'] in self._subscribers: # hfoslog("[CAM] Taking input of ", cam) success, cvresult = cam['cam'].read() # hfoslog("[CAM] Result: ", cvresult) if success: campacketheader = {'component': 'camera' + str(camid), 'action': 'update', } if six.PY3: # noinspection PyArgumentList campacket = bytes(str(campacketheader), encoding="UTF8") + cvresult.tostring() else: campacket = bytes(str(campacketheader)) + cvresult.tostring() self._broadcast(campacket, cam['uuid']) else: hfoslog("[CAM] Failed to get an image.", success, cvresult) except Exception as e: hfoslog("[CAM] Error: ", e, type(e), lvl=error) if self._framecount % 100 == 0: hfoslog("[CAM] ", self._framecount, " frames taken.", lvl=debug) def toggleFilming(self): """Toggles the camera system recording state""" if self._filming: hfoslog("[CAM] Stopping operation") self._filming = False self.timer.stop() else: hfoslog("[CAM] Starting operation") self._filming = True self.timer.start() def _broadcast(self, camerapacket, camerauuid): try: for recipient in self._subscribers[camerauuid]: self.fireEvent(send(recipient, camerapacket, raw=True), "hfosweb") except Exception as e: hfoslog("[CAM] Failed broadcast: ", e, type(e), lvl=error) def _generatecameralist(self): try: result = {} for item in self._cameras.values(): result[item['name']] = item['uuid'] return result except Exception as e: hfoslog("[CAM] Error during list retrieval:", e, type(e), lvl=error) def _unsubscribe(self, clientuuid, camerauuid=None): # TODO: Verify everything and send a response if not camerauuid: for subscribers in self._subscribers.values(): if clientuuid in subscribers: subscribers.remove(clientuuid) hfoslog("[CAM] Subscription removed: ", clientuuid, lvl=debug) else: self._subscribers[camerauuid].remove(clientuuid) if len(self._subscribers[camerauuid]) == 0: del (self._subscribers[camerauuid]) hfoslog("[CAM] Subscription deleted: ", camerauuid, clientuuid) def client_disconnect(self, event): """ A client has disconnected, update possible subscriptions accordingly. :param event: """ hfoslog("[CAM] Removing disconnected client from subscriptions", lvl=debug) clientuuid = event.clientuuid self._unsubscribe(clientuuid) @handler("camerarequest", channel="hfosweb") def camerarequest(self, event): """ Handles new camera category requests :param event: CameraRequest with actions * subscribe * unsubscribe * update """ hfoslog("[CAM] Event: '%s'" % event.__dict__) try: try: action = event.action data = event.data clientuuid = event.client.uuid except Exception as e: raise ValueError("[CAM] Problem during event unpacking:", e, type(e)) if action == 'list': try: dblist = self._generatecameralist() self.fireEvent(send(clientuuid, {'component': 'camera', 'action': 'list', 'data': dblist}), "hfosweb") except Exception as e: hfoslog("[CAM] Listing error: ", e, type(e), lvl=error) return elif action == 'get': return elif action == 'subscribe': # TODO: Verify everything and send a response if data in self._subscribers: if clientuuid not in self._subscribers[data]: self._subscribers[data].append(clientuuid) else: self._subscribers[data] = [clientuuid] hfoslog("[CAM] Subscription registered: ", data, clientuuid) return elif action == 'unsubscribe': self._unsubscribe(clientuuid, data) return except Exception as e: hfoslog("[CAM] Global Error: '%s' %s" % (e, type(e)), lvl=error)
class Manager(ConfigurableComponent): """ Handles camera updates, subscriptions and broadcasts """ channel = "cam" def __init__(self, maxcams=16, *args): super(Manager, self).__init__("CAM", *args) self._cameras = {} self._subscribers = {} self._filming = True self._frame_count = 0 self._frames = {} if opencv is not None: self.log("Checking opencv for cameras.", lvl=debug) for cam in range(maxcams): video = opencv.VideoCapture(cam) if video.isOpened(): camera = {'uuid': str(uuid4()), 'name': 'Camera' + str(cam), 'cam': video } self._cameras[cam] = camera self.log("Found camera [", cam, "]: ", camera) if len(self._cameras) > 0: self.log("Starting timer") self.timer = Timer(0.05, Event.create("rec"), persist=True).register(self) self.log("Found cameras: ", self._cameras, lvl=debug) else: self.log("No opencv, no cameras.") self.log("Started") def rec(self): """Records a single snapshot""" try: self._snapshot() except Exception as e: self.log("Timer error: ", e, type(e), lvl=error) def _snapshot(self): try: for cam_id, cam in self._cameras.items(): if cam['uuid'] in self._subscribers: # self.log("Taking input of ", cam) success, cvresult = cam['cam'].read() # self.log("Result: ", cvresult) if success: cam_packet_header = { 'component': 'hfos.camera.manager' + str( cam_id), 'action': 'update' } if six.PY3: # noinspection PyArgumentList cam_packet = bytes(str(cam_packet_header), encoding="UTF8") + \ cvresult.tostring() else: cam_packet = bytes( str(cam_packet_header)) + cvresult.tostring() self._broadcast(cam_packet, cam['uuid']) else: self.log("Failed to get an image.", success, cvresult) self._frame_count += 1 if self._frame_count > 0 and self._frame_count % 100 == 0: self.log("", self._frame_count, " frames taken.", lvl=debug) except Exception as e: self.log("Error: ", e, type(e), lvl=error) def _toggle_filming(self): """Toggles the camera system recording state""" if self._filming: self.log("Stopping operation") self._filming = False self.timer.stop() else: self.log("Starting operation") self._filming = True self.timer.start() def _broadcast(self, camera_packet, camera_uuid): try: for recipient in self._subscribers[camera_uuid]: self.fireEvent(send(recipient, camera_packet, raw=True), "hfosweb") except Exception as e: self.log("Failed broadcast: ", e, type(e), lvl=error) def _generate_camera_list(self): try: result = {} for item in self._cameras.values(): result[item['name']] = item['uuid'] return result except Exception as e: self.log("Error during list retrieval:", e, type(e), lvl=error) def _unsubscribe(self, client_uuid, camera_uuid=None): # TODO: Verify everything and send a response if not camera_uuid: for subscribers in self._subscribers.values(): if client_uuid in subscribers: subscribers.remove(client_uuid) self.log("Subscription removed: ", client_uuid, lvl=debug) else: self._subscribers[camera_uuid].remove(client_uuid) if len(self._subscribers[camera_uuid]) == 0: del (self._subscribers[camera_uuid]) self.log("Subscription deleted: ", camera_uuid, client_uuid) def client_disconnect(self, event): """ A client has disconnected, update possible subscriptions accordingly. :param event: """ self.log("Removing disconnected client from subscriptions", lvl=debug) client_uuid = event.clientuuid self._unsubscribe(client_uuid) @handler(camera_list, channel='hfosweb') def camera_list(self, event): try: client_uuid = event.client.uuid db_list = self._generate_camera_list() self.fireEvent(send(client_uuid, { 'component': 'hfos.camera.manager', 'action': 'list', 'data': db_list }), "hfosweb") except Exception as e: self.log("Listing error: ", e, type(e), lvl=error) @handler(camera_subscribe, channel='hfosweb') def camera_subscribe(self, event): # TODO: Verify everything and send response try: data = event.data client_uuid = event.client.uuid if data in self._subscribers: if client_uuid not in self._subscribers[data]: self._subscribers[data].append(client_uuid) else: self._subscribers[data] = [client_uuid] self.log("Subscription registered: ", data, client_uuid) return except Exception as e: self.log("Subscription Error:", e, type(e), lvl=error) @handler(camera_unsubscribe, channel='hfosweb') def camera_unsubscribe(self, event): try: client_uuid = event.client.uuid data = event.data self._unsubscribe(client_uuid, data) return except Exception as e: self.log("Global Error: '%s' %s" % (e, type(e)), lvl=error)
class YoutubeDownloader(Component): channel = 'youtube' EXPECTED_MAX_SIZE = 15 def init(self, quality=3, rate_limit=None): self.manager = Manager() script_dir = get_script_dir() save_dir = os.path.join(script_dir, 'songs') if not os.path.exists(save_dir): os.mkdir(save_dir) print('Script Dir: {}'.format(script_dir)) print('Saving to: {}'.format(save_dir)) self.save_dir = save_dir self.options = [ '--extract-audio', '--prefer-ffmpeg', '--audio-format mp3', '--ffmpeg {}'.format(script_dir), '--audio-quality {}'.format(quality) ] if rate_limit: try: rate_limit = float(rate_limit) except ValueError as e: raise ValueError('rate_limit should be a float.') self.options.append( '--limit-rate {}'.format(str(rate_limit) + 'M')) else: rate_limit = 1 # Make timeout to cancel download relative to rate limiting self.timeout = 2 * self.EXPECTED_MAX_SIZE / rate_limit self.queue = deque() self.downloading = None self.process = None self.yt_dl = 'youtube-dl' if sys.platform.startswith('win'): self.yt_dl += '.exe' self.timer = None self.start_time = None @handler('youtube_download') def download(self, url): self.queue.append(url) self.fire(process_download(), 'youtube') @handler('process_download') def _process_download(self): if not self.downloading and self.queue: if not self.process: self.downloading = self.queue.popleft() flags = ' '.join(self.options) # Still not sure why I have to give a stock Manager() rather than self. self.process = Process( self.yt_dl + ' ' + flags + ' ' + self.downloading, cwd=self.save_dir).register(self.manager) self.process.start() self.start_time = time.clock() if not self.timer: self.timer = Timer(1, poll_process(), persist=True).register(self) def _shutdown_process(self): self.process.kill() self.process = None self.timer.stop() self.timer.unregister() self.timer = None @handler('poll_process') def _poll_process(self): status = self.process.status if (time.clock() - self.start_time) > self.timeout: self._shutdown_process() self.fire( youtube_error('Timeout while downloading {}'.format( self.downloading)), '*') self.downloading = None self.fire(process_download()) return if status is not None: self._shutdown_process() if status == 0: self.fire(youtube_download_complete(self.downloading), '*') else: self.fire(youtube_error(self.downloading), '*') self.downloading = None self.fire(process_download())
class TextRender(ConfigurableComponent): """Text Renderer""" channel = "AVIO" configprops = { 'channel': { 'type': 'integer' }, 'playing': { 'type': 'boolean', 'default': False }, 'movement': { 'type': 'object', 'properties': { 'speed': { 'type': 'number', 'default': 1.0 }, 'direction': { 'type': 'number', 'default': 90 } }, }, 'loop': { 'type': 'boolean', 'default': True }, 'bounce': { 'type': 'boolean', 'default': False }, 'font': { 'type': 'string', 'default': '' } } def __init__(self): super(TextRender, self).__init__("GIFMASTER") self.timer = None @handler(subscribe, channel="isomer-web") def subscribe(self, event): self.log("Subscription Event:", event.client) if event.client.uuid not in self.players[event.data].clients: self.players[event.data].clients.append(event.client.uuid) @handler(unsubscribe, channel="isomer-web") def unsubscribe(self, event): self.log("Unsubscription Event:", event.client) if event.client.uuid in self.players[event.data].clients: self.players[event.data].clients.remove(event.client.uuid) @handler("userlogout", channel="isomer-web") def userlogout(self, event): self.stop_client(event) @handler("clientdisconnect", channel="isomer-web") def clientdisconnect(self, event): """Handler to deal with a possibly disconnected simulation frontend :param event: ClientDisconnect Event """ self.stop_client(event) def stop_client(self, event): try: for player in self.players: if event.clientuuid in player.clients: player.clients.remove(event.clientuuid) self.log("Remote simulator disconnected") else: self.log("Client not subscribed") except Exception as e: self.log("Strange thing while client disconnected", e, type(e)) def cli_test_text(self, *args): if 'stop' in args: self.log("Stopping test video") self.stop() else: self.log('Running test video') self.config['filename'] = os.path.abspath( os.path.join(__file__, "../../test.gif")) self.get_frames() self.timer = Timer(self.config['delay'] / 1000.0, render(), persist=True).register(self) def update(self): self.log('Updating', self.playing, self.config['playing']) if self.config['playing'] is True: if self.playing is False: self.log('Beginning playback') self.play() else: if self.playing is True: self.log('Beginning playback') self.stop() def started(self, event, thing): self.log('Converting image') def task_success(self, event, call, result): self.log("Worker finished:", event.channels[0], pretty=True, lvl=verbose) if event.channels[0] != "gifimport_" + self.uniquename: self.log("Not for us.", lvl=verbose) return if len(result) == 3: frames, durations, log = result else: self.log("Unexpected result:", result, pretty=True) return if len(frames) > 0: self.frames = frames self.durations = durations self.cur = 0 self.breakpoint = len(self.frames) - 1 self.startpoint = 0 self.reversed = False else: self.log("No frames extracted:", log, lvl=warn) def render(self): # pos = self.x, self.y # self.log('Rendering %s' % self.config['filename'], lvl=verbose) if self.playing: self.delta += time.time() - self.ptime if self.delta > self.frames[self.cur][1]: while self.delta > self.frames[self.cur][1]: self.delta -= self.frames[self.cur][1] if self.reversed: self.cur -= 1 if self.cur < self.startpoint: self.cur = self.breakpoint else: self.cur += 1 if self.cur > self.breakpoint: self.cur = self.startpoint if self.frames[self.cur][1] == 0: break self.ptime = time.time() try: frame = self.frames[self.cur][0] # self.log('Firing event', frame) if len(self.clients) > 0: self._broadcast(frame) self.fireEvent(mix_image(self.config['channel'], frame), "AVIO") except IndexError: pass def _broadcast(self, frame): message = { 'component': 'avio.gifplayer', 'action': 'frame_update', 'data': { 'channel': self.config['channel'], 'frame': frame.tolist() } } self.fireEvent(broadcast("clientgroup", message, group=self.clients), "isomer-web") def set_speed(self, factor): self.log('Setting new speed: %f' % factor) for i, duration in enumerate(self.durations): self.frames[i][1] = duration * factor def seek(self, num): self.cur = num if self.cur < 0: self.cur = 0 if self.cur >= len(self.frames): self.cur = len(self.frames) - 1 def set_bounds(self, start, end): if start < 0: start = 0 if start >= len(self.frames): start = len(self.frames) - 1 if end < 0: end = 0 if end >= len(self.frames): end = len(self.frames) - 1 if end < start: end = start self.startpoint = start self.breakpoint = end def stop(self): self.log('Stop!', lvl=debug) self.playing = False if self.timer is not None: self.timer.stop() self.timer.unregister() self.timer = None def play(self): self.log('Play!', lvl=debug) self.playing = True if self.timer is None: self.ptime = time.time() self.timer = Timer(self.config['delay'] / 1000.0, render(), persist=True).register(self) def rewind(self): self.seek(0) def fastforward(self): self.seek(self.length() - 1) def get_height(self): return self.image.size[1] def get_width(self): return self.image.size[0] def get_size(self): return self.image.size def length(self): return len(self.frames) def reverse(self): self.reversed = not self.reversed def reset(self): self.cur = 0 self.ptime = time.time() self.reversed = False