fix the queue stream
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Mon, 10 Jun 2019 13:14:51 +0000 (15:14 +0200)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Mon, 10 Jun 2019 13:14:51 +0000 (15:14 +0200)
music_assistant/models.py
music_assistant/modules/http_streamer.py
music_assistant/modules/player.py
music_assistant/modules/playerproviders/chromecast.py
music_assistant/modules/playerproviders/lms.py
music_assistant/modules/playerproviders/pylms.py

index 982b0a48d2bb0c87ec77d127615ae18cbe408f81..1de7e006a549225e3ee56168942d6b11c6a3ce5f 100755 (executable)
@@ -505,8 +505,6 @@ class MusicPlayer():
         self.powered = False
         self.cur_item = None
         self.cur_item_time = 0
-        self.cur_queue_index = 0
-        self.next_queue_index = 0
         self.volume_level = 0
         self.shuffle_enabled = True
         self.repeat_enabled = False
index 1effcbf8c8a2cb1bed83f446f1fa830bd360ff61..0c89ee6f32466bcbb8c086f09f57952a6d5ae830 100755 (executable)
@@ -134,7 +134,7 @@ class HTTPStreamer():
             use case is enable crossfade support for chromecast devices 
         '''
         player_id = http_request.query.get('player_id')
-        startindex = int(http_request.query.get('startindex', 0))
+        startindex = int(http_request.query.get('startindex'))
         cancelled = threading.Event()
         resp = web.StreamResponse(status=200,
                                  reason='OK',
@@ -179,9 +179,14 @@ class HTTPStreamer():
             await buffer.put(b'') # indicate EOF
         asyncio.create_task(fill_buffer())
 
+        player = await self.mass.player.player(player_id)
+
+        # retrieve player object
         player = await self.mass.player.player(player_id)
         queue_index = startindex
+        LOGGER.info("Start Queue Stream for player %s at index %s" %(player_id, queue_index))
         last_fadeout_data = b''
+        # report start of queue playback so we can calculate current track/duration etc.
         self.mass.event_loop.create_task(self.mass.player.player_queue_stream_update(player_id, queue_index, True))
         while True:
             # get the (next) track in queue
@@ -265,14 +270,14 @@ class HTTPStreamer():
                 while buffer.qsize() > 1 and not cancelled.is_set():
                     await asyncio.sleep(1)
             # end of the track reached
-            LOGGER.info("Finished Streaming queue track: %s - %s" % (track_id, queue_track.name))
-            # update actual duration to the queue for more accurate now playing info
+            # WIP: update actual duration to the queue for more accurate now playing info
             accurate_duration = bytes_written / int(sample_rate * 4 * 2)
             queue_track.duration = accurate_duration
             self.mass.player.providers[player.player_provider]._player_queue[player_id][queue_index] = queue_track
             # move to next queue index
             queue_index += 1
             self.mass.event_loop.create_task(self.mass.player.player_queue_stream_update(player_id, queue_index, False))
+            LOGGER.info("Finished Streaming queue track: %s - %s" % (track_id, queue_track.name))
             # break out the loop if the http session is cancelled
             if cancelled.is_set():
                 break
index add13064cab62ce07dbcf0027cff0c7964a5c0df..52fd7a68188a0de2f6745c4b32e38ba4d9ac59b4 100755 (executable)
@@ -392,7 +392,9 @@ class Player():
 
     async def player_queue_index(self, player_id):
         ''' get current index of the player's queue '''
-        return self._players[player_id].cur_queue_index
+        player = self._players[player_id]
+        player_prov = self.providers[player.player_provider]
+        return await player_prov.player_queue_index(player_id)
 
     async def player_queue_stream_update(self, player_id, cur_index, is_start=False):
         ''' called by our queue streamer when it started playing the queue from position x '''
index adb887b2ec9cb2a05ea55c242838d32993d31e64..05c26d8a2775217dd14b8fae994562f5d1e28f1f 100644 (file)
@@ -52,7 +52,8 @@ class ChromecastProvider(PlayerProvider):
         self._players = {}
         self._chromecasts = {}
         self._player_queue = {}
-        self._player_queue_startindex = {}
+        self._player_queue_index = {}
+        self._player_queue_stream_startindex = {}
         self.supported_musicproviders = ['http']
         asyncio.ensure_future(self.__discover_chromecasts())
         
@@ -87,12 +88,12 @@ class ChromecastProvider(PlayerProvider):
         elif cmd == 'next':
             enable_crossfade = self.mass.config['player_settings'][player_id]["crossfade_duration"] > 0
             if enable_crossfade:
-                await self.__play_stream_queue(player_id, self._players[player_id].cur_queue_index+1)
+                await self.__play_stream_queue(player_id, self._player_queue_index[player_id]+1)
             else:
                 self._chromecasts[player_id].media_controller.queue_next()
         elif cmd == 'previous':
             if enable_crossfade:
-                await self.__play_stream_queue(player_id, self._players[player_id].cur_queue_index-1)
+                await self.__play_stream_queue(player_id, self._player_queue_index[player_id]-1)
             else:
                 self._chromecasts[player_id].media_controller.queue_prev()
         elif cmd == 'power' and cmd_args == 'off':
@@ -115,12 +116,16 @@ class ChromecastProvider(PlayerProvider):
         ''' return the current items in the player's queue '''
         return self._player_queue[player_id][offset:limit]
     
+    async def player_queue_index(self, player_id):
+        ''' get current index of the player's queue '''
+        return self._player_queue_index[player_id]
+    
     async def play_media(self, player_id, media_items, queue_opt='play'):
         ''' 
             play media on a player
         '''
         castplayer = self._chromecasts[player_id]
-        cur_queue_index = self._players[player_id].cur_queue_index
+        cur_queue_index = self._player_queue_index.get(player_id, 0)
         enable_crossfade = self.mass.config['player_settings'][player_id]["crossfade_duration"] > 0
 
         if queue_opt == 'replace' or not self._player_queue[player_id]:
@@ -161,7 +166,8 @@ class ChromecastProvider(PlayerProvider):
     async def player_queue_stream_update(self, player_id, cur_index, is_start=False):
         ''' called by our queue streamer when it started playing a track in the queue at index X '''
         if is_start:
-            self._player_queue_startindex[player_id] = cur_index
+            self._player_queue_stream_startindex[player_id] = cur_index
+            self._player_queue_index[player_id] = cur_index
         # schedule update a few times as we don't know how much time is prebuffered
         for i in range(0, 20):
             castplayer = self._chromecasts[player_id]
@@ -308,17 +314,21 @@ class ChromecastProvider(PlayerProvider):
                 player.state = PlayerState.Paused
             else:
                 player.state = PlayerState.Stopped
-            if not 'stream_queue' in mediastatus.content_id:
+            if not mediastatus.content_id:
+                player.cur_item = None
+                player.cur_item_time = 0
+            elif not 'stream_queue' in mediastatus.content_id:
                 player.cur_item = await self.__parse_track(mediastatus)
                 player.cur_item_time =  mediastatus.adjusted_current_time
-                player.cur_queue_index = await self.__get_cur_queue_index(player_id, mediastatus.content_id)
-            else:
+                self._player_queue_index[player_id] = await self.__get_cur_queue_index(player_id, mediastatus.content_id)
+            elif 'stream_queue' in mediastatus.content_id:
+                # player is playing our special queue continuous stream
                 # try to work out the current time
                 # player is playing a constant stream of the queue so we need to do this the hard way
                 cur_time_queue = mediastatus.adjusted_current_time
                 total_time = 0
                 track_time = 0
-                queue_index = self._player_queue_startindex[player_id]
+                queue_index = self._player_queue_stream_startindex[player_id]
                 queue_track = None
                 while True:
                     queue_track = self._player_queue[player_id][queue_index]
@@ -330,7 +340,7 @@ class ChromecastProvider(PlayerProvider):
                         break
                 player.cur_item = queue_track
                 player.cur_item_time = track_time
-                player.cur_queue_index = queue_index
+                self._player_queue_index[player_id] = queue_index
         await self.mass.player.update_player(player)
 
     async def __parse_track(self, mediastatus):
@@ -413,6 +423,7 @@ class ChromecastProvider(PlayerProvider):
             if not player_id in self._player_queue:
                 # TODO: persistant storage of player queue ?
                 self._player_queue[player_id] = []
+                self._player_queue_index[player_id] = 0
             chromecast.wait()
 
     @run_periodic(600)
index a50595ad31ca0d2336e8d6f8fd513d21b99761de..5eb166adc6f21fba7872919a78f710f97b26b8b2 100644 (file)
@@ -49,7 +49,6 @@ class LMSProvider(PlayerProvider):
         self._players = {}
         self._host = hostname
         self._port = port
-        self._players = {}
         self.last_msg_received = 0
         self.supported_musicproviders = ['qobuz', 'file', 'spotify', 'http']
         self.http_session = aiohttp.ClientSession(loop=mass.event_loop)
@@ -127,6 +126,10 @@ class LMSProvider(PlayerProvider):
                 items.append(track)
         return items
 
+    async def player_queue_index(self, player_id):
+        ''' get current index of the player's queue '''
+        raise NotImplementedError()
+
     ### Provider specific (helper) methods #####
     
     async def __get_players(self):
index bbaf659541839f21614c8ef25977066f07066693..15c06088d523ec22a5e493bb790875434163300d 100644 (file)
@@ -101,6 +101,10 @@ class PyLMSServer(PlayerProvider):
         ''' return the current items in the player's queue '''
         return self._player_queue[player_id][offset:limit]
     
+    async def player_queue_index(self, player_id):
+        ''' get current index of the player's queue '''
+        return self._player_queue_index.get(player_id, 0)
+    
     async def play_media(self, player_id, media_items, queue_opt='play'):
         ''' 
             play media on a player