fix config save
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Fri, 24 May 2019 21:00:46 +0000 (23:00 +0200)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Fri, 24 May 2019 21:00:46 +0000 (23:00 +0200)
music_assistant/modules/player.py
music_assistant/modules/playerproviders/pylms.py
music_assistant/modules/web.py
music_assistant/web/pages/config.vue.js

index d5496ba064e6294ef298f716e7d407bee9376870..218a302522ab034a47d1ae6f02f70757a72f1d3f 100755 (executable)
@@ -46,9 +46,9 @@ class Player():
             cmd = 'pause' if player.state == PlayerState.Playing else 'play'
         if cmd == 'power' and cmd_args == 'toggle':
             cmd_args = 'off' if player.powered else 'on'
-        if cmd == 'volume' and cmd_args == 'up':
+        if cmd == 'volume' and (cmd_args == 'up' or '+' in cmd_args):
             cmd_args = player.volume_level + 2
-        elif cmd == 'volume' and cmd_args == 'down':
+        elif cmd == 'volume' and (cmd_args == 'down' or '-' in cmd_args):
             cmd_args = player.volume_level - 2
         # redirect playlist related commands to parent player
         if player.group_parent and cmd not in ['power', 'volume', 'mute']:
index fb29c7b26eda2362597234f86fd9f4e52c9b5149..65da48f33006a41118854b5f085e8bc547548192 100644 (file)
@@ -45,6 +45,7 @@ class PyLMSServer(PlayerProvider):
         self.buffer = b''
         self.last_msg_received = 0
         self.supported_musicproviders = ['http']
+        
         # start slimproto server
         mass.event_loop.create_task(asyncio.start_server(self.__handle_socket_client, '0.0.0.0', 3483))
         # setup discovery
@@ -53,7 +54,6 @@ class PyLMSServer(PlayerProvider):
                 family=socket.AF_INET, reuse_address=True, reuse_port=True,
             allow_broadcast=True)
         mass.event_loop.create_task(listen)
-        
 
      ### Provider specific implementation #####
 
@@ -202,32 +202,30 @@ class PyLMSServer(PlayerProvider):
                 self._lmsplayers[lms_player.player_id] = lms_player
             asyncio.create_task(self.__handle_player_event(lms_player.player_id, event, event_data))
 
-        @run_periodic(5)
-        async def send_heartbeat():
-            try:
+        try:
+            @run_periodic(5)
+            async def send_heartbeat():
                 timestamp = int(time.time())
                 data = lms_player.pack_stream(b"t", replayGain=timestamp, flags=0)
                 lms_player.send_frame(b"strm", data)
-            except RuntimeError:
-                reader.close()
 
-        lms_player.send_frame = send_frame
-        lms_player.send_event = handle_event
-        heartbeat_task = asyncio.create_task(send_heartbeat())
-        
-        # keep reading bytes from the socket
-        while True:
-            data = await reader.read(64)
-            if data:
-                lms_player.dataReceived(data)
-            else:
-                break
+            lms_player.send_frame = send_frame
+            lms_player.send_event = handle_event
+            heartbeat_task = asyncio.create_task(send_heartbeat())
+            
+            # keep reading bytes from the socket
+            while True:
+                data = await reader.read(64)
+                if data:
+                    lms_player.dataReceived(data)
+                else:
+                    break
+        except RuntimeError:
+            LOGGER.warning("connection lost")
         # disconnect
         heartbeat_task.cancel()
         asyncio.create_task(self.__handle_player_event(lms_player.player_id, 'disconnected'))
 
-    
-    ### Provider specific implementation #####
 
 class PyLMSPlayer(object):
     ''' very basic Python implementation of SlimProto '''
index 62099c5d31f1d1753664c27eec43c233cbcb9027..1820dd0a5a618bd6d953385844988b5bf84fd8f4 100755 (executable)
@@ -65,6 +65,8 @@ class Web():
 
     async def setup_web(self):
         app = web.Application()
+        app.add_routes([web.get('/jsonrpc.js', self.json_rpc)])
+        app.add_routes([web.post('/jsonrpc.js', self.json_rpc)])
         app.add_routes([web.get('/ws', self.websocket_handler)])
         app.add_routes([web.get('/stream', self.stream)])
         app.add_routes([web.get('/api/search', self.search)])
@@ -85,7 +87,6 @@ class Web():
         app.add_routes([web.get('/api/{media_type}/{media_id}', self.get_item)])
         app.add_routes([web.get('/', self.index)])
         app.router.add_static("/", "./web")  
-        
         self.runner = web.AppRunner(app)
         await self.runner.setup()
         http_site = web.TCPSite(self.runner, '0.0.0.0', self._http_port)
@@ -279,4 +280,38 @@ class Web():
         if request.method.upper() != 'HEAD':
             async for chunk in self.mass.http_streamer.get_audio_stream(track_id, provider, player_id):
                 await resp.write(chunk)
-        return resp
\ No newline at end of file
+        return resp
+
+    async def json_rpc(self, request):
+        ''' 
+            implement fake LMS jsonrpc interface 
+            for some compatability with tools that talk to lms
+            only support for basic commands
+        '''
+        data = await request.json()
+        params = data['params']
+        player_id = params[0]
+        cmds = params[1]
+        cmd_str = " ".join(cmds)
+        if cmd_str in ['play', 'pause', 'stop']:
+            await self.mass.player.player_command(player_id, cmd_str)
+        elif 'power' in cmd_str:
+            await self.mass.player.player_command(player_id, cmd_str, cmd_str[1])
+        elif cmd_str == 'playlist index +1':
+            await self.mass.player.player_command(player_id, 'next')
+        elif cmd_str == 'playlist index -1':
+            await self.mass.player.player_command(player_id, 'previous')
+        elif 'mixer volume' in cmd_str:
+            await self.mass.player.player_command(player_id, 'volume', cmd_str[2])
+        elif cmd_str == 'mixer muting 1':
+            await self.mass.player.player_command(player_id, 'mute', 'on')
+        elif cmd_str == 'mixer muting 0':
+            await self.mass.player.player_command(player_id, 'mute', 'off')
+        elif cmd_str == 'button volup':
+            await self.mass.player.player_command(player_id, 'volume', 'up')
+        elif cmd_str == 'button voldown':
+            await self.mass.player.player_command(player_id, 'volume', 'down')
+        elif cmd_str == 'button power':
+            await self.mass.player.player_command(player_id, 'power', 'toggle')
+        return web.Response(text='success')
+        
\ No newline at end of file
index dfd27c34dc209b05e424341c85c076bfa4de71ad..d2bb3eed0be2dcb214858b49a332f9cbc8f221bb 100755 (executable)
@@ -92,14 +92,14 @@ var Config = Vue.component('Config', {
         playersLst.push({id: player_id, name: this.conf.player_settings[player_id].name})
       return playersLst;
     }
-
   },
   watch: {
-    conf: {
-      handler: _.debounce(function (val) {
-        console.log("save config needed!");
-        this.saveConfig();
-      }, 1000)
+    'conf': {
+        handler: _.debounce(function (val, oldVal) {
+          console.log("save config needed!");
+          this.saveConfig();
+        }, 5000),
+        deep: true
     }
   },
   created() {