From 497eb4a9205c346c24718ff68684aca47835656e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20L=C3=B3pez=20Brante?= Date: Tue, 6 Oct 2026 08:22:01 -0300 Subject: [PATCH] PlaylistLoader, SQLiteStore: Read stored URLs through +[PlaylistEntry urlForPath:] The C function urlForPath() went with the rest of PlaylistEntry's URL code to CogPlaylist in 2f5135316, but PlaylistLoader and SQLiteStore declared it themselves and still called it. The app links with -undefined dynamic_lookup, so the build passed, and the call failed when it was reached: loading metadata in the background, as adding several files at once does, aborted the app, as would SQLiteStore's import of the old library. The Swift port of it is now visible to Objective-C as +[PlaylistEntry urlForPath:], and both call it. Co-Authored-By: Claude Opus 5.5 (1M context) --- CogPlaylist/Sources/PlaylistEntry+Extension.swift | 4 ++-- CogPlaylist/Tests/PlaylistEntryTests.swift | 9 +++++++++ Playlist/PlaylistLoader.m | 4 +--- Utils/SQLiteStore.m | 4 +--- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/CogPlaylist/Sources/PlaylistEntry+Extension.swift b/CogPlaylist/Sources/PlaylistEntry+Extension.swift index 1fa7bc190..171fb981c 100644 --- a/CogPlaylist/Sources/PlaylistEntry+Extension.swift +++ b/CogPlaylist/Sources/PlaylistEntry+Extension.swift @@ -78,8 +78,8 @@ extension PlaylistEntry { /// A stored URL string, or a path as older playlists kept it, perhaps /// with a cue track fragment ("/a/b.flac#01"); nothing is ten seconds of - /// silence. - static func url(forPath path: String?) -> URL? { + /// silence. The loader reads entries' stored strings with it. + @objc(urlForPath:) public static func url(forPath path: String?) -> URL? { guard let path, !path.isEmpty else { return URL(string: "silence://10") } if path.contains("://") { diff --git a/CogPlaylist/Tests/PlaylistEntryTests.swift b/CogPlaylist/Tests/PlaylistEntryTests.swift index 4e67940b5..4c668272d 100644 --- a/CogPlaylist/Tests/PlaylistEntryTests.swift +++ b/CogPlaylist/Tests/PlaylistEntryTests.swift @@ -41,6 +41,15 @@ final class PlaylistEntryTests: XCTestCase { XCTAssertEqual(makeEntry(url: "/Music/#1 hits.mp3").url?.path, "/Music/#1 hits.mp3") } + /// The loader reads stored strings through it from Objective-C. + func testURLForPathIsAvailableToObjectiveC() { + let selector = NSSelectorFromString("urlForPath:") + XCTAssertTrue(PlaylistEntry.responds(to: selector)) + let url = (PlaylistEntry.self as AnyObject).perform(selector, with: "/Music/a.cue#02")?.takeUnretainedValue() as? URL + XCTAssertEqual(url?.path, "/Music/a.cue") + XCTAssertEqual(url?.fragment, "02") + } + func testNoURLIsSilence() { XCTAssertEqual(makeEntry(url: nil).url?.absoluteString, "silence://10") XCTAssertEqual(makeEntry(url: "").url?.absoluteString, "silence://10") diff --git a/Playlist/PlaylistLoader.m b/Playlist/PlaylistLoader.m index c4ddedd54..729650b5a 100644 --- a/Playlist/PlaylistLoader.m +++ b/Playlist/PlaylistLoader.m @@ -951,8 +951,6 @@ - (NSArray *)insertURLs:(NSArray *)urls atIndex:(NSInteger)index sort:(BOOL)sort } } -NSURL *_Nullable urlForPath(NSString *_Nullable path); - - (void)loadInfoForEntries:(NSArray *)entries { NSMutableDictionary *queueThisJob = [NSMutableDictionary new]; for(PlaylistEntry *pe in entries) { @@ -1046,7 +1044,7 @@ - (void)loadInfoForEntries:(NSArray *)entries { [blockInputs removeObjectAtIndex:0]; [blockLock unlock]; - NSURL *url = urlForPath(key); + NSURL *url = [PlaylistEntry urlForPath:key]; NSString *message = [NSString stringWithFormat:@"Loading metadata for %@", url]; DLog(@"%@", message); diff --git a/Utils/SQLiteStore.m b/Utils/SQLiteStore.m index 89b35dd1e..fff45d8b6 100644 --- a/Utils/SQLiteStore.m +++ b/Utils/SQLiteStore.m @@ -507,8 +507,6 @@ const char *query_count_queue = "SELECT COUNT(*) FROM queue"; -NSURL *_Nonnull urlForPath(NSString *_Nullable path); - @interface SQLiteStore (Private) - (NSString *_Nullable)addString:(id _Nullable)string returnId:(int64_t *_Nonnull)stringId; - (NSString *_Nonnull)getString:(int64_t)stringId; @@ -1510,7 +1508,7 @@ - (PlaylistEntry *_Nonnull)getTrack:(int64_t)trackId { uint64_t discNr = ((uint64_t)trackNr) >> 32; trackNr &= (1UL << 32) - 1; - entry.url = urlForPath([self getString:urlId]); + entry.url = [PlaylistEntry urlForPath:[self getString:urlId]]; entry.album = [self getString:albumId]; entry.albumartist = [self getString:albumartistId];