Beispiel #1
0
def base64_encode_image(filename):
    """:return the base64 encoded image if filename was a image else None"""
    try:
        imgfile = open(filename, "rb")
        img = imgfile.read(1024)
    except IOError as err:
        log("Artwork '{0}' won't be displayed: {2}".
            format(filename, err.message), min_verbosity=1, error=True)
        return None
    mimetype = APP.magic.buffer(img).lower()
    mimere = re.compile(r'(?P<mimetype>image/(png|jpeg|jpg|bmp|gif)).*')
    mimes = mimere.findall(mimetype)
    if len(mimes) == 1:
        mimetype = mimes[0][0]
        img += imgfile.read()  # read remeaning file
        imgfile.close()
        imgstr = str(base64.b64encode(img).decode('ascii'))
        imgstr = imgstr.replace('\n', '')
        return "data:{mime};base64,{base64}".format(
            mime=mimetype, base64=imgstr)
    else:
        log("Artwork '{0}' rejected: invalid mimetype '{1}'".
            format(filename, mimetype), min_verbosity=1, error=True)
        imgfile.close()
        return None
Beispiel #2
0
 def open(self):
     """when a client connects, add this socket to list"""
     APP.clients.append(self)
     mpris_prop_change_handler()
     self.send_status()
     log("WebSocket opened. {0} child(s) connected".
         format(len(APP.clients)), min_verbosity=1)
Beispiel #3
0
 def glib_loop_thread(self):
     """
     runs the GLib main loop to get notified about player status changes
     """
     self.mloop.run()
     log("GLib loop exited", min_verbosity=2)
     thread.exit_thread()
Beispiel #4
0
 def __init__(self, prop_changed_handler):
     """
     :param properties_changed_handler: a function that will be executed on
     status changes like `def handler(self, *args, **kw)`
     """
     # initialize DBus:
     DBusGMainLoop(set_as_default=True)
     self.prop_changed_handler = prop_changed_handler
     self.try_connect()
     if not self.player:
         log("No MPRIS player available. " +
             "Please start your favourite music player with MPRIS support.",
             min_verbosity=0, error=True)
     self.mloop = gi.repository.GLib.MainLoop()
     thread.start_new_thread(self.glib_loop_thread, ())
     thread.start_new_thread(self.check_connection_thread, ())
     signal.signal(signal.SIGINT, self.sigint_handler)
Beispiel #5
0
 def check_connection_thread(self):
     """
     checks if the currently connected player is connected and
     tries to reconnect if not
     """
     while True:
         time.sleep(5)
         try:
             self.player.CanControl
             # -> AttributeError when None
             # -> DBusException when not connected anymore
             # I found no other method to test this
             # -> better sorry than safe
             log("Player is still connected", min_verbosity=5)
         # except AttributeError, dbus.exceptions.DBusException:
         except (AttributeError, dbus.exceptions.DBusException):
             log("Player is NOT connected", min_verbosity=5)
             self.try_connect()
             self.prop_changed_handler()
Beispiel #6
0
def main():
    """the main function starts the server"""
    global APP
    APP = make_app()
    APP.args = parse_args()
    APP.clients = []  # global list of all connected websocket clients
    APP.mpris_wrapper = MPRISWrapper(mpris_prop_change_handler)
    log("Loading magic file for mimetypes. Please wait.", min_verbosity=1)
    APP.magic = magic.open(magic.MAGIC_MIME_TYPE)
    APP.magic.load()
    log("Loading finished.", min_verbosity=2)
    APP.listen(APP.args.port, address=APP.args.ip)
    log("App will listen on http://{ip}:{port}".format(
        ip=APP.args.ip, port=APP.args.port))
    tornado.ioloop.IOLoop.current().start()
Beispiel #7
0
 def try_connect(self):
     """
     Sets self.player to a player and sets the prop_changed_handler
     if there is a mpris player on dbus or sets self.player to None
     """
     log("Try to connect to player", min_verbosity=4)
     uris = list(mpris2.get_players_uri())
     if len(uris):
         self.player = mpris2.Player(dbus_interface_info={
             'dbus_uri': uris[0]  # connects to the first player
         })
         self.player.PropertiesChanged = self.prop_changed_handler
         log("Connected to player", min_verbosity=4)
     else:
         log("Can't connect. No MPRIS player available",
             min_verbosity=4, error=True)
         self.player = None
Beispiel #8
0
def mpris_prop_change_handler(*args, **kw):
    """function will be executed on mpris player property changes"""
    meta = {
        "titles": {
            "current": APP.mpris_wrapper.get_current_title(),
            "next": APP.mpris_wrapper.get_next_title(),
        },
        "trackMetadata": APP.mpris_wrapper.get_current_metadata(),
        "status": APP.mpris_wrapper.get_playback_status(),
        "player": {
            "canControl": APP.mpris_wrapper.get_can_control(),
            "canGoNext": APP.mpris_wrapper.get_can_go_next(),
            "canGoPrevious": APP.mpris_wrapper.get_can_go_previous(),
            "canPlay": APP.mpris_wrapper.get_can_play(),
            "canPause": APP.mpris_wrapper.get_can_pause(),
        },
        "volume": APP.mpris_wrapper.volume,
    }
    if 'trackMetadata' in meta.keys() and \
            'artUri' in meta['trackMetadata'].keys() and \
            meta['trackMetadata']['artUri']:
        arturi = meta['trackMetadata']['artUri']
        arturi = arturi.strip().replace("file://", '')
        if arturi and os.path.isfile(arturi):
            image = base64_encode_image(arturi)
            if image:
                meta['trackMetadata']['art'] = image
            else:
                log("Artwork '{0}' won't be displayed: could not open file".
                    format(arturi), min_verbosity=1, error=True)
        else:
            log("Artwork '{0}' won't be displayed: file not found".
                format(arturi), min_verbosity=3, error=True)
        del meta['trackMetadata']['artUri']
    else:
        log("Track has no Artwork", min_verbosity=4)

    APP.meta_status = meta
    for client in APP.clients:
        client.send_status()
Beispiel #9
0
 def on_message(self, message):
     """new message received"""
     try:
         msg = json.loads(message)
     except ValueError:
         log("Client sent an invalid message: {0}".format(message),
             error=True)
         return
     if 'action' not in msg:
         log("invalid message received from client: '{0}'".
             format(str(msg)),
             min_verbosity=2, error=True)
         return
     elif msg['action'] == 'backward':
         APP.mpris_wrapper.previous()
     elif msg['action'] == 'play':
         APP.mpris_wrapper.play()
     elif msg['action'] == 'pause':
         APP.mpris_wrapper.pause()
     elif msg['action'] == 'stop':
         APP.mpris_wrapper.stop()
     elif msg['action'] == 'forward':
         APP.mpris_wrapper.next()
     elif msg['action'] == 'volume':
         if 'value' in msg.keys():
             try:
                 APP.mpris_wrapper.volume = float(msg['value'])
             except ValueError as err:
                 log(("Invalid value '{0}' for volume " +
                      "in message from client: {1}").
                     format(msg['value'], err.message),
                     min_verbosity=1, error=True)
         else:
             log("Missing value for action 'volume' in message from client",
                 min_verbosity=1, error=True)
     else:
         log("invalid action '{0}' received from client".
             format(msg['action']),
             min_verbosity=1, error=True)
     log("received: " + message, min_verbosity=2)
Beispiel #10
0
 def on_close(self):
     """the client of this socket leaved, remove this socket from list"""
     APP.clients.remove(self)
     log("WebSocket closed. {0} child(s) connected".
         format(len(APP.clients)), min_verbosity=1)
Beispiel #11
0
 def send_status(self):
     """sends the current and next tracks to the client"""
     self.write_message(json.dumps(APP.meta_status), binary=False)
     log("send: {0}".format(APP.meta_status), min_verbosity=3)
Beispiel #12
0
 def sigint_handler(self, sig, frame):
     """Stop on sigint (Ctrl+C)"""
     log("Signal {0} in frame {1} caught".format(sig, frame),
         min_verbosity=1)
     self.mloop.quit()
     exit(0)