diff --git a/Application/AppController.m b/Application/AppController.m index 993c54f8c..f7e2801b1 100644 --- a/Application/AppController.m +++ b/Application/AppController.m @@ -4,6 +4,7 @@ #import "PlaylistController.h" #import "PlaylistView.h" #import "FileOutlineView.h" +#import "FileTreeDataSource.h" #import "NDHotKeyEvent.h" #import "AppleRemote.h" #import "PlaylistLoader.h" diff --git a/Cog.xcodeproj/project.pbxproj b/Cog.xcodeproj/project.pbxproj index 325d1e4fb..d58e36613 100644 --- a/Cog.xcodeproj/project.pbxproj +++ b/Cog.xcodeproj/project.pbxproj @@ -72,6 +72,10 @@ 1791FF900CB43A2C0070BC5C /* MediaKeysApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 1791FF8E0CB43A2C0070BC5C /* MediaKeysApplication.m */; }; 179790E10C087AB7001D6996 /* OpenURLPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = 179790DF0C087AB7001D6996 /* OpenURLPanel.m */; }; 179790F20C087B46001D6996 /* OpenURLPanel.nib in Resources */ = {isa = PBXBuildFile; fileRef = 179790F00C087B46001D6996 /* OpenURLPanel.nib */; }; + 17BA9FBE0CC431890015F804 /* ContainerNode.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17BA9FBC0CC431890015F804 /* ContainerNode.h */; }; + 17BA9FBF0CC431890015F804 /* ContainerNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 17BA9FBD0CC431890015F804 /* ContainerNode.m */; }; + 17BA9FC70CC432060015F804 /* ContainedNode.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17BA9FC50CC432060015F804 /* ContainedNode.h */; }; + 17BA9FC80CC432060015F804 /* ContainedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 17BA9FC60CC432060015F804 /* ContainedNode.m */; }; 17BB5CED0B8A86010009ACB1 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BB5CEC0B8A86010009ACB1 /* AudioToolbox.framework */; }; 17BB5CF90B8A86350009ACB1 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BB5CF60B8A86350009ACB1 /* AudioUnit.framework */; }; 17BB5CFA0B8A86350009ACB1 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17BB5CF70B8A86350009ACB1 /* CoreAudio.framework */; }; @@ -418,6 +422,8 @@ 17F94CCD0B8D090800A34E87 /* Sparkle.framework in CopyFiles */, 1791FF8F0CB43A2C0070BC5C /* MediaKeysApplication.h in CopyFiles */, 1769D7D10CC2BFF7003F455B /* FileTreeDataSource.h in CopyFiles */, + 17BA9FBE0CC431890015F804 /* ContainerNode.h in CopyFiles */, + 17BA9FC70CC432060015F804 /* ContainedNode.h in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -533,6 +539,10 @@ 179790DE0C087AB7001D6996 /* OpenURLPanel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = OpenURLPanel.h; sourceTree = ""; }; 179790DF0C087AB7001D6996 /* OpenURLPanel.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = OpenURLPanel.m; sourceTree = ""; }; 179790F10C087B46001D6996 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/OpenURLPanel.nib; sourceTree = ""; }; + 17BA9FBC0CC431890015F804 /* ContainerNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContainerNode.h; sourceTree = ""; }; + 17BA9FBD0CC431890015F804 /* ContainerNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContainerNode.m; sourceTree = ""; }; + 17BA9FC50CC432060015F804 /* ContainedNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContainedNode.h; sourceTree = ""; }; + 17BA9FC60CC432060015F804 /* ContainedNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContainedNode.m; sourceTree = ""; }; 17BB5CEC0B8A86010009ACB1 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = ""; }; 17BB5CF60B8A86350009ACB1 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = /System/Library/Frameworks/AudioUnit.framework; sourceTree = ""; }; 17BB5CF70B8A86350009ACB1 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = ""; }; @@ -1154,6 +1164,10 @@ 8EFFCD530AA093AF00C458A5 /* PathNode.m */, 171678BD0AC8C39E00C28CF3 /* SmartFolderNode.h */, 171678BE0AC8C39E00C28CF3 /* SmartFolderNode.m */, + 17BA9FBC0CC431890015F804 /* ContainerNode.h */, + 17BA9FBD0CC431890015F804 /* ContainerNode.m */, + 17BA9FC50CC432060015F804 /* ContainedNode.h */, + 17BA9FC60CC432060015F804 /* ContainedNode.m */, ); path = FileDrawer; sourceTree = ""; @@ -1529,6 +1543,8 @@ 179790E10C087AB7001D6996 /* OpenURLPanel.m in Sources */, 1791FF900CB43A2C0070BC5C /* MediaKeysApplication.m in Sources */, 1769D7D20CC2BFF7003F455B /* FileTreeDataSource.m in Sources */, + 17BA9FBF0CC431890015F804 /* ContainerNode.m in Sources */, + 17BA9FC80CC432060015F804 /* ContainedNode.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/FileDrawer/ContainedNode.h b/FileDrawer/ContainedNode.h new file mode 100644 index 000000000..482e10bd9 --- /dev/null +++ b/FileDrawer/ContainedNode.h @@ -0,0 +1,18 @@ +// +// ContainedNode.h +// Cog +// +// Created by Vincent Spader on 10/15/07. +// Copyright 2007 __MyCompanyName__. All rights reserved. +// + +#import + +#import "PathNode.h" + +@interface ContainedNode : PathNode { + + +} + +@end diff --git a/FileDrawer/ContainedNode.m b/FileDrawer/ContainedNode.m new file mode 100644 index 000000000..582ef87fa --- /dev/null +++ b/FileDrawer/ContainedNode.m @@ -0,0 +1,41 @@ +// +// ContainedNode.m +// Cog +// +// Created by Vincent Spader on 10/15/07. +// Copyright 2007 __MyCompanyName__. All rights reserved. +// + +#import "ContainedNode.h" + + +@implementation ContainedNode + +- (BOOL)isLeaf +{ + return YES; +} + +- (void)setURL:(NSURL *)u +{ + [super setURL:u]; + + if ([u fragment]) + { + [display release]; + display = [[u fragment] retain]; + } +} + +//Disable watching for us, it doesn't matter. +- (void)startWatching +{ +} +- (void)stopWatching +{ +} +- (void)updatePathNotification:(NSNotification *)notification +{ +} + +@end diff --git a/FileDrawer/ContainerNode.h b/FileDrawer/ContainerNode.h new file mode 100644 index 000000000..cc160a729 --- /dev/null +++ b/FileDrawer/ContainerNode.h @@ -0,0 +1,17 @@ +// +// ContainerNode.h +// Cog +// +// Created by Vincent Spader on 10/15/07. +// Copyright 2007 __MyCompanyName__. All rights reserved. +// + +#import + +#import "PathNode.h" + +@interface ContainerNode : PathNode { + +} + +@end diff --git a/FileDrawer/ContainerNode.m b/FileDrawer/ContainerNode.m new file mode 100644 index 000000000..8336d7662 --- /dev/null +++ b/FileDrawer/ContainerNode.m @@ -0,0 +1,40 @@ +// +// ContainerNode.m +// Cog +// +// Created by Vincent Spader on 10/15/07. +// Copyright 2007 __MyCompanyName__. All rights reserved. +// + +#import "ContainerNode.h" +#import "CogAudio/AudioContainer.h" + +#import "ContainedNode.h" + +@implementation ContainerNode + +- (BOOL)isLeaf +{ + return NO; +} + +- (void)updatePath +{ + NSArray *urls = [AudioContainer urlsForContainerURL:url]; + + NSURL *u; + NSEnumerator *e = [urls objectEnumerator]; + NSMutableArray *paths = [[NSMutableArray alloc] init]; + while (u = [e nextObject]) + { + ContainedNode *node = [[ContainedNode alloc] initWithDataSource:dataSource url:u]; + NSLog(@"Node: %@", u); + [paths addObject:node]; + } + + [self setSubpaths:paths]; + + [paths release]; +} + +@end diff --git a/FileDrawer/DirectoryNode.m b/FileDrawer/DirectoryNode.m index f67425121..06a85a9ca 100644 --- a/FileDrawer/DirectoryNode.m +++ b/FileDrawer/DirectoryNode.m @@ -20,13 +20,13 @@ - (void)updatePath { - NSArray *contents = [[[NSFileManager defaultManager] directoryContentsAtPath:path] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; + NSArray *contents = [[[NSFileManager defaultManager] directoryContentsAtPath:[url path]] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; NSMutableArray *fullPaths = [[NSMutableArray alloc] init]; NSString *s; NSEnumerator *e = [contents objectEnumerator]; while (s = [e nextObject]) { - [fullPaths addObject:[path stringByAppendingPathComponent: s]]; + [fullPaths addObject:[[url path] stringByAppendingPathComponent: s]]; } [self processPaths: fullPaths]; diff --git a/FileDrawer/FileIconCell.m b/FileDrawer/FileIconCell.m index 9c7935dfd..523f7233c 100644 --- a/FileDrawer/FileIconCell.m +++ b/FileDrawer/FileIconCell.m @@ -11,14 +11,14 @@ @implementation FileIconCell -- (void)setObjectValue:(id)o +- (void)setObjectValue:(PathNode *)o { - if ([o respondsToSelector:@selector(icon)] && [o respondsToSelector:@selector(displayPath)]) { - [super setObjectValue:[o displayPath]]; + if ([o respondsToSelector:@selector(icon)] && [o respondsToSelector:@selector(display)]) { + [super setObjectValue:[o display]]; [super setImage: [o icon]]; } else { - [super setObjectValue:o]; + [super setObjectValue:(id)o]; } } diff --git a/FileDrawer/FileOutlineView.m b/FileDrawer/FileOutlineView.m index 16af03081..f7fa7d472 100644 --- a/FileDrawer/FileOutlineView.m +++ b/FileDrawer/FileOutlineView.m @@ -10,7 +10,6 @@ #import "FileIconCell.h" #import "FileTreeDataSource.h" - @interface FileOutlineView (KFTypeSelectTableViewSupport) - (void)findPrevious:(id)sender; - (void)findNext:(id)sender; diff --git a/FileDrawer/PathNode.h b/FileDrawer/PathNode.h index 8324bddf4..434ef0904 100644 --- a/FileDrawer/PathNode.h +++ b/FileDrawer/PathNode.h @@ -14,25 +14,25 @@ { FileTreeDataSource *dataSource; - NSString *path; - NSString *displayPath; //The pretty path to display. + NSURL *url; + NSString *display; //The pretty path to display. NSImage *icon; NSArray *subpaths; } -- (id)initWithDataSource:(FileTreeDataSource *)ds path:(NSString *)p; +- (id)initWithDataSource:(FileTreeDataSource *)ds url:(NSURL *)u; -- (NSString *)path; -- (void)setPath:(NSString *)p; +- (NSURL *)url; +- (void)setURL:(NSURL *)url; - (void)processPaths: (NSArray *)contents; - (NSArray *)subpaths; - (void)setSubpaths:(NSArray *)s; -- (NSString *)displayPath; +- (NSString *)display; - (NSImage *)icon; - (BOOL)isLeaf; diff --git a/FileDrawer/PathNode.m b/FileDrawer/PathNode.m index 6397ce943..662670165 100644 --- a/FileDrawer/PathNode.m +++ b/FileDrawer/PathNode.m @@ -17,56 +17,42 @@ @class FileNode; @class DirectoryNode; @class SmartFolderNode; +@class ContainerNode; @implementation PathNode //From http://developer.apple.com/documentation/Cocoa/Conceptual/LowLevelFileMgmt/Tasks/ResolvingAliases.html -NSString *resolveAliases(NSString *path) +NSURL *resolveAliases(NSURL *url) { - NSString *resolvedPath = nil; - CFURLRef url; - - url = CFURLCreateWithFileSystemPath(NULL /*allocator*/, (CFStringRef)path, kCFURLPOSIXPathStyle, NO /*isDirectory*/); - - if (url != NULL) + FSRef fsRef; + if (CFURLGetFSRef((CFURLRef)url, &fsRef)) { - FSRef fsRef; - if (CFURLGetFSRef(url, &fsRef)) - { - Boolean targetIsFolder, wasAliased; + Boolean targetIsFolder, wasAliased; - if (FSResolveAliasFile (&fsRef, true /*resolveAliasChains*/, &targetIsFolder, &wasAliased) == noErr && wasAliased) + if (FSResolveAliasFile (&fsRef, true /*resolveAliasChains*/, &targetIsFolder, &wasAliased) == noErr && wasAliased) + { + CFURLRef resolvedUrl = CFURLCreateFromFSRef(NULL, &fsRef); + + if (resolvedUrl != NULL) { - CFURLRef resolvedUrl = CFURLCreateFromFSRef(NULL, &fsRef); - - if (resolvedUrl != NULL) - { - resolvedPath = (NSString*) - - CFURLCopyFileSystemPath(resolvedUrl, kCFURLPOSIXPathStyle); - - CFRelease(resolvedUrl); - } + NSLog(@"Resolved..."); + return [(NSURL *)resolvedUrl autorelease]; } } - - CFRelease(url); } - if (resolvedPath==nil) - resolvedPath = [[NSString alloc] initWithString:path]; - - return resolvedPath; + NSLog(@"Not resolved"); + return url; } -- (id)initWithDataSource:(FileTreeDataSource *)ds path:(NSString *)p +- (id)initWithDataSource:(FileTreeDataSource *)ds url:(NSURL *)u { self = [super init]; if (self) { dataSource = ds; - [self setPath: p]; + [self setURL: u]; } return self; @@ -74,22 +60,22 @@ NSString *resolveAliases(NSString *path) - (void)stopWatching { - if (path) + if (url) { - NSLog(@"Stopped watching...: %@", path); + NSLog(@"Stopped watching...: %@", [url path]); //Remove all in one go [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self]; - [[UKKQueue sharedFileWatcher] removePath:path]; + [[UKKQueue sharedFileWatcher] removePath:[url path]]; } } - (void)startWatching { - if (path) + if (url) { - NSLog(@"WATCHING! %@ %i", path, path); + NSLog(@"WATCHING! %@", [url path]); [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(updatePathNotification:) name:UKFileWatcherRenameNotification object:nil]; [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(updatePathNotification:) name:UKFileWatcherWriteNotification object:nil]; @@ -99,36 +85,36 @@ NSString *resolveAliases(NSString *path) [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(updatePathNotification:) name:UKFileWatcherLinkCountChangeNotification object:nil]; [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(updatePathNotification:) name:UKFileWatcherAccessRevocationNotification object:nil]; - [[UKKQueue sharedFileWatcher] addPath:path]; + [[UKKQueue sharedFileWatcher] addPath:[url path]]; } } -- (void)setPath:(NSString *)p +- (void)setURL:(NSURL *)u { - [p retain]; + [u retain]; [self stopWatching]; - [path release]; + [url release]; - path = p; + url = u; [self startWatching]; - [displayPath release]; - displayPath = [[NSFileManager defaultManager] displayNameAtPath:path]; - [displayPath retain]; + [display release]; + display = [[NSFileManager defaultManager] displayNameAtPath:[url path]]; + [display retain]; [icon release]; - icon = [[NSWorkspace sharedWorkspace] iconForFile:path]; + icon = [[NSWorkspace sharedWorkspace] iconForFile:[url path]]; [icon retain]; [icon setSize: NSMakeSize(16.0, 16.0)]; } -- (NSString *)path +- (NSURL *)url { - return path; + return url; } - (void)updatePath @@ -143,10 +129,8 @@ NSString *resolveAliases(NSString *path) - (void)updatePathNotificationMainThread:(NSNotification *)notification { NSString *p = [[notification userInfo] objectForKey:@"path"]; - if (p == path) + if ([p isEqualToString:[url path]]) { - NSLog(@"Update path notification: %@", [NSThread currentThread]); - [self updatePath]; [dataSource reloadPathNode:self]; @@ -166,33 +150,41 @@ NSString *resolveAliases(NSString *path) continue; } + NSURL *u = [NSURL fileURLWithPath:s]; + PathNode *newNode; - s = resolveAliases(s); + NSLog(@"Before: %@", u); + u = resolveAliases(u); + NSLog(@"After: %@", u); if ([[s pathExtension] caseInsensitiveCompare:@"savedSearch"] == NSOrderedSame) { NSLog(@"Smart folder!"); - newNode = [[SmartFolderNode alloc] initWithDataSource:dataSource path:s]; + newNode = [[SmartFolderNode alloc] initWithDataSource:dataSource url:u]; } else { BOOL isDir; - [[NSFileManager defaultManager] fileExistsAtPath:s isDirectory:&isDir]; - - if (!isDir && ![[AudioPlayer fileTypes] containsObject:[s pathExtension]]) + [[NSFileManager defaultManager] fileExistsAtPath:[u path] isDirectory:&isDir]; + + if (!isDir && ![[AudioPlayer fileTypes] containsObject:[[u path] pathExtension]]) { continue; } if (isDir) { - newNode = [[DirectoryNode alloc] initWithDataSource:dataSource path: s]; + newNode = [[DirectoryNode alloc] initWithDataSource:dataSource url:u]; + } + else if ([[AudioPlayer containerTypes] containsObject:[[[u path] pathExtension] lowercaseString]]) + { + newNode = [[ContainerNode alloc] initWithDataSource:dataSource url:u]; } else { - newNode = [[FileNode alloc] initWithDataSource:dataSource path: s]; + newNode = [[FileNode alloc] initWithDataSource:dataSource url:u]; } } @@ -229,9 +221,9 @@ NSString *resolveAliases(NSString *path) return YES; } -- (NSString *)displayPath +- (NSString *)display { - return displayPath; + return display; } - (NSImage *)icon @@ -243,7 +235,7 @@ NSString *resolveAliases(NSString *path) { [self stopWatching]; - [path release]; + [url release]; [icon release]; [subpaths release]; diff --git a/FileDrawer/SmartFolderNode.m b/FileDrawer/SmartFolderNode.m index 2ee4ef1ee..2d6abbf8d 100644 --- a/FileDrawer/SmartFolderNode.m +++ b/FileDrawer/SmartFolderNode.m @@ -20,7 +20,7 @@ - (void)updatePath { - NSDictionary *doc = [NSDictionary dictionaryWithContentsOfFile:path]; + NSDictionary *doc = [NSDictionary dictionaryWithContentsOfFile:[url path]]; NSString *rawQuery = [doc objectForKey:@"RawQuery"]; NSArray *searchPaths = [[doc objectForKey:@"SearchCriteria"] objectForKey:@"CurrentFolderPath"]; diff --git a/Playlist/DNDArrayController.h b/Playlist/DNDArrayController.h index 98eafba8a..319ce7c53 100755 --- a/Playlist/DNDArrayController.h +++ b/Playlist/DNDArrayController.h @@ -2,6 +2,7 @@ #import extern NSString *MovedRowsType; +extern NSString *CogUrlsPbboardType; extern NSString *iTunesDropType; @interface DNDArrayController : NSArrayController diff --git a/Playlist/DNDArrayController.m b/Playlist/DNDArrayController.m index e5bd6aef8..ed31a3612 100755 --- a/Playlist/DNDArrayController.m +++ b/Playlist/DNDArrayController.m @@ -4,6 +4,7 @@ @implementation DNDArrayController NSString *MovedRowsType = @"MOVED_ROWS_TYPE"; +NSString *CogUrlsPbboardType = @"COG_URLS_TYPE"; // @"CorePasteboardFlavorType 0x6974756E" is the "itun" type representing an iTunes plist NSString *iTunesDropType = @"CorePasteboardFlavorType 0x6974756E"; @@ -11,8 +12,7 @@ NSString *iTunesDropType = @"CorePasteboardFlavorType 0x6974756E"; - (void)awakeFromNib { // register for drag and drop - [tableView registerForDraggedTypes:[NSArray arrayWithObjects:MovedRowsType, NSFilenamesPboardType, - iTunesDropType, nil]]; + [tableView registerForDraggedTypes:[NSArray arrayWithObjects:MovedRowsType, CogUrlsPbboardType, NSFilenamesPboardType, iTunesDropType, nil]]; } diff --git a/Playlist/PlaylistController.m b/Playlist/PlaylistController.m index ab4f65fb6..df3a05805 100644 --- a/Playlist/PlaylistController.m +++ b/Playlist/PlaylistController.m @@ -66,10 +66,17 @@ row = 0; // Determine the type of object that was dropped - NSArray *supportedtypes = [NSArray arrayWithObjects:NSFilenamesPboardType, iTunesDropType, nil]; + NSArray *supportedtypes = [NSArray arrayWithObjects:CogUrlsPbboardType, NSFilenamesPboardType, iTunesDropType, nil]; NSPasteboard *pboard = [info draggingPasteboard]; NSString *bestType = [pboard availableTypeFromArray:supportedtypes]; + // Get files from an file drawer drop + if ([bestType isEqualToString:CogUrlsPbboardType]) { + NSArray *urls = [NSUnarchiver unarchiveObjectWithData:[[info draggingPasteboard] dataForType:CogUrlsPbboardType]]; + NSLog(@"URLS: %@", urls); + [playlistLoader insertURLs: urls atIndex:row sort:YES]; + } + // Get files from a normal file drop (such as from Finder) if ([bestType isEqualToString:NSFilenamesPboardType]) { NSMutableArray *urls = [[NSMutableArray alloc] init]; diff --git a/Playlist/PlaylistLoader.m b/Playlist/PlaylistLoader.m index d7be1002f..0fd9323c1 100755 --- a/Playlist/PlaylistLoader.m +++ b/Playlist/PlaylistLoader.m @@ -200,7 +200,7 @@ while (url = [urlEnumerator nextObject]) { //File url - if ([[self acceptableContainerTypes] containsObject:[[[url path] pathExtension] lowercaseString]]) { + if ([[self acceptableContainerTypes] containsObject:[[[url path] pathExtension] lowercaseString]] && ([url fragment] == nil)) { if ([url isFileURL] ) { [allURLs addObjectsFromArray:[AudioContainer urlsForContainerURL:url]];