diff --git a/Audio/AudioContainer.h b/Audio/AudioContainer.h index 0b92da666..f8aa73685 100644 --- a/Audio/AudioContainer.h +++ b/Audio/AudioContainer.h @@ -13,5 +13,6 @@ } + (NSArray *)urlsForContainerURL:(NSURL *)url; ++ (NSArray *)dependencyUrlsForContainerURL:(NSURL *)url; @end diff --git a/Audio/AudioContainer.m b/Audio/AudioContainer.m index 4390d936b..06204791d 100644 --- a/Audio/AudioContainer.m +++ b/Audio/AudioContainer.m @@ -18,4 +18,10 @@ } } ++ (NSArray *)dependencyUrlsForContainerURL:(NSURL *)url { + @autoreleasepool { + return [[PluginController sharedPluginController] dependencyUrlsForContainerURL:url]; + } +} + @end diff --git a/Audio/CogPluginMulti.h b/Audio/CogPluginMulti.h index 0fed368e4..00671ed0a 100644 --- a/Audio/CogPluginMulti.h +++ b/Audio/CogPluginMulti.h @@ -23,6 +23,7 @@ } + (NSArray *)urlsForContainerURL:(NSURL *)url containers:(NSArray *)containers; ++ (NSArray *)dependencyUrlsForContainerURL:(NSURL *)url containers:(NSArray *)containers; @end diff --git a/Audio/CogPluginMulti.m b/Audio/CogPluginMulti.m index 6bd90251d..66f2bdffb 100644 --- a/Audio/CogPluginMulti.m +++ b/Audio/CogPluginMulti.m @@ -171,6 +171,19 @@ static void *kCogDecoderMultiContext = &kCogDecoderMultiContext; return nil; } ++ (NSArray *)dependencyUrlsForContainerURL:(NSURL *)url containers:(NSArray *)containers { + NSArray *sortedContainers = sortClassesByPriority(containers); + for(NSString *classString in sortedContainers) { + Class container = NSClassFromString(classString); + if([container respondsToSelector:@selector(dependencyUrlsForContainerURL:)]) { + NSArray *urls = [container dependencyUrlsForContainerURL:url]; + if([urls count]) + return urls; + } + } + return nil; +} + @end @implementation CogMetadataReaderMulti diff --git a/Audio/Plugin.h b/Audio/Plugin.h index 3c6119520..e3db69361 100644 --- a/Audio/Plugin.h +++ b/Audio/Plugin.h @@ -25,6 +25,9 @@ + (float)priority; + (NSArray *)urlsForContainerURL:(NSURL *)url; + +@optional ++ (NSArray *)dependencyUrlsForContainerURL:(NSURL *)url; @end @protocol CogDecoder @@ -93,6 +96,7 @@ - (id)audioSourceForURL:(NSURL *)url; - (NSArray *)urlsForContainerURL:(NSURL *)url; +- (NSArray *)dependencyUrlsForContainerURL:(NSURL *)url; - (NSDictionary *)metadataForURL:(NSURL *)url skipCue:(BOOL)skip; - (NSDictionary *)propertiesForURL:(NSURL *)url skipCue:(BOOL)skip; - (id)audioDecoderForSource:(id)source skipCue:(BOOL)skip; diff --git a/Audio/PluginController.mm b/Audio/PluginController.mm index 799f518b7..bc4207e28 100644 --- a/Audio/PluginController.mm +++ b/Audio/PluginController.mm @@ -567,6 +567,29 @@ static NSString *xmlEscapeString(NSString * string) { return [container urlsForContainerURL:url]; } +- (NSArray *)dependencyUrlsForContainerURL:(NSURL *)url { + NSString *ext = [url pathExtension]; + NSArray *containerSet = [containers objectForKey:[ext lowercaseString]]; + NSString *classString; + if(containerSet) { + if([containerSet count] > 1) { + return [CogContainerMulti dependencyUrlsForContainerURL:url containers:containerSet]; + } else { + classString = [containerSet objectAtIndex:0]; + } + } else { + return nil; + } + + Class container = NSClassFromString(classString); + + if([container respondsToSelector:@selector(dependencyUrlsForContainerURL:)]) { + return [container dependencyUrlsForContainerURL:url]; + } else { + return nil; + } +} + // Note: Source is assumed to already be opened. - (id)audioDecoderForSource:(id)source skipCue:(BOOL)skip { NSString *ext = [[source url] pathExtension]; diff --git a/Plugins/CueSheet/CueSheetContainer.m b/Plugins/CueSheet/CueSheetContainer.m index 1fd287394..7f8b5a4e1 100644 --- a/Plugins/CueSheet/CueSheetContainer.m +++ b/Plugins/CueSheet/CueSheetContainer.m @@ -70,4 +70,44 @@ return tracks; } ++ (NSArray *)dependencyUrlsForContainerURL:(NSURL *)url { + if(![url isFileURL]) { + return @[]; + } + + if([url fragment]) { + NSString *pathString = [url path]; + NSString *lastComponent = [url lastPathComponent]; + + // Find that last component in the string from the end to make sure + // to get the last one + NSRange fragmentRange = [pathString rangeOfString:lastComponent options:NSBackwardsSearch]; + + // Chop the fragment. + NSString *newPathString = [pathString substringToIndex:fragmentRange.location + fragmentRange.length]; + + url = [NSURL fileURLWithPath:newPathString]; + } + + NSMutableArray *tracks = [NSMutableArray array]; + + CueSheet *cuesheet = nil; + + NSString *ext = [url pathExtension]; + if([ext caseInsensitiveCompare:@"cue"] != NSOrderedSame) { + return @[]; + } else + cuesheet = [CueSheet cueSheetWithFile:[url path]]; + + if(!cuesheet) + return @[]; + + for(CueSheetTrack *track in [cuesheet tracks]) { + if(![tracks containsObject:track.url]) + [tracks addObject:track.url]; + } + + return tracks; +} + @end diff --git a/Preferences/Preferences/PathSuggester.m b/Preferences/Preferences/PathSuggester.m index fe0223243..1391c4066 100644 --- a/Preferences/Preferences/PathSuggester.m +++ b/Preferences/Preferences/PathSuggester.m @@ -11,6 +11,8 @@ #import "SandboxBroker.h" +#import "AudioContainer.h" + // Sync, only declare items we need @interface PlaylistEntry @property(nonatomic) NSURL *_Nullable url; @@ -95,7 +97,15 @@ static NSURL *defaultMoviesDirectory(void) { NSMutableArray *items = [[NSMutableArray alloc] init]; NSMutableArray *itemPaths = [[NSMutableArray alloc] init]; - NSMutableArray *array = [[results valueForKey:@"url"] mutableCopy]; + NSArray *originalArray = [results valueForKey:@"url"]; + NSMutableArray *array = [originalArray mutableCopy]; + + for(NSURL *url in originalArray) { + NSArray *containedUrls = [AudioContainer dependencyUrlsForContainerURL:url]; + if(containedUrls && [containedUrls count] > 0) { + [array addObjectsFromArray:containedUrls]; + } + } // Add other system paths to this setting NSString *fileTreePath = [[NSUserDefaults standardUserDefaults] stringForKey:@"fileTreeRootURL"]; diff --git a/Preferences/Preferences/Preferences.xcodeproj/project.pbxproj b/Preferences/Preferences/Preferences.xcodeproj/project.pbxproj index cc920f0b2..0687baf01 100644 --- a/Preferences/Preferences/Preferences.xcodeproj/project.pbxproj +++ b/Preferences/Preferences/Preferences.xcodeproj/project.pbxproj @@ -102,6 +102,7 @@ 8307D31328606EAF000FF8EB /* growl@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "growl@2x.png"; path = "Icons/growl@2x.png"; sourceTree = ""; }; 8307D31428606EAF000FF8EB /* general.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = general.png; path = Icons/general.png; sourceTree = ""; }; 8307D31528606EAF000FF8EB /* growl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = growl.png; path = Icons/growl.png; sourceTree = ""; }; + 832FAE812868566F008B48B3 /* AudioContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioContainer.h; path = ../../Audio/AudioContainer.h; sourceTree = ""; }; 833F681B1CDBCAA700AFB9F0 /* es */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = ""; }; 833F681C1CDBCAA700AFB9F0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; 8347435D20E6D58800063D45 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Preferences.strings; sourceTree = ""; }; @@ -203,6 +204,7 @@ 08FB77AFFE84173DC02AAC07 /* Classes */ = { isa = PBXGroup; children = ( + 832FAE812868566F008B48B3 /* AudioContainer.h */, 839E3B5728659B2700880EA2 /* AppController.h */, 83AC573E2861B77E009D6F50 /* SandboxBroker.h */, 8307D30828604ECF000FF8EB /* PlaylistController.h */,