Fix for Spotify on Raspberry Pi platforms
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Sun, 24 Apr 2022 12:43:50 +0000 (14:43 +0200)
committerGitHub <noreply@github.com>
Sun, 24 Apr 2022 12:43:50 +0000 (14:43 +0200)
music_assistant/helpers/audio.py
music_assistant/providers/spotify/__init__.py
music_assistant/providers/spotify/spotty/linux/spotty-armv6 [new file with mode: 0755]
music_assistant/providers/spotify/spotty/linux/spotty-muslhf [new file with mode: 0755]

index f80fa1b9bc0169ad8a0aafbe326ddfdc20191a0f..0ffd4929dd0cbdf623a103cef5526f93599d5850 100644 (file)
@@ -320,14 +320,14 @@ async def get_sox_args(
     """Collect all args to send to the sox (or ffmpeg) process."""
     stream_path = streamdetails.path
     stream_type = StreamType(streamdetails.type)
-    content_type = streamdetails.content_type
+    input_format = streamdetails.content_type
     if output_format is None:
-        output_format = streamdetails.content_type
+        output_format = input_format
 
     sox_present, ffmpeg_present = await check_audio_support()
 
     # use ffmpeg if content not supported by SoX (e.g. AAC radio streams)
-    if not sox_present or not streamdetails.content_type.sox_supported():
+    if not sox_present or not input_format.sox_supported():
         if not ffmpeg_present:
             raise AudioError(
                 "FFmpeg binary is missing from system."
@@ -344,7 +344,7 @@ async def get_sox_args(
                 "-loglevel",
                 "error",
                 "-f",
-                content_type.value,
+                input_format.value,
                 "-i",
                 "-",
             ]
@@ -372,7 +372,7 @@ async def get_sox_args(
         filter_args = []
         if streamdetails.gain_correct:
             filter_args += ["-filter:a", f"volume={streamdetails.gain_correct}dB"]
-        if resample:
+        if resample or input_format.is_pcm():
             filter_args += ["-ar", str(resample)]
         return input_args + filter_args + output_args
 
@@ -384,11 +384,18 @@ async def get_sox_args(
             "|",
             "sox",
             "-t",
-            content_type.sox_format(),
-            "-",
+            input_format.sox_format(),
         ]
+        if input_format.is_pcm():
+            input_args += [
+                "-r",
+                str(streamdetails.sample_rate),
+                "-c",
+                str(streamdetails.channels),
+            ]
+        input_args.append("-")
     else:
-        input_args = ["sox", "-t", content_type.sox_format(), stream_path]
+        input_args = ["sox", "-t", input_format.sox_format(), stream_path]
     # collect output args
     if output_format.is_pcm():
         output_args = ["-t", output_format.sox_format(), "-c", "2", "-"]
index c63537a15dd97d1ca8404eaeb8438c5c939f4663..9220f59f9b86888b8695dead871e680e3818523e 100644 (file)
@@ -267,13 +267,13 @@ class SpotifyProvider(MusicProvider):
         # make sure that the token is still valid by just requesting it
         await self.get_token()
         spotty = await self.get_spotty_binary()
-        spotty_exec = f'{spotty} -n temp -c "/tmp" -b 320 --pass-through --single-track spotify://track:{track.item_id}'
+        spotty_exec = f'{spotty} -n temp -c "/tmp" -b 320 --single-track spotify://track:{track.item_id}'
         return StreamDetails(
             type=StreamType.EXECUTABLE,
             item_id=track.item_id,
             provider=self.id,
             path=spotty_exec,
-            content_type=ContentType.OGG,
+            content_type=ContentType.PCM_S16LE,
             sample_rate=44100,
             bit_depth=16,
         )
@@ -577,7 +577,8 @@ class SpotifyProvider(MusicProvider):
         ) as response:
             return await response.text()
 
-    async def get_spotty_binary(self):
+    @staticmethod
+    async def get_spotty_binary():
         """Find the correct spotty binary belonging to the platform."""
         if platform.system() == "Windows":
             return os.path.join(
@@ -599,10 +600,10 @@ class SpotifyProvider(MusicProvider):
                 return os.path.join(
                     os.path.dirname(__file__), "spotty", "linux", "spotty-i386"
                 )
-            if "aarch64" in architecture or "armv8" in architecture:
-                # try arm64 linux binary, fallback to 32 bits
+            # arm architecture... try all options one by one...
+            for arch in ["aarch64", "armhf", "muslhf", "armv6"]:
                 spotty_path = os.path.join(
-                    os.path.dirname(__file__), "spotty", "linux", "spotty-aarch64"
+                    os.path.dirname(__file__), "spotty", "linux", f"spotty-{arch}"
                 )
                 try:
                     spotty = await asyncio.create_subprocess_exec(
@@ -611,13 +612,6 @@ class SpotifyProvider(MusicProvider):
                     stdout, _ = await spotty.communicate()
                     if spotty.returncode == 0 and b"librespot" in stdout:
                         return spotty_path
-                except OSError as err:
-                    self.logger.exception(
-                        "failed to start arm64 spotty binary, fallback to 32 bits",
-                        exc_info=err,
-                    )
-            # assume armv7
-            return os.path.join(
-                os.path.dirname(__file__), "spotty", "linux", "spotty-armhf"
-            )
+                except OSError:
+                    pass
         return None
diff --git a/music_assistant/providers/spotify/spotty/linux/spotty-armv6 b/music_assistant/providers/spotify/spotty/linux/spotty-armv6
new file mode 100755 (executable)
index 0000000..bee2f66
Binary files /dev/null and b/music_assistant/providers/spotify/spotty/linux/spotty-armv6 differ
diff --git a/music_assistant/providers/spotify/spotty/linux/spotty-muslhf b/music_assistant/providers/spotify/spotty/linux/spotty-muslhf
new file mode 100755 (executable)
index 0000000..c172724
Binary files /dev/null and b/music_assistant/providers/spotify/spotty/linux/spotty-muslhf differ