Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 24 additions & 16 deletions scrobble.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
A622991D2EE7D72900592239 /* ServicesStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A622991C2EE7D72900592239 /* ServicesStatusView.swift */; };
A62299202EE80F2C00592239 /* LabeledStepper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A622991F2EE80F2C00592239 /* LabeledStepper.swift */; };
A63A2B192D2717A1000BC92E /* FriendsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A63A2B182D2717A1000BC92E /* FriendsView.swift */; };
A6FFILTER0002 /* FriendsFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6FFILTER0001 /* FriendsFilterView.swift */; };
A63A2B1B2D271A95000BC92E /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A63A2B1A2D271A95000BC92E /* ContentView.swift */; };
A64304B92D52EBAE001998B6 /* LastFmManagerDesktop.swift in Sources */ = {isa = PBXBuildFile; fileRef = A64304B82D52EBAE001998B6 /* LastFmManagerDesktop.swift */; };
A64304BB2D52EC87001998B6 /* LastFMAuthSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A64304BA2D52EC87001998B6 /* LastFMAuthSheetView.swift */; };
Expand All @@ -30,6 +29,8 @@
A6A580A82E78DB7F0079DC91 /* MediaRemoteAdapter in Frameworks */ = {isa = PBXBuildFile; productRef = A6A580A72E78DB7F0079DC91 /* MediaRemoteAdapter */; };
A6A580A92E78DB9F0079DC91 /* MediaRemoteAdapter in Embed Frameworks */ = {isa = PBXBuildFile; productRef = A6A580A72E78DB7F0079DC91 /* MediaRemoteAdapter */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
A6CC84552EE8470C00236D47 /* MarqueeText.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6CC84542EE8470C00236D47 /* MarqueeText.swift */; };
A6CLEANER0002 /* TrackMetadataCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6CLEANER0001 /* TrackMetadataCleaner.swift */; };
A6CLEANER0004 /* TrackMetadataCleanerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6CLEANER0003 /* TrackMetadataCleanerTests.swift */; };
A6COMPAT012EFBAA0000001 /* GlassEffect+Compat.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6COMPAT012EFBAA0000002 /* GlassEffect+Compat.swift */; };
A6COMPAT012EFBAA0000003 /* LastFMWebAuthViewLegacy.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6COMPAT012EFBAA0000004 /* LastFMWebAuthViewLegacy.swift */; };
A6DESIGN012EFBAA0000001 /* DesignTokens.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6DESIGN012EFBAA0000002 /* DesignTokens.swift */; };
Expand All @@ -47,6 +48,7 @@
A6F2FEEF2EE79E47003826F7 /* Secrets.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = A6F2FEED2EE79E47003826F7 /* Secrets.xcconfig */; };
A6F2FEF22EE7A429003826F7 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6F2FEF12EE7A429003826F7 /* Logger.swift */; };
A6F954FC2EED236000501378 /* LaunchAtLoginSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6F954FB2EED236000501378 /* LaunchAtLoginSettingsView.swift */; };
A6FFILTER0002 /* FriendsFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6FFILTER0001 /* FriendsFilterView.swift */; };
A6HIG00001 /* AppSelectionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6HIG00002 /* AppSelectionButton.swift */; };
A6HIG00003 /* FeatureRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6HIG00004 /* FeatureRow.swift */; };
A6HIG00005 /* ServiceRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6HIG00006 /* ServiceRow.swift */; };
Expand Down Expand Up @@ -107,7 +109,6 @@
A622991C2EE7D72900592239 /* ServicesStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServicesStatusView.swift; sourceTree = "<group>"; };
A622991F2EE80F2C00592239 /* LabeledStepper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabeledStepper.swift; sourceTree = "<group>"; };
A63A2B182D2717A1000BC92E /* FriendsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendsView.swift; sourceTree = "<group>"; };
A6FFILTER0001 /* FriendsFilterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendsFilterView.swift; sourceTree = "<group>"; };
A63A2B1A2D271A95000BC92E /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
A64304B82D52EBAE001998B6 /* LastFmManagerDesktop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LastFmManagerDesktop.swift; sourceTree = "<group>"; tabWidth = 3; };
A64304BA2D52EC87001998B6 /* LastFMAuthSheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LastFMAuthSheetView.swift; sourceTree = "<group>"; };
Expand All @@ -123,6 +124,8 @@
A6A580A22E78D8480079DC91 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; };
A6A580A42E78D9340079DC91 /* NowPlayingFetcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingFetcher.swift; sourceTree = "<group>"; };
A6CC84542EE8470C00236D47 /* MarqueeText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarqueeText.swift; sourceTree = "<group>"; };
A6CLEANER0001 /* TrackMetadataCleaner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackMetadataCleaner.swift; sourceTree = "<group>"; };
A6CLEANER0003 /* TrackMetadataCleanerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackMetadataCleanerTests.swift; sourceTree = "<group>"; };
A6COMPAT012EFBAA0000002 /* GlassEffect+Compat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GlassEffect+Compat.swift"; sourceTree = "<group>"; };
A6COMPAT012EFBAA0000004 /* LastFMWebAuthViewLegacy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LastFMWebAuthViewLegacy.swift; sourceTree = "<group>"; };
A6DESIGN012EFBAA0000002 /* DesignTokens.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DesignTokens.swift; sourceTree = "<group>"; };
Expand All @@ -143,6 +146,7 @@
A6F2FEED2EE79E47003826F7 /* Secrets.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Secrets.xcconfig; sourceTree = "<group>"; };
A6F2FEF12EE7A429003826F7 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
A6F954FB2EED236000501378 /* LaunchAtLoginSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchAtLoginSettingsView.swift; sourceTree = "<group>"; };
A6FFILTER0001 /* FriendsFilterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendsFilterView.swift; sourceTree = "<group>"; };
A6HIG00002 /* AppSelectionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSelectionButton.swift; sourceTree = "<group>"; };
A6HIG00004 /* FeatureRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureRow.swift; sourceTree = "<group>"; };
A6HIG00006 /* ServiceRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceRow.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -193,18 +197,6 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
A6SERVICES0001 /* Services */ = {
isa = PBXGroup;
children = (
A6F2130E2C8C027C00E1D23B /* Scrobbler.swift */,
A61F9BCE2E85E04A00CC1661 /* ScrobblingService.swift */,
A6F213122C8C038F00E1D23B /* LastFmManager.swift */,
A64304B82D52EBAE001998B6 /* LastFmManagerDesktop.swift */,
A6A580A42E78D9340079DC91 /* NowPlayingFetcher.swift */,
);
path = Services;
sourceTree = "<group>";
};
A622991E2EE80F1600592239 /* View Components */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -349,6 +341,19 @@
path = Onboarding;
sourceTree = "<group>";
};
A6SERVICES0001 /* Services */ = {
isa = PBXGroup;
children = (
A6F2130E2C8C027C00E1D23B /* Scrobbler.swift */,
A6CLEANER0001 /* TrackMetadataCleaner.swift */,
A61F9BCE2E85E04A00CC1661 /* ScrobblingService.swift */,
A6F213122C8C038F00E1D23B /* LastFmManager.swift */,
A64304B82D52EBAE001998B6 /* LastFmManagerDesktop.swift */,
A6A580A42E78D9340079DC91 /* NowPlayingFetcher.swift */,
);
path = Services;
sourceTree = "<group>";
};
A6TESTGR0001 /* scrobbleTests */ = {
isa = PBXGroup;
children = (
Expand All @@ -359,6 +364,7 @@
A6TESTFR0005 /* DesignTokensTests.swift */,
A6TESTFR0006 /* ScrobbleDelayTests.swift */,
A6TESTFR0007 /* UpdateStateTests.swift */,
A6CLEANER0003 /* TrackMetadataCleanerTests.swift */,
A6TESTFR0008 /* CodableTests.swift */,
A6TESTFR0009 /* CryptoUtilsTests.swift */,
);
Expand Down Expand Up @@ -503,6 +509,7 @@
A6KEYCHAIN01 /* KeychainHelper.swift in Sources */,
A6F213112C8C037500E1D23B /* PreferencesView.swift in Sources */,
A6F2130F2C8C027C00E1D23B /* Scrobbler.swift in Sources */,
A6CLEANER0002 /* TrackMetadataCleaner.swift in Sources */,
A622991B2EE7D69100592239 /* MenuButtonsView.swift in Sources */,
A61F9BCF2E85E04A00CC1661 /* ScrobblingService.swift in Sources */,
A6F213002C8C021800E1D23B /* scrobbleApp.swift in Sources */,
Expand All @@ -527,6 +534,7 @@
A6TESTBF0005 /* DesignTokensTests.swift in Sources */,
A6TESTBF0006 /* ScrobbleDelayTests.swift in Sources */,
A6TESTBF0007 /* UpdateStateTests.swift in Sources */,
A6CLEANER0004 /* TrackMetadataCleanerTests.swift in Sources */,
A6TESTBF0008 /* CodableTests.swift in Sources */,
A6TESTBF0009 /* CryptoUtilsTests.swift in Sources */,
);
Expand Down Expand Up @@ -679,7 +687,7 @@
CODE_SIGN_ENTITLEMENTS = scrobble/scrobble.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 10;
CURRENT_PROJECT_VERSION = 11;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"scrobble/Preview Content\"";
ENABLE_APP_SANDBOX = NO;
Expand Down Expand Up @@ -729,7 +737,7 @@
CODE_SIGN_ENTITLEMENTS = scrobble/scrobble.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 10;
CURRENT_PROJECT_VERSION = 11;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"scrobble/Preview Content\"";
ENABLE_APP_SANDBOX = NO;
Expand Down
7 changes: 5 additions & 2 deletions scrobble/Services/NowPlayingFetcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ final class NowPlayingFetcher {
var currentTrackArtist: String = ""
var currentTrackAlbum: String = ""
var currentApplication: String = ""
var currentBundleIdentifier: String? = nil
var currentArtwork: NSImage? = nil
var currentArtworkBase64: String? = nil
var isPlaying: Bool = false
Expand Down Expand Up @@ -68,6 +69,7 @@ final class NowPlayingFetcher {
self.currentTrackArtist = trackInfo.payload.artist ?? ""
self.currentTrackAlbum = trackInfo.payload.album ?? ""
self.currentApplication = trackInfo.payload.applicationName ?? ""
self.currentBundleIdentifier = trackInfo.payload.bundleIdentifier
self.currentArtwork = trackInfo.payload.artwork
self.currentArtworkBase64 = trackInfo.payload.artworkDataBase64
self.isPlaying = trackInfo.payload.isPlaying ?? false
Expand Down Expand Up @@ -105,6 +107,7 @@ final class NowPlayingFetcher {
currentTrackArtist = ""
currentTrackAlbum = ""
currentApplication = ""
currentBundleIdentifier = nil
currentArtwork = nil
currentArtworkBase64 = nil
isPlaying = false
Expand Down Expand Up @@ -154,8 +157,8 @@ final class NowPlayingFetcher {
Log.debug("Forcing UI update with current state", category: .scrobble)
}

func fetchCurrentTrackInfo() -> (isPlaying: Bool, title: String, artist: String, album: String, duration: TimeInterval, application: String, artwork: NSImage?, artworkBase64: String?) {
return (isPlaying: isPlaying, title: currentTrackTitle, artist: currentTrackArtist, album: currentTrackAlbum, duration: currentTrackDuration, application: currentApplication, artwork: currentArtwork, artworkBase64: currentArtworkBase64)
func fetchCurrentTrackInfo() -> (isPlaying: Bool, title: String, artist: String, album: String, duration: TimeInterval, application: String, bundleIdentifier: String?, artwork: NSImage?, artworkBase64: String?) {
return (isPlaying: isPlaying, title: currentTrackTitle, artist: currentTrackArtist, album: currentTrackAlbum, duration: currentTrackDuration, application: currentApplication, bundleIdentifier: currentBundleIdentifier, artwork: currentArtwork, artworkBase64: currentArtworkBase64)
}

func fetchCurrentArtwork() -> NSImage? {
Expand Down
19 changes: 14 additions & 5 deletions scrobble/Services/Scrobbler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,16 @@ class Scrobbler {
// unreadable within minutes.
private func checkNowPlaying() async {
if let trackInfo = getCurrentTrackInfoViaFetcher() {
let trackString = "\(trackInfo.artist) - \(trackInfo.name)"
// Web sources (browsers) relay whatever the page put in the Media
// Session API — clean known junk before anything downstream sees it.
let track = TrackMetadataCleaner.cleanIfWebSource(
title: trackInfo.name,
artist: trackInfo.artist,
album: trackInfo.album,
bundleIdentifier: trackInfo.bundleIdentifier,
applicationName: trackInfo.application
)
let trackString = "\(track.artist) - \(track.title)"

// Music is playing - prevent App Nap
beginBackgroundActivity()
Expand All @@ -322,9 +331,9 @@ class Scrobbler {
hasScrobbledCurrentSession = false

// Update Now Playing (Async)
await updateNowPlaying(artist: trackInfo.artist, title: trackInfo.name, album: trackInfo.album)
await updateNowPlaying(artist: track.artist, title: track.title, album: track.album)

setupScrobbleTimer(artist: trackInfo.artist, title: trackInfo.name, album: trackInfo.album)
setupScrobbleTimer(artist: track.artist, title: track.title, album: track.album)
}
} else {
if currentTrack != "No track playing" {
Expand All @@ -341,7 +350,7 @@ class Scrobbler {


// Called from the poll loop — must stay silent in the steady state.
private func getCurrentTrackInfoViaFetcher() -> (name: String, artist: String, album: String, duration: TimeInterval?, application: String, artwork: NSImage?)? {
private func getCurrentTrackInfoViaFetcher() -> (name: String, artist: String, album: String, duration: TimeInterval?, application: String, bundleIdentifier: String?, artwork: NSImage?)? {
guard let fetcher = _mediaRemoteFetcher else {
return nil
}
Expand All @@ -351,7 +360,7 @@ class Scrobbler {
guard trackInfo.isPlaying, !trackInfo.title.isEmpty, !trackInfo.artist.isEmpty else {
return nil
}
return (name: trackInfo.title, artist: trackInfo.artist, album: trackInfo.album, duration: trackInfo.duration, application: trackInfo.application, artwork: trackInfo.artwork)
return (name: trackInfo.title, artist: trackInfo.artist, album: trackInfo.album, duration: trackInfo.duration, application: trackInfo.application, bundleIdentifier: trackInfo.bundleIdentifier, artwork: trackInfo.artwork)
}

private func scrobbleTrack(artist: String, title: String, album: String) {
Expand Down
Loading
Loading