コード例 #1
0
ファイル: test_timers.py プロジェクト: ke4roh/circuits
    def persistent(self, interval):
        timer = Timer(interval, single(), persist=True)
        timer.register(self)

        yield sleep(interval * 10)

        timer.unregister()
コード例 #2
0
ファイル: test_timers.py プロジェクト: totalgood/circuits
    def persistent(self, interval):
        timer = Timer(interval, single(), persist=True)
        timer.register(self)

        yield sleep(interval * 10)

        timer.unregister()
コード例 #3
0
def test_persistentTimer(app):
    app.timestamps.append(time.time())
    timer = Timer(0.2, test(), "timer", persist=True)
    timer.register(app)

    wait_res = pytest.wait_for(app, "count", 2)
    assert app.count >= 2
    assert wait_res
    delta = app.timestamps[1] - app.timestamps[0]
    # Should be 0.1, but varies depending on timer precision and load
    assert delta >= 0.08 and delta < 0.5
    delta = app.timestamps[2] - app.timestamps[1]
    assert delta >= 0.08 and delta < 0.5
    app.reset()

    timer.unregister()
コード例 #4
0
def test_persistentTimer(app):
    app.timestamps.append(time.time())
    timer = Timer(0.2, test(), "timer", persist=True)
    timer.register(app)

    wait_res = pytest.wait_for(app, "count", 2)
    assert app.count >= 2
    assert wait_res
    delta = app.timestamps[1] - app.timestamps[0]
    # Should be 0.1, but varies depending on timer precision and load
    assert delta >= 0.08 and delta < 0.5
    delta = app.timestamps[2] - app.timestamps[1]
    assert delta >= 0.08 and delta < 0.5
    app.reset()

    timer.unregister()
コード例 #5
0
ファイル: camera.py プロジェクト: ri0t/avio
class CVCamera(AVIOComponent):
    def __init__(self, device_id=0, targetresolution=(40, 16), *args,
                 **kwargs):
        super(CVCamera, self).__init__(*args, **kwargs)
        self.targetresolution = targetresolution
        self.cam = cv2.VideoCapture(device_id)
        self.cam.set(3, 320)
        self.cam.set(4, 240)

        self.framerate = 20 / 1000.0

        self.recording = True

        self.worker = Worker(process=False, workers=1,
                             channel="camera").register(self)

        self.cam_timer = Timer(2, Event.create('takepicture')).register(
            self)

        self.surface = pygame.Surface(targetresolution)
        self.log('Camera started')

    def takepicture(self):
        if self.recording:
            self.log('Taking a pic')
            self.fireEvent(task(take_picture, self.cam), 'camera')


    @handler('task_success', channel='camera')
    def task_success(self, event, call, result):
        frame = result

        if frame is None:
            self.log("Oh, no camera attached! Change this and rerun!")
            self.cam_timer.unregister()

            return

        newframe = numpy.rot90(frame)
        #newframe = cv2.resize(frame, self.targetresolution)
        surfarr = pygame.surfarray.make_surface(newframe)
        srf = pygame.transform.scale(surfarr, self.targetresolution)

        self.fireEvent(cameraframe(srf))
        self.fireEvent(Event.create('takepicture'))
コード例 #6
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
コード例 #7
0
class IsomerClient(LoggingComponent):
    def __init__(self,
                 no_stdin=False,
                 no_stdout=False,
                 loop_function=None,
                 loop_frequency=60,
                 *args,
                 **kwargs):
        super(IsomerClient, self).__init__(*args, **kwargs)
        self.url = '{protocol}://{host}:{port}/{url}'.format(**kwargs)
        if no_stdout:
            set_verbosity(100)

        if not no_stdin:
            self.log("Connecting stdin")
            stdin.register(self)

        self.log("Connecting to isomer instance at", self.url)
        self.username = kwargs.get('username')
        self.password = kwargs.get('password')

        self.max_length = 100
        self._request_id = 0

        self.messages = []
        self.hooks = {}

        self.client = WebSocketClient(self.url).register(self)

        if loop_function is not None:
            self.log('Registering external loop function')
            self.loop_function = loop_function
            self.loop_timer = Timer(1 / loop_frequency,
                                    call_loop(),
                                    persist=True).register(self)

        self.log("Ready")

    @handler("call_loop")
    def call_loop(self, event):
        """Runs a given client loop for interactive processes"""
        self.log('Running external loop')
        try:
            self.loop_function()
        except Exception:
            self.loop_timer.unregister()
            Timer(2, Event.create("quit")).register(self)

    @handler("quit")
    def quit(self):
        self.log("Quitting")
        sys.exit()

    @handler("registered")
    def registered(self, event, *args):
        if 'ws' not in event.channels:
            self.log("Hello", event)
            return
        self.log('Transmitting login')

        self.fireEvent(write(""), "ws")

        packet = {
            'component': 'auth',
            'action': 'login',
            'data': {
                'username': self.username,
                'password': self.password
            }
        }

        self._transmit(packet)

    def _transmit(self, packet):

        self.log(packet)
        unicode = dumps(packet).encode('utf-8')
        self.log(unicode, type(unicode))

        self.fireEvent(write(bytes(unicode)), 'ws')

    @handler("read")
    def read(self, *args):
        self.log("Reading")
        msg = args[0]
        self._handle_message(msg)

        self.messages.append(msg)
        if len(msg) > self.max_length:
            msg = str(msg)[:self.max_length] + " ..."
        self.log("Response [%i]: %s" % (len(self.messages), msg))

    def _handle_message(self, msg):
        try:
            decoded = loads(msg)
        except Exception:
            self.log("Couldn't decode message!")
            return

        if decoded['component'] == 'isomer.auth' and decoded[
                'action'] == 'fail':
            self.log("Login failed. Check credentials and url!", lvl=error)
            sys.exit()

    @handler("read", channel="stdin")
    def stdin_read(self, data):
        """read Event (on channel ``stdin``)
        This is the event handler for ``read`` events specifically from the
        ``stdin`` channel. This is triggered each time stdin has data that
        it has read.
        """

        data = data.strip().decode("utf-8")
        self.log("Incoming:", data, lvl=verbose)

        if len(data) == 0:
            self.log('Use /help to get a list of client commands')
            return

        if data[0] == "/":
            cmd = data[1:]
            args = []
            if ' ' in cmd:
                cmd, args = cmd.split(' ', maxsplit=1)
                args = args.split(' ')
            if cmd in self.hooks:
                self.log('Firing hooked event:', cmd, args, lvl=debug)
                self.fireEvent(self.hooks[cmd](*args))
            if cmd.lower() in ('send', 's'):
                data = " ".join(args)
                json = loads(" ".join(args))
                self.log("Transmitting:", data, pretty=True, lvl=debug)
                self.fireEvent(write(data), 'ws')
            if cmd.lower() in ('history', 'h'):
                position = int(args[0])
                pretty = '-p' in args
                self.log('Response [%i]: %s' %
                         (position, self.messages[position]),
                         pretty=pretty)
            if cmd.lower() == "test":
                self.fireEvent(get_data('user', {'name': 'riot'}))
            if cmd.lower() in ('quit', 'q'):
                self.log('Initiating system exit in 3 seconds on request.',
                         lvl=verbose)
                Timer(3, Event.create("quit")).register(self)

    def get_data(self, event: get_data):
        """Request data from Isomer server"""

        request = {
            'component': 'isomer.events.objectmanager',
            'action': 'search',
            'data': {
                'schema': event.schema,
                'search': event.search_filter,
                'req': self._request_id
            }
        }

        self._transmit(request)
        self._request_id += 1
コード例 #8
0
class PancakesBot(Component):

    channel = "pancakesbot"

    def init(self, **kwargs):
        # Default Settings
        prop_defaults = {
            "nick": "pancakesbot",
            "network": "irc.slashnet.org",
            "port": 6667,
            "channels": ["#bots"],
            "plugins": ["admin"],
            "plugins_path": "plugins",
            "command_prefix": "~",
            "storage_path": "storage",
        }
        self.__dict__.update(prop_defaults)
        # Overwrite defaults with kwargs
        if kwargs:
            self.__dict__.update(kwargs)

        self.terminate = False
        self.storage_path = os.path.abspath(self.storage_path)

        # Add a logger
        self.logger = logging.getLogger(__name__)

        # Message Queue used by plugins, as to avoid kicks for flooding.
        self.msg_queue = []
        # Global mesasge queue timer, only activated when there are messages
        # to process.
        self.queue_timer = None

        # Add TCPClient and IRC to the system.
        TCPClient(channel=self.channel).register(self)
        IRC(channel=self.channel).register(self)

        # Creates an instance of UserManager
        self.logger.debug("Initializing user manager.")
        user_db_file = os.path.join(self.storage_path, "users-{}.db".format(self.network))
        if not os.path.exists(self.storage_path):
            os.makedirs(self.storage_path)
        self.user_mngr = UserManager(self, user_db_file)
        self.user_mngr.register(self)

        # Add plugins directory to path
        self.logger.debug("Initializing plugin manager.")
        self.plugins_path = os.path.abspath(self.plugins_path)
        if not os.path.exists(self.plugins_path):
            os.makedirs(self.plugins_path)
        sys.path.append(self.plugins_path)
        # Keeps track of plugins and commands
        self.plugin_mngr = PluginManager(self, self.command_prefix, os.path.basename(self.plugins_path)).register(self)
        for plugin in self.plugins:
            self.plugin_mngr.load(plugin)

        # Send Keepalive PING every 5 minutes
        Timer(300.0, Event.create("keepalive"), persist=True).register(self)

    def enqueue_msg(self, target, message):
        if self.queue_timer:
            self.msg_queue.append((target, message))
        else:
            self.fire(PRIVMSG(target, message))
            self.queue_timer = Timer(1.0, Event.create("process_queue"), persist=True).register(self)

    def process_queue(self):
        if self.msg_queue:
            msg = self.msg_queue[0]
            self.fire(PRIVMSG(msg[0], msg[1]))
            self.msg_queue.pop(0)
        if not self.msg_queue:
            self.queue_timer.unregister()
            self.queue_timer = None

    def keepalive(self):
        timestamp = int(time() * 1000)
        self.logger.debug("PING: {}".format(timestamp))
        self.fire(request(Message("PING", "LAG{0}".format(timestamp))))

    @handler("signal", channels="*")
    def signal(self, signo, stack):
        if signo in (SIGINT, SIGTERM):
            self.fire(QUIT("Received SIGTERM, terminating..."))
            self.fire(events.terminate())

    #######################################################
    # Event Handlers                                      #
    # These handle events and fire the pancakesbot events #
    #######################################################

    @handler("privmsg")
    def _on_text(self, user, target, message):
        user += (self.user_mngr.get_user_id(user),)
        if (message.startswith("\x01ACTION ")) and (message[-1] == "\x01"):
            message = message[7:]
            self.logger.debug("ACTION: {}({})@{}: {}".format(user[0], user[3], target, message))
            self.fire(events.on_action(user, target, message), "plugins")
        else:
            self.logger.debug("MSG: {}({})@{}: {}".format(user[0], user[3], target, message))
            self.fire(events.on_text(user, target, message), "plugins")

    @handler("ready")
    def _on_ready(self, component):
        self.logger.info("Ready. " "Connecting to {0.network}:{0.port}".format(self))
        self.fire(connect(self.network, self.port))

    @handler("connected")
    def _on_connected(self, network, port):
        self.logger.info("Connected. Signing in as {0.nick}".format(self))
        self.fire(NICK(self.nick))
        self.fire(USER("pancakes", "pancakes", network, "robot"))
        self.fire(events.on_logon(network, port), "plugins")

    @handler("disconnected")
    def _on_disconnected(self):
        self.logger.info("Disconnected.")
        self.fire(events.on_disconnect(), "plugins")
        if self.terminate:
            raise SystemExit(0)
        else:
            self.logger.info("Reconnecting.")
            self.fire(events.on_reconnect(), "plugins")
            self.fire(connect(self.network, self.port))

    @handler("terminate")
    def _on_terminate(self):
        self.terminate = True
        self.fire(events.on_exit(), "plugins")
        self.logger.info("Terminating.")
        raise SystemExit(0)

    @handler("join")
    def _on_join(self, user, channel):
        # Send a who for channel on join
        if user[0] == self.nick:
            self.fire(WHO(channel))

        user += (self.user_mngr.get_user_id(user),)
        self.fire(events.on_join(user, channel), "plugins")
        self.logger.info("JOIN: {} ({}) to {}".format(user[0], user[3], channel))

    @handler("part")
    def _on_part(self, user, channel, *args):
        if args:
            message = args[0]
        else:
            message = ""
        user += (self.user_mngr.get_user_id(user),)
        self.fire(events.on_part(user, channel, message), "plugins")
        self.logger.debug("PART: {} ({}) from {} ({})".format(user[0], user[3], channel, message))

    @handler("quit")
    def _on_quit(self, user, *args):
        if args:
            message = args[0]
        else:
            message = ""
        user += (self.user_mngr.get_user_id(user),)
        self.fire(events.on_quit(user, message), "plugins")
        self.logger.debug("QUIT: {} ({})".format(user[0], user[3], message))

    @handler("notice")
    def _on_notice(self, user, target, message):
        user += (self.user_mngr.get_user_id(user),)
        self.fire(events.on_notice(user, target, message), "plugins")
        self.logger.debug("NOTICE: {}@{}: {}".format(user[0], target, message))

    @handler("invite")
    def _on_invite(self, nickname, channel):
        user = self.user_mngr.get_full_user(nick=nickname)
        self.fire(events.on_invite(user, channel), "plugins")
        self.logger.info("INVITE: {} ({}) invited us to {}.".format(user[0], user[3], channel))

    @handler("kick")
    def _on_kick(self, user, channel, target, message):
        user += (self.user_mngr.get_user_id(user),)
        target = self.user_mngr.get_full_user(nick=target)
        self.fire(events.on_kick(user, target, channel, message), "plugins")
        self.logger.debug(
            "KICK: {} ({}) kicked {} ({}) from {} ({})".format(user[0], user[3], target[0], target[3], channel, message)
        )

    @handler("mode")
    def _on_mode(self, user, target, mode, *args):
        if mode == "+b":
            user += (self.user_mngr.get_user_id(user),)
            self.fire(events.on_ban(user, args[0], target), "plugins")
            self.logger.debug("BAN: {} banned {} from {}".format(user[0], args[0], target))
        elif mode == "-b":
            user += (self.user_mngr.get_user_id(user),)
            self.fire(events.on_unban(user, args[0], target), "plugins")
            self.logger.debug("UNBAN: {} unbanned {} from {}".format(user[0], args[0], target))
        elif mode == "+v":
            user += (self.user_mngr.get_user_id(user),)
            t_user = self.user_mngr.get_full_user(nick=args[0])
            self.fire(events.on_voice(user, t_user, target), "plugins")
            self.logger.debug("VOICE: {} gave voice " "to {} in {}".format(user[0], t_user[0], target))
        elif mode == "-v":
            user += (self.user_mngr.get_user_id(user),)
            t_user = self.user_mngr.get_full_user(nick=args[0])
            self.fire(events.on_devoice(user, t_user, target), "plugins")
            self.logger.debug("DEVOICE: {} removed voice " "from {} in {}".format(user[0], t_user[0], target))
        elif mode == "+o":
            user += (self.user_mngr.get_user_id(user),)
            t_user = self.user_mngr.get_full_user(nick=args[0])
            self.fire(events.on_op(user, t_user, target), "plugins")
            self.logger.debug("OP: {} gave operator " "to {} in {}".format(user[0], t_user[0], target))
        elif mode == "-o":
            user += (self.user_mngr.get_user_id(user),)
            t_user = self.user_mngr.get_full_user(nick=args[0])
            self.fire(events.on_deop(user, t_user, target), "plugins")
            self.logger.debug("DEOP: {} removed operator " "from {} in {}".format(user[0], t_user[0], target))
        elif mode == "+q":
            user += (self.user_mngr.get_user_id(user),)
            t_user = self.user_mngr.get_full_user(nick=args[0])
            self.fire(events.on_owner(user, t_user, target), "plugins")
            self.logger.debug("OWNER: {} gave owner " "to {} in {}".format(user[0], t_user[0], target))
        elif mode == "-q":
            user += (self.user_mngr.get_user_id(user),)
            t_user = self.user_mngr.get_full_user(nick=args[0])
            self.fire(events.on_deowner(user, t_user, target), "plugins")
            self.logger.debug("DEOWNER: {} removed owner " "from {} in {}".format(user[0], t_user[0], target))
        elif target.startswith("#"):
            user += (self.user_mngr.get_user_id(user),)
            self.fire(events.on_mode(user, mode, target), "plugins")
            self.logger.debug("MODE: {} set {} in {} ({})".format(user[0], mode, target, args))

    @handler("nick")
    def _on_nick(self, user, new_nick):
        self.user_mngr.changed_nick(user, new_nick)
        user += (self.user_mngr.get_user_id(user),)
        self.fire(events.on_nick(user, new_nick), "plugins")
        self.logger.debug("NICK: {} ({}) changed nick to {}".format(user[0], user[3], new_nick))

    @handler("topic")
    def _on_topic(self, user, channel, topic):
        user += (self.user_mngr.get_user_id(user),)
        self.logger.debug('TOPIC: {} ({}) changed topic of {} to "{}"'.format(user[0], user[3], channel, topic))

    @handler("numeric")
    def _on_numeric(self, source, numeric, *args):
        self.logger.debug("NUMERIC: {} - {}".format(numeric, ", ".join(args)))

        if numeric == ERR_NICKNAMEINUSE:
            # Change Nick if in use
            newnick = "{0:s}_".format(args[1])
            self.nick = newnick
            self.fire(NICK(newnick))
        if numeric == RPL_WHOREPLY:
            print(args)
            user = (args[5], args[2], args[3])
            user += (self.user_mngr.get_user_id(user),)
            print(user)
        elif numeric in (RPL_ENDOFMOTD, ERR_NOMOTD):
            self.fire(events.on_connect(self.network, self.port), "plugins")
            for chan in self.channels:
                self.fire(JOIN(chan))

    # Used to test handlers to determine arguments
    @handler("test")
    def _gen_handler(self, *args, **kwargs):
        if args:
            for arg in args:
                self.logger.info("from args: {}".format(arg))
        if kwargs:
            for key, value in kwargs:
                self.logger.info("from kwargs: {} == {}".format(key, value))
コード例 #9
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())
コード例 #10
0
class Matelight(ConfigurableComponent):
    """Matelight connector with some minimal extra facilities"""

    channel = "matelight"

    configprops = {
        'host': {'type': 'string', 'default': 'matelight'},
        'port': {'type': 'integer', 'default': 1337},
        'gamma': {'type': 'number', 'default': 1.1},
        'size': {
            'type': 'object',
            'properties': {
                'width': {'type': 'integer', 'default': 40},
                'height': {'type': 'integer', 'default': 16}
            },
            'default': {
                'width': 40,
                'height': 16
            }
        }
    }

    def __init__(self, *args, **kwargs):
        super(Matelight, self).__init__('MATELIGHT', *args, **kwargs)
        self.log("Initializing matelight output")

        self.size = (self.config.size['width'], self.config.size['height'])
        self.gamma = self.config.gamma

        self.fading = None

        self.auto_restart = True
        self.output_broken = False

        self.last_frame = np.zeros(self.size, np.uint8)

        self.fade_timer = None
        self.init_timer = Timer(5, fade_out_ml()).register(self)
        self.refresh_timer = None

        self.fireEvent(cli_register_event("test_matelight", cli_test_matelight))

        self.cli_test_matelight(None)

    def started(self, *args):
        self.log("Starting matelight output on device %s:%i" % (self.host, self.port))

    def cli_test_matelight(self, event):
        self.log('Displaying test image')
        import os, cv2 as cv

        path = os.path.abspath(os.path.join(__file__, "../../testscreen.png"))
        self.log("Path of image:", path, lvl=verbose)
        test_image = cv.imread(path)
        test_image = cv.cvtColor(test_image, cv.COLOR_BGR2RGB)
        self._transmit(test_image)

    def fade_out_ml(self, event):
        if self.fading is None:
            self.fading = 20
            self.fade_timer = Timer(1 / 60.0, fade_out_ml(), persist=True).register(
                self)
        elif self.fading > 0:
            new_frame = (self.last_frame * 0.9).astype(np.uint8)
            self._transmit(new_frame)
            self.fading -= 1
        elif self.fading <= 0:
            self._clear()
            self.fade_timer.unregister()
            self.fading = None

    def _clear(self):
        self.log('Clearing')
        img = np.zeros((self.config.size['width'], self.config.size['height'], 3),
                       np.uint8)
        self._transmit(img)

    def clear_ml(self, event):
        self._clear()

    @handler('refresh_ml')
    def refresh_ml(self, event):
        self._transmit(self.last_frame)
        self.refresh_timer = Timer(1, refresh_ml()).register(self)

    def _transmit(self, image):
        self.log("New transmission request", lvl=verbose)
        if self.output_broken and not self.auto_restart:
            return

        self.log('Transmitting image, shape:', image.shape, lvl=verbose)

        self.last_frame = image

        if self.gamma != 1:
            image = (image * self.gamma).astype(np.uint8)

        ml_data = bytearray(image) + b"\00\00\00\00"

        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            sock.sendto(ml_data, (self.config.host, self.config.port))
        except Exception as e:
            self.log("Error during matelight transmission: ", e)
            self.output_broken = True

        if self.refresh_timer is not None:
            self.refresh_timer.unregister()
        self.refresh_timer = Timer(1, refresh_ml()).register(self)

    @handler("transmit_ml")
    @handler(transmit_ml)
    def transmit_ml(self, event):
        if self.fade_timer is not None:
            self.fade_timer.unregister()
            self.fade_timer = None

        self._transmit(event.frame)
コード例 #11
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
コード例 #12
0
ファイル: matelight.py プロジェクト: ri0t/avio
class Matelight(AVIOComponent):
    """Matelight connector with some minimal extra facilities"""

    channel = "matelight"

    def __init__(self, host="matelight", port=1337, *args):
        super(Matelight, self).__init__(*args)
        self.log("Initializing matelight output")

        self.host = host
        self.port = port

        self.size = (40, 16)
        self.gamma = 0.5

        self.fading = None

        self.auto_restart = True
        self.output_broken = False

        self.last_frame = np.zeros(self.size, np.uint8)

        path = os.path.abspath("./images/startscreen_matelight.png")
        boot_image = cv.imread(path)

        self.boot_image = cv.cvtColor(boot_image, cv.COLOR_BGR2RGB)
        self._transmit(self.boot_image)

        self.fade_timer = None
        self.init_timer = Timer(5, fade_out_ml()).register(self)
        self.refresh_timer = Timer(1, refresh_ml(),
                                   persist=True).register(self)

    def started(self, *args):
        self.log("Starting matelight output on device %s:%i" %
                 (self.host, self.port))

    def fade_out_ml(self, event):
        if self.fading is None:
            self.fading = 20
            self.fade_timer = Timer(1 / 60.0, fade_out_ml(),
                                    persist=True).register(self)
        elif self.fading > 0:
            new_frame = (self.last_frame * 0.9).astype(np.uint8)
            self._transmit(new_frame)
            self.fading -= 1
        elif self.fading <= 0:
            self._clear()
            self.fade_timer.unregister()
            self.fading = None

    def _clear(self):
        self.log('Clearing')
        img = np.zeros((40, 16, 3), np.uint8)
        self._transmit(img)

    def clear_ml(self, event):
        self._clear()

    @handler('refresh_ml')
    def refresh_ml(self, event):
        self._transmit(self.last_frame)

    def _transmit(self, image):
        if self.output_broken and not self.auto_restart:
            return

        self.log('Transmitting image, shape:', image.shape, lvl=verbose)

        self.last_frame = image

        if self.gamma != 1:
            image = (image * self.gamma).astype(np.uint8)

        ml_data = bytearray(image) + b"\00\00\00\00"

        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            sock.sendto(ml_data, (self.host, self.port))
        except Exception as e:
            self.log("Error during matelight transmission: ", e)
            self.output_broken = True

    def transmit_ml(self, event):
        if self.fade_timer is not None:
            self.fade_timer.unregister()
            self.fade_timer = None

        self._transmit(event.frame)

    @handler('keypress')
    def keypress(self, event):
        if event.ev.key == 223 and event.ev.mod == 1:
            self._transmit(self.boot_image)
            Timer(2, fade_out_ml()).register(self)
        if event.ev.mod & pygame.KMOD_LCTRL and event.ev.mod & pygame.KMOD_LSHIFT:
            if event.ev.key == pygame.K_MINUS:
                self.gamma = max(0.1, self.gamma - 0.1)
            elif event.ev.key == pygame.K_PLUS:
                self.gamma = min(1, self.gamma + 0.1)
            self.log(self.gamma)