chromecast discovery
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Tue, 27 Aug 2019 06:42:27 +0000 (08:42 +0200)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Tue, 27 Aug 2019 06:42:27 +0000 (08:42 +0200)
trigger rescan if command fails

music_assistant/modules/player.py
music_assistant/modules/playerproviders/chromecast.py
music_assistant/web/components/headermenu.vue.js

index da0e50a48d14b8a6906d2309a6cee3daa836ddd4..0276c9ea4e92fb8b59ad5d849b32690387f9e556 100755 (executable)
@@ -199,10 +199,24 @@ class Player():
             player_childs = [item for item in self._players.values() if item.group_parent == player_id]
             if player.settings['apply_group_volume']:
                 player_details.volume_level = await self.__get_group_volume(player_childs)
-        # compare values to detect changes
+        # detect current track changes
         if player.cur_item and player_details.cur_item and player.cur_item.name != player_details.cur_item.name:
+            # track changed
+            player_changed = True
+            LOGGER.info("%s -- STOP PLAYING %s -- SECONDS PLAYED: %s" %(player.name, player.cur_item.name, player.cur_item_time))
+            LOGGER.info("%s -- START PLAYING %s" %(player.name, player_details.cur_item.name))
+            player.cur_item = player_details.cur_item
+        elif not player.cur_item and player_details.cur_item:
+            # player started playing
             player_changed = True
-        player.cur_item = player_details.cur_item
+            LOGGER.info("%s -- START PLAYING %s" %(player.name, player_details.cur_item.name))
+            player.cur_item = player_details.cur_item
+        elif player.cur_item and not player_details.cur_item:
+            # player queue cleared
+            player_changed = True
+            LOGGER.info("%s -- STOP PLAYING %s -- SECONDS PLAYED: %s" %(player.name, player.cur_item.name, player.cur_item_time))
+            player.cur_item = player_details.cur_item
+        # compare values to detect changes
         for key, cur_value in player.__dict__.items():
             if key != 'settings':
                 new_value = getattr(player_details, key)
index 6e1898bbbac60be4390ac3a52e2c92a555bb5abf..cbc11cf2601ebd887e725bfb9bf9d17b128ff69c 100644 (file)
@@ -49,8 +49,9 @@ class ChromecastProvider(PlayerProvider):
         self._player_queue = {}
         self._player_queue_index = {}
         self._player_queue_stream_startindex = {}
+        self._discovery_running = False
         self.supported_musicproviders = ['http']
-        self.mass.event_loop.create_task(self.__chromecast_discovery())
+        self.mass.event_loop.create_task(self.__periodic_chromecast_discovery())
         
     ### Provider specific implementation #####
 
@@ -65,48 +66,52 @@ class ChromecastProvider(PlayerProvider):
 
     async def player_command(self, player_id, cmd:str, cmd_args=None):
         ''' issue command on player (play, pause, next, previous, stop, power, volume, mute) '''
-        if cmd == 'play':
-            self._players[player_id].powered = True
-            if self._chromecasts[player_id].media_controller.status.player_is_playing:
-                pass
-            elif self._chromecasts[player_id].media_controller.status.player_is_paused:
-                self._chromecasts[player_id].media_controller.play()
-            else:
-                await self.__resume_queue(player_id)
-            await self.mass.player.update_player(self._players[player_id])
-        elif cmd == 'pause':
-            self._chromecasts[player_id].media_controller.pause()
-        elif cmd == 'stop':
-            self._chromecasts[player_id].media_controller.stop()
-        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._player_queue_index[player_id]+1)
-            else:
-                self._chromecasts[player_id].media_controller.queue_next()
-        elif cmd == 'previous':
-            enable_crossfade = self.mass.config['player_settings'][player_id]["crossfade_duration"] > 0
-            if enable_crossfade:
-                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':
-            self._players[player_id].powered = False
-            if not self._players[player_id].group_parent:
-                self._chromecasts[player_id].quit_app() # power is not supported so send quit_app instead
-            await self.mass.player.update_player(self._players[player_id])
-        elif cmd == 'power':
-            self._players[player_id].powered = True
-            await self.mass.player.update_player(self._players[player_id])
-        elif cmd == 'volume':
-            new_volume = try_parse_int(cmd_args)
-            self._chromecasts[player_id].set_volume(new_volume/100)
-            self._players[player_id].volume_level = new_volume
-            await self.mass.player.update_player(self._players[player_id])
-        elif cmd == 'mute' and cmd_args == 'off':
-            self._chromecasts[player_id].set_volume_muted(False)
-        elif cmd == 'mute':
-            self._chromecasts[player_id].set_volume_muted(True)
+        try:
+            if cmd == 'play':
+                self._players[player_id].powered = True
+                if self._chromecasts[player_id].media_controller.status.player_is_playing:
+                    pass
+                elif self._chromecasts[player_id].media_controller.status.player_is_paused:
+                    self._chromecasts[player_id].media_controller.play()
+                else:
+                    await self.__resume_queue(player_id)
+                await self.mass.player.update_player(self._players[player_id])
+            elif cmd == 'pause':
+                self._chromecasts[player_id].media_controller.pause()
+            elif cmd == 'stop':
+                self._chromecasts[player_id].media_controller.stop()
+            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._player_queue_index[player_id]+1)
+                else:
+                    self._chromecasts[player_id].media_controller.queue_next()
+            elif cmd == 'previous':
+                enable_crossfade = self.mass.config['player_settings'][player_id]["crossfade_duration"] > 0
+                if enable_crossfade:
+                    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':
+                self._players[player_id].powered = False
+                if not self._players[player_id].group_parent:
+                    self._chromecasts[player_id].quit_app() # power is not supported so send quit_app instead
+                await self.mass.player.update_player(self._players[player_id])
+            elif cmd == 'power':
+                self._players[player_id].powered = True
+                await self.mass.player.update_player(self._players[player_id])
+            elif cmd == 'volume':
+                new_volume = try_parse_int(cmd_args)
+                self._chromecasts[player_id].set_volume(new_volume/100)
+                self._players[player_id].volume_level = new_volume
+                await self.mass.player.update_player(self._players[player_id])
+            elif cmd == 'mute' and cmd_args == 'off':
+                self._chromecasts[player_id].set_volume_muted(False)
+            elif cmd == 'mute':
+                self._chromecasts[player_id].set_volume_muted(True)
+        except pychromecast.error.NotConnected:
+            # CC is not connected, trigger rescan
+            self.mass.event_loop.create_task(self.__chromecast_discovery())
 
     async def player_queue(self, player_id, offset=0, limit=50):
         ''' return the current items in the player's queue '''
@@ -388,9 +393,16 @@ class ChromecastProvider(PlayerProvider):
                     self._players[member].group_parent = str(mz._uuid)
                     self.mass.event_loop.create_task(self.mass.player.update_player(self._players[member]))
     
-    @run_periodic(300)
+    @run_periodic(1800)
+    async def __periodic_chromecast_discovery(self):
+        ''' run chromecast discovery on interval '''
+        await self.__chromecast_discovery()
+
     async def __chromecast_discovery(self):
         ''' background non-blocking chromecast discovery and handler '''
+        if self._discovery_running:
+            return
+        self._discovery_running = True
         # remove any disconnected players...
         removed_players = []
         for player_id, cast in self._chromecasts.items():
@@ -399,9 +411,9 @@ class ChromecastProvider(PlayerProvider):
                 removed_players.append(player_id)
         for player_id in removed_players:
             self._chromecasts[player_id].socket_client.stop.set()
+            await asyncio.sleep(1)
             self._chromecasts.pop(player_id, None)
             await self.mass.player.remove_player(player_id)
-        await asyncio.sleep(5)
         # search for available chromecasts
         from pychromecast.discovery import start_discovery, stop_discovery
         def discovered_callback(name):
@@ -418,6 +430,7 @@ class ChromecastProvider(PlayerProvider):
         await asyncio.sleep(15) # run discovery for 15 seconds
         stop_discovery(browser)
         LOGGER.debug("Chromecast discovery completed...")
+        self._discovery_running = True
     
     async def __chromecast_discovered(self, player_id, discovery_info):
         ''' callback when a (new) chromecast device is discovered '''
index eda7b28eb12e1d924c947d2c681216d7c0bee9e3..f0e8566f2f73352059e83b96772a677bbab684d2 100755 (executable)
@@ -26,9 +26,6 @@ Vue.component("headermenu", {
             <v-btn @click="$router.go(-1)" icon v-if="$route.path != '/'">
               <v-icon>arrow_back</v-icon>
             </v-btn>
-          
-            
-            
         </v-layout>
     </v-toolbar>
     <v-toolbar flat fixed dense dark scroll-off-screen color="transparent" v-if="!$globals.windowtitle" >