Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
Archivo: manager.py Proyecto: ri0t/hfos
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)
Ejemplo n.º 6
0
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())
Ejemplo n.º 7
0
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