SubmarinerApp / Submariner

A Subsonic client for macOS
https://submarinerapp.com
BSD 3-Clause "New" or "Revised" License
123 stars 3 forks source link

AirPlay album art won't show on device #95

Closed NattyNarwhal closed 20 hours ago

NattyNarwhal commented 1 year ago

I don't see any album art, be it if the Mac's entire audio output is set to an AirPlay device, or if it's just the app. App-specific:

IMG_8533

I see this in the logs:

2023-01-29 14:00:37.889346-0400 Submariner[42682:9794531] [Entitlements] MSVEntitlementUtilities - Process Submariner PID[42682] - Group: (null) - Entitlement: com.apple.mediaremote.external-artwork-validation - Entitled: NO - Error: (null)

This entitlement doesn't seem documented. Is this something Apple hands out?

NattyNarwhal commented 1 year ago

The only reference I could find to this entitlement in something tangible is this WebKit commit, but it seems to be a private entitlement. LaunchServices is very angry if you try to use it.

NattyNarwhal commented 1 year ago

I also don't think it's artwork size? Every one else just never bothers resizing the image from the callback on MPMediaItemArtwork. I never see it request anything other than the size we gave it just once.

If it did fix it, a patch:

diff --git a/Submariner/NSImage+Additions.h b/Submariner/NSImage+Additions.h
index dadd14d..e78110f 100644
--- a/Submariner/NSImage+Additions.h
+++ b/Submariner/NSImage+Additions.h
@@ -36,6 +36,7 @@

 @interface NSImage (Additions)

+- (NSImage *)resizedImageToPixelDimensions:(NSSize)newSize;
 - (NSImage *)imageTintedWithColor:(NSColor *)tint;

 @end
diff --git a/Submariner/NSImage+Additions.m b/Submariner/NSImage+Additions.m
index eb86c45..efb4203 100644
--- a/Submariner/NSImage+Additions.m
+++ b/Submariner/NSImage+Additions.m
@@ -38,6 +38,34 @@

 @implementation NSImage (Additions)

+// https://stackoverflow.com/a/38442746 but adapted as category
+- (NSImage *)resizedImageToPixelDimensions:(NSSize)newSize
+{
+    if (! self.isValid) return nil;
+
+    NSBitmapImageRep *rep = [[NSBitmapImageRep alloc]
+              initWithBitmapDataPlanes:NULL
+                            pixelsWide:newSize.width
+                            pixelsHigh:newSize.height
+                         bitsPerSample:8
+                       samplesPerPixel:4
+                              hasAlpha:YES
+                              isPlanar:NO
+                        colorSpaceName:NSCalibratedRGBColorSpace
+                           bytesPerRow:0
+                          bitsPerPixel:0];
+    rep.size = newSize;
+
+    [NSGraphicsContext saveGraphicsState];
+    [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:rep]];
+    [self drawInRect:NSMakeRect(0, 0, newSize.width, newSize.height) fromRect:NSZeroRect operation:NSCompositingOperationCopy fraction:1.0];
+    [NSGraphicsContext restoreGraphicsState];
+
+    NSImage *newImage = [[NSImage alloc] initWithSize:newSize];
+    [newImage addRepresentation:rep];
+    return newImage;
+}
+
 - (NSImage *)imageTintedWithColor:(NSColor *)tint 
 {
     NSSize size = [self size];
diff --git a/Submariner/SBPlayer.m b/Submariner/SBPlayer.m
index 8bf6d8e..54bb0c2 100644
--- a/Submariner/SBPlayer.m
+++ b/Submariner/SBPlayer.m
@@ -51,6 +51,7 @@
 #import "NSManagedObjectContext+Fetch.h"
 #import "NSOperationQueue+Shared.h"
 #import "NSString+Time.h"
+#import "NSImage+Additions.h"

 #import <MediaPlayer/MPNowPlayingInfoCenter.h>
 #import <MediaPlayer/MPMediaItem.h>
@@ -264,14 +265,14 @@ -(void) updateSystemNowPlayingMetadata {
         } else {
             [self updateSystemNowPlayingMetadataMusic: currentTrack];
         }
-        if (@available(macOS 10.13.2, *)) {
-            NSImage *artwork = [currentTrack coverImage];
-            CGSize artworkSize = [artwork size];
-            MPMediaItemArtwork *mpArtwork = [[MPMediaItemArtwork alloc] initWithBoundsSize:artworkSize requestHandler:^NSImage * _Nonnull(CGSize size) {
-                return artwork;
-            }];
-            [songInfo setObject: mpArtwork forKey:MPMediaItemPropertyArtwork];
-        }
+        NSImage *artwork = [currentTrack coverImage];
+        CGSize artworkSize = [artwork size];
+        MPMediaItemArtwork *mpArtwork = [[MPMediaItemArtwork alloc] initWithBoundsSize:artworkSize requestHandler:^NSImage * _Nonnull(CGSize size) {
+            NSLog(@"Requesing artwork of size %@", NSStringFromSize(size));
+            NSLog(@"Versus image size of %@", NSStringFromSize([artwork size]));
+            return [artwork resizedImageToPixelDimensions: size];
+        }];
+        [songInfo setObject: mpArtwork forKey:MPMediaItemPropertyArtwork];
     } else {
         [songInfo removeObjectForKey: MPMediaItemPropertyMediaType];
         [songInfo removeObjectForKey: MPMediaItemPropertyTitle];
NattyNarwhal commented 20 hours ago

I think it might be an issue with the Roku AirPlay implementation, tested an Apple TV running latest tvOS and it seems fine.

Closing this for now.

IMG_2838