From: marcelveldt Date: Sun, 19 May 2019 22:28:24 +0000 (+0200) Subject: some more fixes for http streamer X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=848d00ebf70074be12137c06854d0feaa7d98cc0;p=music-assistant-server.git some more fixes for http streamer --- diff --git a/music_assistant/modules/musicproviders/file.py b/music_assistant/modules/musicproviders/file.py index 7d883c40..8f7900ab 100644 --- a/music_assistant/modules/musicproviders/file.py +++ b/music_assistant/modules/musicproviders/file.py @@ -11,6 +11,7 @@ from models import MusicProvider, MediaType, TrackQuality, AlbumType, Artist, Al from constants import CONF_ENABLED import taglib from modules.cache import use_cache +import base64 def setup(mass): @@ -104,34 +105,37 @@ class FileProvider(MusicProvider): async def get_artist(self, prov_item_id) -> Artist: ''' get full artist details by id ''' - if not os.path.isdir(prov_item_id): - LOGGER.error("artist path does not exist: %s" % prov_item_id) - return None - if "\\" in prov_item_id: - name = prov_item_id.split("\\")[-1] + if not os.sep in prov_item_id: + itempath = base64.b64decode(prov_item_id).decode('utf-8') else: - name = prov_item_id.split("/")[-1] + itempath = prov_item_id + prov_item_id = base64.b64encode(itempath.encode('utf-8')).decode('utf-8') + if not os.path.isdir(itempath): + LOGGER.error("artist path does not exist: %s" % itempath) + return None + name = itempath.split(os.sep)[-1] artist = Artist() artist.item_id = prov_item_id artist.provider = self.prov_id artist.name = name artist.provider_ids.append({ "provider": self.prov_id, - "item_id": prov_item_id + "item_id": artist.item_id }) return artist async def get_album(self, prov_item_id) -> Album: ''' get full album details by id ''' - if not os.path.isdir(prov_item_id): - LOGGER.error("album path does not exist: %s" % prov_item_id) - return None - if "\\" in prov_item_id: - name = prov_item_id.split("\\")[-1] - artistpath = prov_item_id.rsplit("\\", 1)[0] + if not os.sep in prov_item_id: + itempath = base64.b64decode(prov_item_id).decode('utf-8') else: - name = prov_item_id.split("/")[-1] - artistpath = prov_item_id.rsplit("/", 1)[0] + itempath = prov_item_id + prov_item_id = base64.b64encode(itempath.encode('utf-8')).decode('utf-8') + if not os.path.isdir(itempath): + LOGGER.error("album path does not exist: %s" % itempath) + return None + name = itempath.split(os.sep)[-1] + artistpath = itempath.rsplit(os.sep, 1)[0] album = Album() album.item_id = prov_item_id album.provider = self.prov_id @@ -147,25 +151,33 @@ class FileProvider(MusicProvider): async def get_track(self, prov_item_id) -> Track: ''' get full track details by id ''' - if not os.path.isfile(prov_item_id): - LOGGER.error("track path does not exist: %s" % prov_item_id) + if not os.sep in prov_item_id: + itempath = base64.b64decode(prov_item_id).decode('utf-8') + else: + itempath = prov_item_id + if not os.path.isfile(itempath): + LOGGER.error("track path does not exist: %s" % itempath) return None - return await self.__parse_track(prov_item_id) + return await self.__parse_track(itempath) async def get_playlist(self, prov_item_id) -> Playlist: ''' get full playlist details by id ''' - if not os.path.isfile(prov_item_id): - LOGGER.error("playlist path does not exist: %s" % prov_item_id) + if not os.sep in prov_item_id: + itempath = base64.b64decode(prov_item_id).decode('utf-8') + else: + itempath = prov_item_id + prov_item_id = base64.b64encode(itempath.encode('utf-8')).decode('utf-8') + if not os.path.isfile(itempath): + LOGGER.error("playlist path does not exist: %s" % itempath) return None - filepath = prov_item_id playlist = Playlist() - playlist.item_id = filepath + playlist.item_id = prov_item_id playlist.provider = self.prov_id - playlist.name = filepath.split('\\')[-1].split('/')[-1].replace('.m3u', '') + playlist.name = itempath.split(os.sep)[-1].replace('.m3u', '') playlist.is_editable = True playlist.provider_ids.append({ "provider": self.prov_id, - "item_id": filepath + "item_id": prov_item_id }) playlist.owner = 'disk' return playlist @@ -173,7 +185,10 @@ class FileProvider(MusicProvider): async def get_album_tracks(self, prov_album_id) -> List[Track]: ''' get album tracks for given album id ''' result = [] - albumpath = prov_album_id + if not os.sep in prov_album_id: + albumpath = base64.b64decode(prov_album_id).decode('utf-8') + else: + albumpath = prov_album_id if not os.path.isdir(albumpath): LOGGER.error("album path does not exist: %s" % albumpath) return [] @@ -190,11 +205,15 @@ class FileProvider(MusicProvider): async def get_playlist_tracks(self, prov_playlist_id, limit=50, offset=0) -> List[Track]: ''' get playlist tracks for given playlist id ''' tracks = [] - if not os.path.isfile(prov_playlist_id): - LOGGER.error("playlist path does not exist: %s" % prov_playlist_id) + if not os.sep in prov_playlist_id: + itempath = base64.b64decode(prov_playlist_id).decode('utf-8') + else: + itempath = prov_playlist_id + if not os.path.isfile(itempath): + LOGGER.error("playlist path does not exist: %s" % itempath) return [] counter = 0 - with open(prov_playlist_id) as f: + with open(itempath) as f: for line in f.readlines(): line = line.strip() if line and not line.startswith('#'): @@ -210,7 +229,10 @@ class FileProvider(MusicProvider): async def get_artist_albums(self, prov_artist_id) -> List[Album]: ''' get a list of albums for the given artist ''' result = [] - artistpath = prov_artist_id + if not os.sep in prov_artist_id: + artistpath = base64.b64decode(prov_artist_id).decode('utf-8') + else: + artistpath = prov_artist_id if not os.path.isdir(artistpath): LOGGER.error("artist path does not exist: %s" % artistpath) return [] @@ -231,10 +253,14 @@ class FileProvider(MusicProvider): async def get_stream_content_type(self, track_id): ''' return the content type for the given track when it will be streamed''' + if not os.sep in track_id: + track_id = base64.b64decode(track_id).decode('utf-8') return track_id.split('.')[-1] - async def get_stream(self, track_id): + async def get_audio_stream(self, track_id): ''' get audio stream for a track ''' + if not os.sep in track_id: + track_id = base64.b64decode(track_id).decode('utf-8') with open(track_id) as f: while True: line = f.readline() @@ -250,15 +276,13 @@ class FileProvider(MusicProvider): song = taglib.File(filename) except: return None # not a media file ? + prov_item_id = base64.b64encode(filename.encode('utf-8')).decode('utf-8') track.duration = song.length - track.item_id = filename + track.item_id = prov_item_id track.provider = self.prov_id name = song.tags['TITLE'][0] track.name, track.version = parse_track_title(name) - if "\\" in filename: - albumpath = filename.rsplit("\\",1)[0] - else: - albumpath = filename.rsplit("/",1)[0] + albumpath = filename.rsplit(os.sep,1)[0] track.album = await self.get_album(albumpath) artists = [] for artist_str in song.tags['ARTIST']: @@ -272,7 +296,7 @@ class FileProvider(MusicProvider): artist.item_id = fake_artistpath # temporary id artist.provider_ids.append({ "provider": self.prov_id, - "item_id": fake_artistpath + "item_id": base64.b64encode(fake_artistpath.encode('utf-8')).decode('utf-8') }) artists.append(artist) track.artists = artists @@ -306,7 +330,7 @@ class FileProvider(MusicProvider): quality_details = "%s kbps" % (song.bitrate) track.provider_ids.append({ "provider": self.prov_id, - "item_id": filename, + "item_id": prov_item_id, "quality": quality, "details": quality_details }) diff --git a/music_assistant/modules/player.py b/music_assistant/modules/player.py index 31a55697..1ec7739a 100755 --- a/music_assistant/modules/player.py +++ b/music_assistant/modules/player.py @@ -161,6 +161,24 @@ class Player(): player.volume_level = new_volume return True + async def __check_player_group_power(self, player_details, player_childs): + ''' handle group power ''' + childs_powered = False + for child_player in player_childs: + if child_player.powered: + childs_powered = True + break + if player_details.powered and not childs_powered: + # all childs turned off so turn off group player + LOGGER.info('all childs turned off so turn off group player %s' % player_details.name) + await self.player_command(player_details.player_id, 'power', 'off') + player_details.powered = False + elif not player_details.powered and childs_powered: + # all childs turned off but group player still off, so turn it on + LOGGER.info('child(s) turned on but group player still off, so turn it on %s' % player_details.name) + await self.player_command(player_details.player_id, 'power', 'on') + player_details.powered = True + async def remove_player(self, player_id): ''' handle a player remove ''' self._players.pop(player_id, None) @@ -207,7 +225,7 @@ class Player(): if player_details.is_group and player.settings['apply_group_volume']: await self.__update_player_group_volume(player_details, player_childs) if player_details.is_group and player.settings['apply_group_power']: - await self.__update_player_group_power(player_details, player_childs) + await self.__check_player_group_power(player_details, player_childs) # compare values to detect changes if player.cur_item and player_details.cur_item and player.cur_item.name != player_details.cur_item.name: player_changed = True @@ -265,24 +283,6 @@ class Player(): group_volume = group_volume / active_players if active_players else 0 player_details.volume_level = group_volume - async def __update_player_group_power(self, player_details, player_childs): - ''' handle group power ''' - player_powered = False - for child_player in player_childs: - if child_player.powered: - player_powered = True - break - if player_details.powered and not player_powered: - # all childs turned off so turn off group player - LOGGER.info('all childs turned off so turn off group player %s' % player_details.name) - await self. player_command(player_details.player_id, 'power', 'off') - player_details.powered = False - elif not player_details.powered and player_powered: - # all childs turned off but group player still off, so turn it on - LOGGER.info('all childs turned off but group player still off, so turn it on %s' % player_details.name) - await self. player_command(player_details.player_id, 'power', 'on') - player_details.powered = True - async def __get_player_settings(self, player_id): ''' get (or create) player config ''' player_settings = self.mass.config['player_settings'].get(player_id,{}) @@ -415,7 +415,7 @@ class Player(): cmd = '%s %s --xml --ebu -f %s' % (bs1770_binary, tmpfile, analysis_file) process = await asyncio.create_subprocess_shell(cmd) await process.wait() - if self.mass.config['base']['http_streamer']['enable_cache']: + if self.mass.config['base']['http_streamer']['enable_cache'] and not os.path.isfile(cachefile): # use sox to store cache file (optionally strip silence from start and end) if self.mass.config['base']['http_streamer']['trim_silence']: cmd = 'sox -t %s %s -t flac -C5 %s silence 1 0.1 1%% reverse silence 1 0.1 1%% reverse' %(content_type, tmpfile, cachefile) diff --git a/music_assistant/modules/playerproviders/chromecast.py b/music_assistant/modules/playerproviders/chromecast.py index e3602ac7..b0568d5a 100644 --- a/music_assistant/modules/playerproviders/chromecast.py +++ b/music_assistant/modules/playerproviders/chromecast.py @@ -74,10 +74,11 @@ class ChromecastProvider(PlayerProvider): self._chromecasts[player_id].media_controller.queue_prev() elif cmd == 'power' and cmd_args == 'off': self._players[player_id].powered = False - self._chromecasts[player_id].quit_app() # power is not supported so send quit app instead + self.mass.event_loop.create_task(self.mass.player.trigger_update(player_id)) + self._chromecasts[player_id].media_controller.stop() # power is not supported so send stop instead elif cmd == 'power': self._players[player_id].powered = True - self._chromecasts[player_id].media_controller.launch() + self.mass.event_loop.create_task(self.mass.player.trigger_update(player_id)) elif cmd == 'volume': self._chromecasts[player_id].set_volume(try_parse_int(cmd_args)/100) elif cmd == 'mute' and cmd_args == 'off': @@ -286,8 +287,8 @@ class ChromecastProvider(PlayerProvider): track = await self.mass.music.providers['qobuz'].track(track_id) elif uri.startswith('http') and '/stream' in uri: params = urllib.parse.parse_qs(uri.split('?')[1]) - track_id = params['track_id'] - provider = params['provider'] + track_id = params['track_id'][0] + provider = params['provider'][0] track = await self.mass.music.providers[provider].track(track_id) return track diff --git a/music_assistant/modules/playerproviders/lms.py b/music_assistant/modules/playerproviders/lms.py index 2b2200b0..47ff77e8 100644 --- a/music_assistant/modules/playerproviders/lms.py +++ b/music_assistant/modules/playerproviders/lms.py @@ -219,8 +219,8 @@ class LMSProvider(PlayerProvider): LOGGER.error(exc) elif track_url.startswith('http') and '/stream' in track_url: params = urllib.parse.parse_qs(track_url.split('?')[1]) - track_id = params['track_id'] - provider = params['provider'] + track_id = params['track_id'][0] + provider = params['provider'][0] return await self.mass.music.providers[provider].track(track_id) # fallback to a generic track track = Track()