Cleaned up code. Added PlaylistLoader class properly, with support for m3u and pls formats. Changed default playlist to m3u. Added bugs GALORE!

CQTexperiment
vspader 2007-03-09 01:16:06 +00:00
parent 94201b5a4f
commit 15f1aa2ebd
19 changed files with 416 additions and 502 deletions

View File

@ -2,23 +2,24 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "PlaybackController.h"
#import "PlaylistController.h"
#import "PlaylistView.h"
#import "FileTreeController.h"
#import "FileOutlineView.h"
#import "NDHotKeyEvent.h" #import "NDHotKeyEvent.h"
#import "AppleRemote.h" @class PlaybackController;
@class PlaylistController;
@class PlaylistView;
@class FileTreeController;
@class FileOutlineView;
@class AppleRemote;
@class PlaylistLoader;
@interface AppController : NSObject @interface AppController : NSObject
{ {
IBOutlet PlaylistController *playlistController;
IBOutlet PlaybackController *playbackController; IBOutlet PlaybackController *playbackController;
IBOutlet PlaylistController *playlistController;
IBOutlet PlaylistLoader *playlistLoader;
IBOutlet NSPanel *mainWindow; IBOutlet NSPanel *mainWindow;
IBOutlet NSPanel *addURLPanel; IBOutlet NSPanel *addURLPanel;

View File

@ -1,5 +1,13 @@
#import "AppController.h" #import "AppController.h"
#import "KFTypeSelectTableView.h"" #import "KFTypeSelectTableView.h""
#import "PlaybackController.h"
#import "PlaylistController.h"
#import "PlaylistView.h"
#import "FileTreeController.h"
#import "FileOutlineView.h"
#import "NDHotKeyEvent.h"
#import "AppleRemote.h"
#import "PlaylistLoader.h"
@implementation AppController @implementation AppController
@ -124,7 +132,7 @@ increase/decrease as long as the user holds the left/right, plus/minus button */
[p setCanChooseDirectories:YES]; [p setCanChooseDirectories:YES];
[p setAllowsMultipleSelection:YES]; [p setAllowsMultipleSelection:YES];
[p beginSheetForDirectory:nil file:nil types:[playlistController acceptableFileTypes] modalForWindow:mainWindow modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL]; [p beginSheetForDirectory:nil file:nil types:[playlistLoader acceptableFileTypes] modalForWindow:mainWindow modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
// [p beginForDirectory:nil file:nil types:[playlistController acceptableFileTypes] modelessDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:nil]; // [p beginForDirectory:nil file:nil types:[playlistController acceptableFileTypes] modelessDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:nil];
/* if ([p runModalForTypes:[playlistController acceptableFileTypes]] == NSOKButton) /* if ([p runModalForTypes:[playlistController acceptableFileTypes]] == NSOKButton)
@ -138,7 +146,7 @@ increase/decrease as long as the user holds the left/right, plus/minus button */
{ {
if (returnCode == NSOKButton) if (returnCode == NSOKButton)
{ {
[playlistController addPaths:[panel filenames] sort:YES]; [playlistLoader addURLs:[panel URLs] sort:YES];
} }
// [panel release]; // [panel release];
@ -238,8 +246,8 @@ increase/decrease as long as the user holds the left/right, plus/minus button */
} }
NSString *filename = @"~/Library/Application Support/Cog/Default.playlist"; NSString *filename = @"~/Library/Application Support/Cog/Default.m3u";
[playlistController loadPlaylist:[filename stringByExpandingTildeInPath]]; [playlistLoader loadM3u:[filename stringByExpandingTildeInPath]];
} }
- (void)applicationWillTerminate:(NSNotification *)aNotification - (void)applicationWillTerminate:(NSNotification *)aNotification
@ -257,18 +265,15 @@ increase/decrease as long as the user holds the left/right, plus/minus button */
[fileManager createDirectoryAtPath: folder attributes: nil]; [fileManager createDirectoryAtPath: folder attributes: nil];
} }
NSString *fileName = @"Default.playlist"; NSString *fileName = @"Default.m3u";
[playlistController savePlaylist:[folder stringByAppendingPathComponent: fileName]]; [playlistLoader saveM3u:[folder stringByAppendingPathComponent: fileName]];
} }
- (IBAction)savePlaylist:(id)sender - (IBAction)savePlaylist:(id)sender
{ {
if ([playlistController playlistFilename] == nil) [playlistLoader save];
[self savePlaylistAs:sender];
[playlistController savePlaylist:[playlistController playlistFilename]];
} }
- (IBAction)savePlaylistAs:(id)sender - (IBAction)savePlaylistAs:(id)sender
{ {
@ -276,13 +281,11 @@ increase/decrease as long as the user holds the left/right, plus/minus button */
p = [NSSavePanel savePanel]; p = [NSSavePanel savePanel];
[p setAllowedFileTypes:[playlistController acceptablePlaylistTypes]]; [p setAllowedFileTypes:[playlistLoader acceptablePlaylistTypes]];
if ([p runModalForDirectory:nil file:[[playlistController playlistFilename] lastPathComponent]] == NSOKButton) if ([p runModalForDirectory:nil file:[[playlistLoader currentFile] lastPathComponent]] == NSOKButton)
{ {
[playlistController setPlaylistFilename:[p filename]]; [playlistLoader save:[p filename]];
[playlistController savePlaylist:[p filename]];
} }
} }
@ -295,11 +298,9 @@ increase/decrease as long as the user holds the left/right, plus/minus button */
[p setCanChooseDirectories:NO]; [p setCanChooseDirectories:NO];
[p setAllowsMultipleSelection:NO]; [p setAllowsMultipleSelection:NO];
if ([p runModalForTypes:[playlistController acceptablePlaylistTypes]] == NSOKButton) if ([p runModalForTypes:[playlistLoader acceptablePlaylistTypes]] == NSOKButton)
{ {
[playlistController setPlaylistFilename:[p filename]]; [playlistLoader load:[p filename]];
[playlistController loadPlaylist:[p filename]];
} }
[mainWindow makeKeyAndOrderFront:self]; [mainWindow makeKeyAndOrderFront:self];
@ -316,16 +317,24 @@ increase/decrease as long as the user holds the left/right, plus/minus button */
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
{ {
DBLog(@"Adding path: %@", filename); DBLog(@"Adding path: %@", filename);
[playlistController addPaths:[NSArray arrayWithObject:filename] sort:NO]; [playlistLoader addURLs:[NSArray arrayWithObject:[NSURL fileURLWithPath:filename]] sort:NO];
return YES; return YES;
} }
- (void)application:(NSApplication *)theApplication openFiles:(NSArray *)filenames - (void)application:(NSApplication *)theApplication openFiles:(NSArray *)filenames
{ {
DBLog(@"Adding paths: %@", filenames); //Need to convert to urls
NSMutableArray *urls = [NSMutableArray array];
NSEnumerator *e = [filenames objectEnumerator];
NSString *filename;
while (filename = [e nextObject])
{
[urls addObject:[NSURL fileURLWithPath:filename]];
}
[playlistLoader addURLs:urls sort:YES];
[playlistController addPaths:filenames sort:YES];
[theApplication replyToOpenOrPrint:NSApplicationDelegateReplySuccess]; [theApplication replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
} }

View File

@ -45,6 +45,7 @@
- (void)setNextStream:(NSURL *)url withUserInfo:(id)userInfo; - (void)setNextStream:(NSURL *)url withUserInfo:(id)userInfo;
+ (NSArray *)fileTypes; + (NSArray *)fileTypes;
+ (NSArray *)schemes;
@end @end

View File

@ -280,5 +280,12 @@
return [types allObjects]; return [types allObjects];
} }
+ (NSArray *)schemes
{
PluginController *pluginController = [PluginController sharedPluginController];
return [[pluginController sources] allKeys];
}
@end @end

View File

@ -11,6 +11,8 @@
170680630B950158006BA573 /* Growl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 170680620B950158006BA573 /* Growl.framework */; }; 170680630B950158006BA573 /* Growl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 170680620B950158006BA573 /* Growl.framework */; };
170680840B950164006BA573 /* Growl.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 170680620B950158006BA573 /* Growl.framework */; }; 170680840B950164006BA573 /* Growl.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 170680620B950158006BA573 /* Growl.framework */; };
171678C00AC8C39E00C28CF3 /* SmartFolderNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 171678BE0AC8C39E00C28CF3 /* SmartFolderNode.m */; }; 171678C00AC8C39E00C28CF3 /* SmartFolderNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 171678BE0AC8C39E00C28CF3 /* SmartFolderNode.m */; };
1755E1F80BA0D2B600CA3560 /* PlaylistLoader.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1755E1F60BA0D2B600CA3560 /* PlaylistLoader.h */; };
1755E1F90BA0D2B600CA3560 /* PlaylistLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 1755E1F70BA0D2B600CA3560 /* PlaylistLoader.m */; };
175D8B640B9A514C005B3CD9 /* CogAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 175D8B630B9A514C005B3CD9 /* CogAudio.framework */; }; 175D8B640B9A514C005B3CD9 /* CogAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 175D8B630B9A514C005B3CD9 /* CogAudio.framework */; };
175D8B670B9A5153005B3CD9 /* CogAudio.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 175D8B630B9A514C005B3CD9 /* CogAudio.framework */; }; 175D8B670B9A5153005B3CD9 /* CogAudio.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 175D8B630B9A514C005B3CD9 /* CogAudio.framework */; };
1766C6930B911DF1004A7AE4 /* AudioScrobbler.m in Sources */ = {isa = PBXBuildFile; fileRef = 1766C68F0B911DF1004A7AE4 /* AudioScrobbler.m */; }; 1766C6930B911DF1004A7AE4 /* AudioScrobbler.m in Sources */ = {isa = PBXBuildFile; fileRef = 1766C68F0B911DF1004A7AE4 /* AudioScrobbler.m */; };
@ -138,6 +140,7 @@
175D8B670B9A5153005B3CD9 /* CogAudio.framework in CopyFiles */, 175D8B670B9A5153005B3CD9 /* CogAudio.framework in CopyFiles */,
170680840B950164006BA573 /* Growl.framework in CopyFiles */, 170680840B950164006BA573 /* Growl.framework in CopyFiles */,
17F94CCD0B8D090800A34E87 /* Sparkle.framework in CopyFiles */, 17F94CCD0B8D090800A34E87 /* Sparkle.framework in CopyFiles */,
1755E1F80BA0D2B600CA3560 /* PlaylistLoader.h in CopyFiles */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -150,6 +153,8 @@
170680620B950158006BA573 /* Growl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Growl.framework; path = ThirdParty/Frameworks/Growl.framework; sourceTree = "<group>"; }; 170680620B950158006BA573 /* Growl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Growl.framework; path = ThirdParty/Frameworks/Growl.framework; sourceTree = "<group>"; };
171678BD0AC8C39E00C28CF3 /* SmartFolderNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmartFolderNode.h; sourceTree = "<group>"; }; 171678BD0AC8C39E00C28CF3 /* SmartFolderNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmartFolderNode.h; sourceTree = "<group>"; };
171678BE0AC8C39E00C28CF3 /* SmartFolderNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SmartFolderNode.m; sourceTree = "<group>"; }; 171678BE0AC8C39E00C28CF3 /* SmartFolderNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SmartFolderNode.m; sourceTree = "<group>"; };
1755E1F60BA0D2B600CA3560 /* PlaylistLoader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PlaylistLoader.h; sourceTree = "<group>"; };
1755E1F70BA0D2B600CA3560 /* PlaylistLoader.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = PlaylistLoader.m; sourceTree = "<group>"; };
175D8B630B9A514C005B3CD9 /* CogAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CogAudio.framework; path = Audio/build/Release/CogAudio.framework; sourceTree = "<group>"; }; 175D8B630B9A514C005B3CD9 /* CogAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CogAudio.framework; path = Audio/build/Release/CogAudio.framework; sourceTree = "<group>"; };
1766C68E0B911DF1004A7AE4 /* AudioScrobbler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AudioScrobbler.h; sourceTree = "<group>"; }; 1766C68E0B911DF1004A7AE4 /* AudioScrobbler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AudioScrobbler.h; sourceTree = "<group>"; };
1766C68F0B911DF1004A7AE4 /* AudioScrobbler.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = AudioScrobbler.m; sourceTree = "<group>"; }; 1766C68F0B911DF1004A7AE4 /* AudioScrobbler.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = AudioScrobbler.m; sourceTree = "<group>"; };
@ -613,6 +618,8 @@
children = ( children = (
8E1296D80A2BA9CE00443124 /* PlaylistHeaderView.h */, 8E1296D80A2BA9CE00443124 /* PlaylistHeaderView.h */,
8E1296D90A2BA9CE00443124 /* PlaylistHeaderView.m */, 8E1296D90A2BA9CE00443124 /* PlaylistHeaderView.m */,
1755E1F60BA0D2B600CA3560 /* PlaylistLoader.h */,
1755E1F70BA0D2B600CA3560 /* PlaylistLoader.m */,
8E75752B09F31D5A0080F1EE /* DNDArrayController.h */, 8E75752B09F31D5A0080F1EE /* DNDArrayController.h */,
8E75752C09F31D5A0080F1EE /* DNDArrayController.m */, 8E75752C09F31D5A0080F1EE /* DNDArrayController.m */,
8E75752D09F31D5A0080F1EE /* PlaylistController.h */, 8E75752D09F31D5A0080F1EE /* PlaylistController.h */,
@ -638,7 +645,6 @@
8EFFCD410AA093AF00C458A5 /* FileDrawer */ = { 8EFFCD410AA093AF00C458A5 /* FileDrawer */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
8EFFCD540AA093AF00C458A5 /* UKKQueue */,
8EFFCD440AA093AF00C458A5 /* FileIconCell.h */, 8EFFCD440AA093AF00C458A5 /* FileIconCell.h */,
8EFFCD450AA093AF00C458A5 /* FileIconCell.m */, 8EFFCD450AA093AF00C458A5 /* FileIconCell.m */,
8EFFCD500AA093AF00C458A5 /* PathIcon.h */, 8EFFCD500AA093AF00C458A5 /* PathIcon.h */,
@ -661,13 +667,6 @@
path = FileDrawer; path = FileDrawer;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
8EFFCD540AA093AF00C458A5 /* UKKQueue */ = {
isa = PBXGroup;
children = (
);
path = UKKQueue;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@ -796,6 +795,7 @@
1770429E0B8BC53600B86321 /* PlaybackController.m in Sources */, 1770429E0B8BC53600B86321 /* PlaybackController.m in Sources */,
1766C6930B911DF1004A7AE4 /* AudioScrobbler.m in Sources */, 1766C6930B911DF1004A7AE4 /* AudioScrobbler.m in Sources */,
1766C6950B911DF1004A7AE4 /* AudioScrobblerClient.m in Sources */, 1766C6950B911DF1004A7AE4 /* AudioScrobblerClient.m in Sources */,
1755E1F90BA0D2B600CA3560 /* PlaylistLoader.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -836,21 +836,9 @@
buildSettings = { buildSettings = {
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(SRCROOT)/Frameworks/CogAudio/build/Release", "$(SRCROOT)/Audio/build/Release",
"$(SRCROOT)/ThirdParty/Frameworks/", "$(SRCROOT)/ThirdParty/Frameworks/",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_3)",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_4)",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_5)",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_6)",
); );
FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/Frameworks/CogAudio/build/Debug\"";
FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/Audio/build/Release\"";
FRAMEWORK_SEARCH_PATHS_QUOTED_3 = "\"$(SRCROOT)/Audio/build/Debug\"";
FRAMEWORK_SEARCH_PATHS_QUOTED_4 = "\"$(SRCROOT)/Audio/build/Release\"";
FRAMEWORK_SEARCH_PATHS_QUOTED_5 = "\"$(SRCROOT)/Audio/build/Release\"";
FRAMEWORK_SEARCH_PATHS_QUOTED_6 = "\"$(SRCROOT)/Audio/build/Debug\"";
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_ENABLE_OBJC_EXCEPTIONS = YES;
@ -881,21 +869,9 @@
i386, i386,
); );
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(SRCROOT)/Frameworks/CogAudio/build/Release", "$(SRCROOT)/Audio/build/Release",
"$(SRCROOT)/ThirdParty/Frameworks/", "$(SRCROOT)/ThirdParty/Frameworks/",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_2)",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_3)",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_4)",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_5)",
"$(FRAMEWORK_SEARCH_PATHS_QUOTED_6)",
); );
FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/Frameworks/CogAudio/build/Debug\"";
FRAMEWORK_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/Audio/build/Release\"";
FRAMEWORK_SEARCH_PATHS_QUOTED_3 = "\"$(SRCROOT)/Audio/build/Debug\"";
FRAMEWORK_SEARCH_PATHS_QUOTED_4 = "\"$(SRCROOT)/Audio/build/Release\"";
FRAMEWORK_SEARCH_PATHS_QUOTED_5 = "\"$(SRCROOT)/Audio/build/Release\"";
FRAMEWORK_SEARCH_PATHS_QUOTED_6 = "\"$(SRCROOT)/Audio/build/Debug\"";
GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_MODEL_TUNING = G5; GCC_MODEL_TUNING = G5;

View File

@ -41,6 +41,7 @@
playButton = NSButton; playButton = NSButton;
playbackController = PlaybackController; playbackController = PlaybackController;
playlistController = PlaylistController; playlistController = PlaylistController;
playlistLoader = PlaylistLoader;
playlistView = PlaylistView; playlistView = PlaylistView;
prevButton = NSButton; prevButton = NSButton;
repeatButton = NSButton; repeatButton = NSButton;
@ -87,7 +88,7 @@
{ {
CLASS = FileTreeController; CLASS = FileTreeController;
LANGUAGE = ObjC; LANGUAGE = ObjC;
OUTLETS = {playlistController = PlaylistController; }; OUTLETS = {playlistLoader = PlaylistLoader; };
SUPERCLASS = NSTreeController; SUPERCLASS = NSTreeController;
}, },
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
@ -127,16 +128,22 @@
}, },
{ {
ACTIONS = { ACTIONS = {
showFileInFinder = id; showEntryInFinder = id;
sortByPath = id;
takeRepeatFromObject = id; takeRepeatFromObject = id;
takeShuffleFromObject = id; takeShuffleFromObject = id;
}; };
CLASS = PlaylistController; CLASS = PlaylistController;
LANGUAGE = ObjC; LANGUAGE = ObjC;
OUTLETS = {playlistLoader = PlaylistLoader; };
SUPERCLASS = DNDArrayController; SUPERCLASS = DNDArrayController;
}, },
{CLASS = PlaylistEntry; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, {CLASS = PlaylistEntry; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{
CLASS = PlaylistLoader;
LANGUAGE = ObjC;
OUTLETS = {playlistController = PlaylistController; };
SUPERCLASS = NSObject;
},
{ {
ACTIONS = {shufflePlaylist = id; sortByPath = id; toggleColumn = id; }; ACTIONS = {shufflePlaylist = id; sortByPath = id; toggleColumn = id; };
CLASS = PlaylistView; CLASS = PlaylistView;

View File

@ -15,7 +15,7 @@
<key>463</key> <key>463</key>
<string>669 637 341 145 0 0 1680 1028 </string> <string>669 637 341 145 0 0 1680 1028 </string>
<key>513</key> <key>513</key>
<string>1026 274 125 137 0 0 1680 1028 </string> <string>352 836 125 137 0 0 1680 1028 </string>
</dict> </dict>
<key>IBFramework Version</key> <key>IBFramework Version</key>
<string>446.1</string> <string>446.1</string>
@ -32,12 +32,12 @@
<integer>4</integer> <integer>4</integer>
<key>IBOpenObjects</key> <key>IBOpenObjects</key>
<array> <array>
<integer>463</integer>
<integer>29</integer>
<integer>1156</integer>
<integer>1307</integer>
<integer>513</integer> <integer>513</integer>
<integer>29</integer>
<integer>463</integer>
<integer>1156</integer>
<integer>21</integer> <integer>21</integer>
<integer>1307</integer>
</array> </array>
<key>IBSystem Version</key> <key>IBSystem Version</key>
<string>8L2127</string> <string>8L2127</string>

Binary file not shown.

View File

@ -23,7 +23,7 @@
- (void)alertDidEnd:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo - (void)alertDidEnd:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo
{ {
if (contextInfo == YES) if ([(NSNumber *)contextInfo boolValue]== YES)
{ {
[feedbackWindow close]; [feedbackWindow close];
} }
@ -39,7 +39,7 @@
[alert setMessageText:NSLocalizedString(@"FeedbackFailedMessageText", @"")]; [alert setMessageText:NSLocalizedString(@"FeedbackFailedMessageText", @"")];
[alert setInformativeText:NSLocalizedString(@"FeedbackFailedInformativeText", @"")]; [alert setInformativeText:NSLocalizedString(@"FeedbackFailedInformativeText", @"")];
[alert beginSheetModalForWindow:feedbackWindow modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:NO]; [alert beginSheetModalForWindow:feedbackWindow modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:[NSNumber numberWithBool:NO]];
} }
- (void)FeedbackSent:(NSNotification *)aNotification - (void)FeedbackSent:(NSNotification *)aNotification
@ -52,7 +52,7 @@
[alert setMessageText:NSLocalizedString(@"FeedbackSuccessMessageText", @"")]; [alert setMessageText:NSLocalizedString(@"FeedbackSuccessMessageText", @"")];
[alert setInformativeText:NSLocalizedString(@"FeedbackSuccessInformativeText", @"")]; [alert setInformativeText:NSLocalizedString(@"FeedbackSuccessInformativeText", @"")];
[alert beginSheetModalForWindow:feedbackWindow modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:YES]; [alert beginSheetModalForWindow:feedbackWindow modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:[NSNumber numberWithBool:YES]];
} }

View File

@ -7,12 +7,13 @@
// //
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "FileTreeWatcher.h"
#import "PlaylistController.h" @class FileTreeWatcher;
@class PlaylistLoader;
@interface FileTreeController : NSTreeController @interface FileTreeController : NSTreeController
{ {
IBOutlet PlaylistController *playlistController; IBOutlet PlaylistLoader *playlistLoader;
NSString *rootPath; NSString *rootPath;
@ -21,5 +22,6 @@
- (id)rootPath; - (id)rootPath;
- (void)setRootPath:(id)r; - (void)setRootPath:(id)r;
- (void) refreshRoot;
@end @end

View File

@ -7,9 +7,11 @@
// //
#import "FileTreeController.h" #import "FileTreeController.h"
#import "FileTreeWatcher.h"
#import "DirectoryNode.h" #import "DirectoryNode.h"
#import "ImageTextCell.h" #import "ImageTextCell.h"
#import "KFTypeSelectTableView.h" #import "KFTypeSelectTableView.h"
#import "PlaylistLoader.h"
@implementation FileTreeController @implementation FileTreeController
@ -109,7 +111,7 @@
- (NSArray *)acceptableFileTypes - (NSArray *)acceptableFileTypes
{ {
return [playlistController acceptableFileTypes]; return [playlistLoader acceptableFileTypes];
} }
- (FileTreeWatcher *)watcher - (FileTreeWatcher *)watcher
@ -119,22 +121,21 @@
- (BOOL)outlineView:(NSOutlineView *)olv writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard { - (BOOL)outlineView:(NSOutlineView *)olv writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard {
//Get selected paths //Get selected paths
NSLog(@"Items: %@", items);
NSMutableArray *paths = [NSMutableArray arrayWithCapacity:[items count]]; NSMutableArray *paths = [NSMutableArray arrayWithCapacity:[items count]];
id p;
NSEnumerator *e = [items objectEnumerator]; NSEnumerator *e = [items objectEnumerator];
id p;
while (p = [e nextObject]) { while (p = [e nextObject]) {
int i; int i;
PathNode *n = nil; PathNode *n = nil;
NSIndexPath *ip = [p indexPath]; NSIndexPath *ip = [p indexPath];
NSLog(@"Content: %@", n);
for (i = 0; i < [ip length]; i++) for (i = 0; i < [ip length]; i++)
{ {
NSArray *a = (n == nil) ? [self content] : [n subpaths]; NSArray *a = (n == nil) ? [self content] : [n subpaths];
n = [a objectAtIndex:[ip indexAtPosition:i]]; n = [a objectAtIndex:[ip indexAtPosition:i]];
} }
NSLog(@"Path: %@", n);
[paths addObject:[n path]]; [paths addObject:[n path]];
} }
@ -193,17 +194,20 @@
//End type-select //End type-select
- (void)addSelectedToPlaylist { - (void)addSelectedToPlaylist {
NSMutableArray *paths = [[NSMutableArray alloc] init]; NSMutableArray *urls = [[NSMutableArray alloc] init];
NSArray *nodes = [self selectedObjects]; NSArray *nodes = [self selectedObjects];
NSEnumerator *e = [nodes objectEnumerator]; NSEnumerator *e = [nodes objectEnumerator];
id n; id n;
while (n = [e nextObject]) { while (n = [e nextObject]) {
[paths addObject:[n path]]; NSURL *url = [[NSURL alloc] initFileURLWithPath:[n path]];
[urls addObject:url];
[url release];
} }
[playlistController addPaths:paths sort:YES]; NSLog(@"Adding URLs: %@", urls);
[paths release]; [playlistLoader addURLs:urls sort:YES];
[urls release];
} }

View File

@ -19,4 +19,6 @@
- (void)addPath: (NSString *)path; - (void)addPath: (NSString *)path;
- (void)removePath: (NSString *)path; - (void)removePath: (NSString *)path;
-(void) setDelegate: (id)d;
@end @end

View File

@ -11,15 +11,8 @@ NSString *iTunesDropType = @"CorePasteboardFlavorType 0x6974756E";
- (void)awakeFromNib - (void)awakeFromNib
{ {
// register for drag and drop // register for drag and drop
NSLog(@"AWOKE");
[tableView registerForDraggedTypes:[NSArray arrayWithObjects:MovedRowsType, NSFilenamesPboardType, [tableView registerForDraggedTypes:[NSArray arrayWithObjects:MovedRowsType, NSFilenamesPboardType,
iTunesDropType, nil]]; iTunesDropType, nil]];
// [tableView setVerticalMotionCanBeginDrag:YES];
// [tableView setAllowsMultipleSelection:NO];
// [super awakeFromNib];
// DBLog(@"HERE: %@", [tableView registeredDraggedTypes]);
} }
@ -27,8 +20,6 @@ NSString *iTunesDropType = @"CorePasteboardFlavorType 0x6974756E";
writeRows:(NSArray*)rows writeRows:(NSArray*)rows
toPasteboard:(NSPasteboard*)pboard toPasteboard:(NSPasteboard*)pboard
{ {
NSLog(@"WRITE ROWS");
NSData *data; NSData *data;
data = [NSKeyedArchiver archivedDataWithRootObject:rows]; data = [NSKeyedArchiver archivedDataWithRootObject:rows];
@ -66,11 +57,10 @@ NSString *iTunesDropType = @"CorePasteboardFlavorType 0x6974756E";
{ {
row = 0; row = 0;
} }
NSLog(@"ACCEPTATING");
// if drag source is self, it's a move // if drag source is self, it's a move
if ([info draggingSource] == tableView) if ([info draggingSource] == tableView)
{ {
// DBLog(@"ACCEPTATED");
NSArray *rows = [NSKeyedUnarchiver unarchiveObjectWithData:[[info draggingPasteboard] dataForType: MovedRowsType]]; NSArray *rows = [NSKeyedUnarchiver unarchiveObjectWithData:[[info draggingPasteboard] dataForType: MovedRowsType]];
NSIndexSet *indexSet = [self indexSetFromRows:rows]; NSIndexSet *indexSet = [self indexSetFromRows:rows];

View File

@ -8,13 +8,13 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "DNDArrayController.h" #import "DNDArrayController.h"
#import "PlaylistEntry.h"
@class PlaylistLoader;
@class PlaylistEntry;
@interface PlaylistController : DNDArrayController { @interface PlaylistController : DNDArrayController {
NSArray *acceptableFileTypes; IBOutlet PlaylistLoader *playlistLoader;
NSArray *acceptablePlaylistTypes;
NSString *playlistFilename;
NSString *totalTimeDisplay; NSString *totalTimeDisplay;
NSMutableArray *shuffleList; NSMutableArray *shuffleList;
@ -27,22 +27,12 @@
int selectedRow; int selectedRow;
} }
//All these return the number of things actually added
//Private Methods //Private Methods
//- (int)addPath:(NSString *)path;
//- (int)insertPath:(NSString *)path atIndex:(int)index;
//- (int)insertFile:(NSString *)filename atIndex:(int)index;
//- (int)addFile:(NSString *)filename;
- (void)updateIndexesFromRow:(int) row; - (void)updateIndexesFromRow:(int) row;
- (void)updateTotalTime; - (void)updateTotalTime;
//PUBLIC METHODS //PUBLIC METHODS
- (void)addPaths:(NSArray *)paths sort:(BOOL)sort;
- (void)insertPaths:(NSArray *)paths atIndex:(int)index sort:(BOOL)sort;
- (NSArray *)acceptableFileTypes;
- (void)setShuffle:(BOOL)s; - (void)setShuffle:(BOOL)s;
- (BOOL)shuffle; - (BOOL)shuffle;
- (void)setRepeat:(BOOL)r; - (void)setRepeat:(BOOL)r;
@ -51,7 +41,10 @@
- (IBAction)takeShuffleFromObject:(id)sender; - (IBAction)takeShuffleFromObject:(id)sender;
- (IBAction)takeRepeatFromObject:(id)sender; - (IBAction)takeRepeatFromObject:(id)sender;
- (IBAction)sortByPath:(id)sender; - (IBAction)sortByPath;
- (IBAction)randomizeList;
- (IBAction)showEntryInFinder:(id)sender;
- (void)setTotalTimeDisplay:(NSString *)ttd; - (void)setTotalTimeDisplay:(NSString *)ttd;
- (NSString *)totalTimeDisplay; - (NSString *)totalTimeDisplay;
@ -63,21 +56,10 @@
- (BOOL)next; - (BOOL)next;
- (BOOL)prev; - (BOOL)prev;
- (PlaylistEntry *)entryAtIndex:(int)i;
- (void)addShuffledListToBack; - (void)addShuffledListToBack;
- (void)addShuffledListToFront; - (void)addShuffledListToFront;
- (void)resetShuffleList; - (void)resetShuffleList;
//load/save playlist
- (void)loadPlaylist:(NSString *)filename;
- (void)savePlaylist:(NSString *)filename;
- (NSString *)playlistFilename;
- (void)setPlaylistFilename:(NSString *)pf;
- (NSArray *)acceptablePlaylistTypes;
- (IBAction)showFileInFinder:(id)sender;
- (void)handlePlaylistViewHeaderNotification:(NSNotification*)notif; - (void)handlePlaylistViewHeaderNotification:(NSNotification*)notif;
@end @end

View File

@ -6,6 +6,7 @@
// Copyright 2005 Vincent Spader All rights reserved. // Copyright 2005 Vincent Spader All rights reserved.
// //
#import "PlaylistLoader.h"
#import "PlaylistController.h" #import "PlaylistController.h"
#import "PlaylistEntry.h" #import "PlaylistEntry.h"
#import "Shuffle.h" #import "Shuffle.h"
@ -22,11 +23,7 @@
if (self) if (self)
{ {
acceptableFileTypes = [[AudioPlayer fileTypes] retain];
acceptablePlaylistTypes = [[NSArray alloc] initWithObjects:@"playlist",nil];
shuffleList = [[NSMutableArray alloc] init]; shuffleList = [[NSMutableArray alloc] init];
// DBLog(@"DAH BUTTER CHORNAR: %@", history);
} }
return self; return self;
@ -40,150 +37,6 @@
[ns addObserver:self selector:@selector(handlePlaylistViewHeaderNotification:) name:@"PlaylistViewColumnSeparatorDoubleClick" object:nil]; [ns addObserver:self selector:@selector(handlePlaylistViewHeaderNotification:) name:@"PlaylistViewColumnSeparatorDoubleClick" object:nil];
} }
- (NSArray *)filesAtPath:(NSString *)path
{
BOOL isDir;
NSFileManager *manager;
manager = [NSFileManager defaultManager];
NSLog(@"Checking if path is a directory: %@", path);
if ([manager fileExistsAtPath:path isDirectory:&isDir] && isDir == YES)
{
DBLog(@"path is directory");
int j;
NSArray *subpaths;
NSMutableArray *validPaths = [[NSMutableArray alloc] init];
subpaths = [manager subpathsAtPath:path];
DBLog(@"Subpaths: %@", subpaths);
for (j = 0; j < [subpaths count]; j++)
{
NSString *filepath;
filepath = [NSString pathWithComponents:[NSArray arrayWithObjects:path,[subpaths objectAtIndex:j],nil]];
if ([manager fileExistsAtPath:filepath isDirectory:&isDir] && isDir == NO)
{
if ([acceptableFileTypes containsObject:[[filepath pathExtension] lowercaseString]] && [[NSFileManager defaultManager] fileExistsAtPath:filepath])
{
[validPaths addObject:filepath];
}
}
}
return [validPaths autorelease];
}
else
{
NSLog(@"path is a file");
if ([acceptableFileTypes containsObject:[[path pathExtension] lowercaseString]] && [[NSFileManager defaultManager] fileExistsAtPath:path])
{
NSLog(@"RETURNING THING");
return [NSArray arrayWithObject:path];
}
else
{
return nil;
}
}
}
- (void)insertPaths:(NSArray *)paths atIndex:(int)index sort:(BOOL)sort
{
NSArray *sortedFiles;
NSMutableArray *files = [[NSMutableArray alloc] init];
NSMutableArray *entries= [[NSMutableArray alloc] init];
int i;
if (!paths)
return;
if (index < 0)
index = 0;
for(i=0; i < [paths count]; i++)
{
[files addObjectsFromArray:[self filesAtPath:[paths objectAtIndex:i]]];
NSLog(@"files is: %i", [files count]);
}
DBLog(@"Sorting paths");
if (sort == YES)
{
sortedFiles = [files sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
}
else
{
sortedFiles = files;
}
for (i = 0; i < [sortedFiles count]; i++)
{
PlaylistEntry *pe = [[PlaylistEntry alloc] init];
[pe setURL:[NSURL fileURLWithPath:[sortedFiles objectAtIndex:i]]];
[pe setIndex:index+i];
[pe setTitle:[[sortedFiles objectAtIndex:i] lastPathComponent]];
// [pe performSelectorOnMainThread:@selector(readTags) withObject:nil waitUntilDone:NO];
// [pe performSelectorOnMainThread:@selector(readInfo) withObject:nil waitUntilDone:NO];
[entries addObject:pe];
[pe release];
}
NSRange r = NSMakeRange(index, [entries count]);
NSLog(@"MAking range from: %i to %i", index, index + [entries count]);
NSIndexSet *is = [NSIndexSet indexSetWithIndexesInRange:r];
NSLog(@"INDex set: %@", is);
NSLog(@"Adding: %i files", [entries count]);
[self insertObjects:entries atArrangedObjectIndexes:is];
if (shuffle == YES)
[self resetShuffleList];
[self setSelectionIndex:index];
//Other thread will release entries....crazy crazy bad idea...whatever
[NSThread detachNewThreadSelector:@selector(readMetaData:) toTarget:self withObject:entries];
[files release];
return;
}
- (void)readMetaData:(id)entries
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int i;
for (i = 0; i < [entries count]; i++)
{
PlaylistEntry *pe =[entries objectAtIndex:i];
[pe readInfoThreaded];
[pe readTagsThreaded];
//Hack so the display gets updated
if (pe == [self currentEntry])
[self performSelectorOnMainThread:@selector(setCurrentEntry:) withObject:[self currentEntry] waitUntilDone:YES];
}
[self performSelectorOnMainThread:@selector(updateTotalTime) withObject:nil waitUntilDone:NO];
[entries release];
[pool release];
}
- (void)addPaths:(NSArray *)paths sort:(BOOL)sort
{
[self insertPaths:paths atIndex:[[self arrangedObjects] count] sort:sort];
}
- (NSArray *)acceptableFileTypes
{
return acceptableFileTypes;
}
- (void)tableView:(NSTableView *)tableView - (void)tableView:(NSTableView *)tableView
didClickTableColumn:(NSTableColumn *)tableColumn didClickTableColumn:(NSTableColumn *)tableColumn
@ -199,27 +52,20 @@
row:(int)row row:(int)row
dropOperation:(NSTableViewDropOperation)op dropOperation:(NSTableViewDropOperation)op
{ {
int i;
NSLog(@"DROPPED");
[super tableView:tv acceptDrop:info row:row dropOperation:op]; [super tableView:tv acceptDrop:info row:row dropOperation:op];
if ([info draggingSource] == tableView) if ([info draggingSource] == tableView)
{ {
//DNDArrayController handles moving...still need to update the uhm...indices //DNDArrayController handles moving...still need to update the indexes
NSLog(@"Archive stuff");
NSArray *rows = [NSKeyedUnarchiver unarchiveObjectWithData:[[info draggingPasteboard] dataForType: MovedRowsType]]; int i;
NSLog(@"Whatever"); NSArray *rows = [NSKeyedUnarchiver unarchiveObjectWithData:[[info draggingPasteboard] dataForType: MovedRowsType]];
NSIndexSet *indexSet = [self indexSetFromRows:rows]; int firstIndex = [[self indexSetFromRows:rows] firstIndex];
int firstIndex = [indexSet firstIndex];
if (firstIndex > row) if (firstIndex > row)
{ i = row;
i = row; else
} i = firstIndex;
else
{
i = firstIndex;
}
NSLog(@"Updating indexes: %i", i);
[self updateIndexesFromRow:i]; [self updateIndexesFromRow:i];
return YES; return YES;
@ -235,10 +81,18 @@
// Get files from a normal file drop (such as from Finder) // Get files from a normal file drop (such as from Finder)
if ([bestType isEqualToString:NSFilenamesPboardType]) { if ([bestType isEqualToString:NSFilenamesPboardType]) {
NSArray *files = [[info draggingPasteboard] propertyListForType:NSFilenamesPboardType]; NSMutableArray *urls = [[NSMutableArray alloc] init];
NSLog(@"INSERTING PATHS: %@", files); NSEnumerator *e = [[[info draggingPasteboard] propertyListForType:NSFilenamesPboardType] objectEnumerator];
[self insertPaths:files atIndex:row sort:YES]; NSString *file;
while (file = [e nextObject])
{
[urls addObject:[NSURL fileURLWithPath:file]];
}
[playlistLoader insertURLs:urls atIndex:row sort:YES];
[urls release];
} }
// Get files from an iTunes drop // Get files from an iTunes drop
@ -246,26 +100,19 @@
NSDictionary *iTunesDict = [pboard propertyListForType:iTunesDropType]; NSDictionary *iTunesDict = [pboard propertyListForType:iTunesDropType];
NSDictionary *tracks = [iTunesDict valueForKey:@"Tracks"]; NSDictionary *tracks = [iTunesDict valueForKey:@"Tracks"];
// Convert the iTunes URLs to filenames // Convert the iTunes URLs to URLs....MWAHAHAH!
NSMutableArray *files = [[NSMutableArray alloc] init]; NSMutableArray *urls = [[NSMutableArray alloc] init];
NSEnumerator *e = [[tracks allValues] objectEnumerator]; NSEnumerator *e = [[tracks allValues] objectEnumerator];
NSDictionary *trackInfo; NSDictionary *trackInfo;
NSURL *url;
while (trackInfo = [e nextObject]) { while (trackInfo = [e nextObject]) {
url = [[NSURL alloc] initWithString:[trackInfo valueForKey:@"Location"]]; [urls addObject:[NSURL URLWithString:[trackInfo valueForKey:@"Location"]]];
if ([url isFileURL]) {
[files addObject:[url path]];
} }
[url release]; [playlistLoader insertURLs:urls atIndex:row sort:YES];
[urls release];
} }
NSLog(@"INSERTING ITUNES PATHS: %@", files);
[self insertPaths:files atIndex:row sort:YES];
[files release];
}
NSLog(@"UPDATING");
[self updateIndexesFromRow:row]; [self updateIndexesFromRow:row];
[self updateTotalTime]; [self updateTotalTime];
@ -295,7 +142,6 @@
[ttd retain]; [ttd retain];
[totalTimeDisplay release]; [totalTimeDisplay release];
totalTimeDisplay = ttd; totalTimeDisplay = ttd;
NSLog(@"Displaying: %@", ttd);
} }
- (NSString *)totalTimeDisplay; - (NSString *)totalTimeDisplay;
@ -305,7 +151,6 @@
- (void)updateIndexesFromRow:(int) row - (void)updateIndexesFromRow:(int) row
{ {
// DBLog(@"UPDATE INDEXES: %i", row);
int j; int j;
for (j = row; j < [[self arrangedObjects] count]; j++) for (j = row; j < [[self arrangedObjects] count]; j++)
{ {
@ -318,20 +163,8 @@
- (void)removeObjectsAtArrangedObjectIndexes:(NSIndexSet *)indexes - (void)removeObjectsAtArrangedObjectIndexes:(NSIndexSet *)indexes
{ {
unsigned int *indexBuffer; NSLog(@"REMOVING");
NSMutableArray *a = [[NSMutableArray alloc] init]; NSArray *a = [[self arrangedObjects] objectsAtIndexes:indexes]; //Screw 10.3
int i;
//10.3 fix
indexBuffer = malloc([indexes count]*sizeof(unsigned int));
[indexes getIndexes:indexBuffer maxCount:[indexes count] inIndexRange:nil];
for (i = 0; i < [indexes count]; i++)
{
NSLog(@"REMOVING FROM INDEX: %i", indexBuffer[i]);
[a addObject:[[self arrangedObjects] objectAtIndex:(indexBuffer[i])]];
}
// a = [[self arrangedObjects] objectsAtIndexes:indexes]; //10.4 only
if ([a containsObject:currentEntry]) if ([a containsObject:currentEntry])
{ {
@ -344,8 +177,6 @@
if (shuffle == YES) if (shuffle == YES)
[self resetShuffleList]; [self resetShuffleList];
[a release];
} }
- (void)setSortDescriptors:(NSArray *)sortDescriptors - (void)setSortDescriptors:(NSArray *)sortDescriptors
@ -363,7 +194,7 @@
[super setSortDescriptors:sortDescriptors]; [super setSortDescriptors:sortDescriptors];
} }
- (IBAction)sortByPath:(id)sender - (IBAction)sortByPath
{ {
NSSortDescriptor *s = [[NSSortDescriptor alloc] initWithKey:@"url" ascending:YES selector:@selector(compare:)]; NSSortDescriptor *s = [[NSSortDescriptor alloc] initWithKey:@"url" ascending:YES selector:@selector(compare:)];
@ -378,7 +209,7 @@
[self updateIndexesFromRow:0]; [self updateIndexesFromRow:0];
} }
- (void)randomizeList - (IBAction)randomizeList
{ {
[self setSortDescriptors:nil]; [self setSortDescriptors:nil];
@ -423,9 +254,9 @@
return [[self arrangedObjects] objectAtIndex:i]; return [[self arrangedObjects] objectAtIndex:i];
} }
- (PlaylistEntry *)shuffledEntryAtIndex:(int)i - (PlaylistEntry *)shuffledEntryAtIndex:(int)i
{ {
// NSLog(@"SHUFFLE: %i %i %i %i", i, shuffleIndex, offset, [shuffleList count]);
while (i < 0) while (i < 0)
{ {
if (repeat == YES) if (repeat == YES)
@ -455,67 +286,6 @@
return [shuffleList objectAtIndex:i]; return [shuffleList objectAtIndex:i];
} }
/*- (PlaylistEntry *)entryAtOffset:(int)offset
{
if (shuffle == YES)
{
int i = shuffleIndex;
i += offset;
// NSLog(@"SHUFFLE: %i %i %i %i", i, shuffleIndex, offset, [shuffleList count]);
while (i < 0)
{
if (repeat == YES)
{
[self addShuffledListToFront];
//change i appropriately
i += [[self arrangedObjects] count];
}
else
{
return nil;
}
}
while (i >= [shuffleList count])
{
if (repeat == YES)
{
NSLog(@"Adding shuffled list to back!");
[self addShuffledListToBack];
}
else
{
return nil;
}
}
return [shuffleList objectAtIndex:i];
}
else
{
int i;
i = [currentEntry index];
i += (offset-1);
if (i < 0)
{
if (repeat == YES)
i += [[self arrangedObjects] count];
else
return nil;
}
else if (i >= [[self arrangedObjects] count])
{
if (repeat == YES)
i -= [[self arrangedObjects] count];
else
return nil;
}
return [[self arrangedObjects] objectAtIndex:i];
}
}
*/
- (PlaylistEntry *)getNextEntry:(PlaylistEntry *)pe - (PlaylistEntry *)getNextEntry:(PlaylistEntry *)pe
{ {
if (shuffle == YES) if (shuffle == YES)
@ -673,75 +443,18 @@
{ {
[super setFilterPredicate:filterPredicate]; [super setFilterPredicate:filterPredicate];
int j;
for (j = 0; j < [[self content] count]; j++)
{
PlaylistEntry *p;
p = [[self content] objectAtIndex:j];
[p setIndex:-1];
}
[self updateIndexesFromRow:0]; [self updateIndexesFromRow:0];
} }
- (void)savePlaylist:(NSString *)filename - (IBAction)showEntryInFinder:(id)sender
{
// DBLog(@"SAVING PLAYLIST: %@", filename);
NSString *fileContents;
NSMutableArray *filenames = [NSMutableArray array];
NSEnumerator *enumerator;
PlaylistEntry *entry;
enumerator = [[self content] objectEnumerator];
while (entry = [enumerator nextObject])
{
[filenames addObject:[[entry url] path]];
}
fileContents = [filenames componentsJoinedByString:@"\n"];
[fileContents writeToFile:filename atomically:NO];
}
- (void)loadPlaylist:(NSString *)filename
{
NSString *fileContents;
[self removeObjects:[self arrangedObjects]];
fileContents = [NSString stringWithContentsOfFile:filename];
if (fileContents)
{
NSArray *filenames = [fileContents componentsSeparatedByString:@"\n"];
// DBLog(@"filenames: %@", filenames);
[self addPaths:filenames sort:NO];
}
}
- (NSArray *)acceptablePlaylistTypes
{
return acceptablePlaylistTypes;
}
- (NSString *)playlistFilename
{
return playlistFilename;
}
- (void)setPlaylistFilename:(NSString *)pf
{
[pf retain];
[playlistFilename release];
playlistFilename = pf;
}
- (IBAction)showFileInFinder:(id)sender
{ {
NSWorkspace* ws = [NSWorkspace sharedWorkspace]; NSWorkspace* ws = [NSWorkspace sharedWorkspace];
if ([self selectionIndex] < 0) if ([self selectionIndex] < 0)
return; return;
PlaylistEntry* curr = [self entryAtIndex:[self selectionIndex]]; NSURL *url = [[self entryAtIndex:[self selectionIndex]] url];
[ws selectFile:[[curr url] path] inFileViewerRootedAtPath:[[curr url] path]]; if ([url isFileURL])
[ws selectFile:[url path] inFileViewerRootedAtPath:[url path]];
} }
- (void)handlePlaylistViewHeaderNotification:(NSNotification*)notif - (void)handlePlaylistViewHeaderNotification:(NSNotification*)notif
@ -750,6 +463,9 @@
NSNumber *colIdx = [[notif userInfo] objectForKey:@"column"]; NSNumber *colIdx = [[notif userInfo] objectForKey:@"column"];
NSTableColumn *col = [[tv tableColumns] objectAtIndex:[colIdx intValue]]; NSTableColumn *col = [[tv tableColumns] objectAtIndex:[colIdx intValue]];
//Change to use NSSelectorFromString and NSMethodSignature returnType, see http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/chapter_5_section_7.html for info
//Maybe we can pull the column bindings out somehow, instead of selectorfromstring
// find which function to call on PlaylistEntry* // find which function to call on PlaylistEntry*
SEL sel; SEL sel;
NSString* identifier = [col identifier]; NSString* identifier = [col identifier];

View File

@ -34,16 +34,16 @@
int displayIdx; int displayIdx;
} }
-(void)setIndex:(int)i; - (void)setIndex:(int)i;
-(int)index; - (int)index;
-(void)setShuffleIndex:(int)si; - (void)setShuffleIndex:(int)si;
-(int)shuffleIndex; - (int)shuffleIndex;
-(void)setURL:(NSURL *)u; - (void)setURL:(NSURL *)u;
-(NSURL *)url; - (NSURL *)url;
-(void)setCurrent:(BOOL) b; - (void)setCurrent:(BOOL) b;
-(BOOL)current; - (BOOL)current;
- (void)setArtist:(NSString *)s; - (void)setArtist:(NSString *)s;
- (NSString *)artist; - (NSString *)artist;
@ -57,10 +57,10 @@
- (NSString *)lengthString; - (NSString *)lengthString;
- (void)setLengthString:(double)l; - (void)setLengthString:(double)l;
-(void)setYear:(NSString *)y; - (void)setYear:(NSString *)y;
-(NSString *)year; - (NSString *)year;
-(void)setTrack:(int)y; - (void)setTrack:(int)y;
-(int)track; - (int)track;
- (void)setLength:(double)l; - (void)setLength:(double)l;
- (void)setBitrate:(int) br; - (void)setBitrate:(int) br;
@ -74,9 +74,9 @@
- (int)bitsPerSample; - (int)bitsPerSample;
- (float)sampleRate; - (float)sampleRate;
- (void)readTags; - (void)setMetadata: (NSDictionary *)m;
- (void)readTagsThreaded; - (void)readMetadataThread;
- (void)readInfo; - (void)setProperties: (NSDictionary *)p;
- (void)readInfoThreaded; - (void)readPropertiesThread;
@end @end

View File

@ -164,7 +164,7 @@
return track; return track;
} }
- (void)readInfoThreadedSetVariables:(NSDictionary *)dict - (void)setProperties:(NSDictionary *)dict
{ {
[self setLength: [[dict objectForKey:@"length" ] doubleValue]]; [self setLength: [[dict objectForKey:@"length" ] doubleValue]];
[self setBitrate: [[dict objectForKey:@"bitrate" ] intValue]]; [self setBitrate: [[dict objectForKey:@"bitrate" ] intValue]];
@ -175,11 +175,11 @@
[self setLengthString:[[dict objectForKey:@"length"] doubleValue]]; [self setLengthString:[[dict objectForKey:@"length"] doubleValue]];
} }
- (void)readInfoThreaded - (void)readPropertiesThread
{ {
NSDictionary *properties = [AudioPropertiesReader propertiesForURL:url]; NSDictionary *properties = [AudioPropertiesReader propertiesForURL:url];
[self performSelectorOnMainThread:@selector(readInfoThreadedSetVariables:) withObject:properties waitUntilDone:YES]; [self performSelectorOnMainThread:@selector(setProperties:) withObject:properties waitUntilDone:YES];
} }
- (NSString *)lengthString - (NSString *)lengthString
@ -240,7 +240,7 @@
return sampleRate; return sampleRate;
} }
- (void)readTagsThreadedSetVariables: (NSDictionary *)m - (void)setMetadata: (NSDictionary *)m
{ {
NSString *ti = [m objectForKey:@"title"]; NSString *ti = [m objectForKey:@"title"];
@ -248,7 +248,7 @@
[self setTitle:[[url path] lastPathComponent]]; [self setTitle:[[url path] lastPathComponent]];
} }
else { else {
[self setTitle:[m objectForKey:@"title"]]; [self setTitle:ti];
} }
[self setArtist:[m objectForKey:@"artist"]]; [self setArtist:[m objectForKey:@"artist"]];
@ -258,11 +258,11 @@
[self setTrack:[[m objectForKey:@"track"] intValue]]; [self setTrack:[[m objectForKey:@"track"] intValue]];
} }
- (void)readTagsThreaded - (void)readMetadataThread
{ {
NSDictionary *metadata = [AudioMetadataReader metadataForURL:url]; NSDictionary *metadata = [AudioMetadataReader metadataForURL:url];
[self performSelectorOnMainThread:@selector(readTagsThreadedSetVariables:) withObject:metadata waitUntilDone:YES]; [self performSelectorOnMainThread:@selector(setMetadata:) withObject:metadata waitUntilDone:YES];
} }

View File

@ -16,13 +16,15 @@ typedef enum {
} PlaylistType; } PlaylistType;
@interface PlaylistLoader : NSObject { @interface PlaylistLoader : NSObject {
PlaylistController *playlistController; IBOutlet PlaylistController *playlistController;
PlaylistType currentType; //m3u or pls PlaylistType currentType; //m3u or pls
NSString *currentFile; NSString *currentFile;
} }
//load arrays of urls...
- (void)addURLs:(NSArray *)urls sort:(BOOL)sort;
- (void)insertURLs:(NSArray *)urls atIndex:(int)index sort:(BOOL)sort;
//load playlist auto-determines type to be either pls or m3u. //load playlist auto-determines type to be either pls or m3u.
- (BOOL)load:(NSString *)filename; - (BOOL)load:(NSString *)filename;
@ -37,6 +39,7 @@ typedef enum {
- (BOOL)saveM3u:(NSString *)filename; - (BOOL)saveM3u:(NSString *)filename;
- (BOOL)savePls:(NSString *)filename; - (BOOL)savePls:(NSString *)filename;
- (NSArray *)acceptableFileTypes;
- (NSArray *)acceptablePlaylistTypes; - (NSArray *)acceptablePlaylistTypes;
- (PlaylistType)currentType; - (PlaylistType)currentType;

View File

@ -10,6 +10,8 @@
#import "PlaylistController.h" #import "PlaylistController.h"
#import "PlaylistEntry.h" #import "PlaylistEntry.h"
#import "CogAudio/AudioPlayer.h"
@implementation PlaylistLoader @implementation PlaylistLoader
//load/save playlist auto-determines type to be either pls or m3u. //load/save playlist auto-determines type to be either pls or m3u.
@ -32,7 +34,7 @@
- (BOOL)save - (BOOL)save
{ {
[self save:currentFilename asType:currentType]; return [self save:currentFile asType:currentType];
} }
- (BOOL)save:(NSString *)filename - (BOOL)save:(NSString *)filename
@ -62,20 +64,15 @@
return NO; return NO;
} }
- (BOOL)loadM3u:(NSString *)filename - (NSString *)relativePathFrom:(NSString *)filename toURL:(NSURL *)entryURL
{
}
- (NSString *)pathRelativeTo:(NSString *)filename forEntry:(PlaylistEntry *)pe
{ {
NSString *basePath = [[[filename stringByStandardizingPath] stringByDeletingLastPathComponent] stringByAppendingString:@"/"]; NSString *basePath = [[[filename stringByStandardizingPath] stringByDeletingLastPathComponent] stringByAppendingString:@"/"];
NSURL *entryURL = [pe url]; if ([entryURL isFileURL]) {
if ([[entryURL scheme] isEqualToString:@"file"]) {
//We want relative paths. //We want relative paths.
NSMutableString *entryPath = [[[[entryURL path] stringByStandardizingPath] mutableCopy] autorelease]; NSMutableString *entryPath = [[[[entryURL path] stringByStandardizingPath] mutableCopy] autorelease];
[entryPath replaceOccurrencesOfString:basePath withString:@"" options:(NSAnchoredSearch | NSLiteralSearch | NSCaseInsensitiveSearch) range:NSMakeRange(0, [entryURL length])]; [entryPath replaceOccurrencesOfString:basePath withString:@"" options:(NSAnchoredSearch | NSLiteralSearch | NSCaseInsensitiveSearch) range:NSMakeRange(0, [entryPath length])];
return entryPath; return entryPath;
} }
@ -85,7 +82,56 @@
} }
} }
return paths; - (NSURL *)urlForPath:(NSString *)path relativeTo:(NSString *)baseFilename
{
if ([path hasPrefix:@"/"]) {
return [NSURL fileURLWithPath:path];
}
NSEnumerator *e = [[AudioPlayer schemes] objectEnumerator];
NSString *scheme;
while (scheme = [e nextObject])
{
if ([path hasPrefix:[scheme stringByAppendingString:@"://"]])
{
return [NSURL URLWithString:path];
}
}
NSString *basePath = [[[baseFilename stringByStandardizingPath] stringByDeletingLastPathComponent] stringByAppendingString:@"/"];
return [NSURL fileURLWithPath:[basePath stringByAppendingString:path]];
}
- (BOOL)loadM3u:(NSString *)filename
{
NSLog(@"Loading playlist: %@", filename);
NSError *error = nil;
NSString *contents = [NSString stringWithContentsOfFile:filename encoding:NSUTF8StringEncoding error:&error];
if (error || !contents) {
NSLog(@"Could not open file...%@ %@", contents, error);
return NO;
}
NSString *entry;
NSEnumerator *e = [[contents componentsSeparatedByString:@"\n"] objectEnumerator];
NSMutableArray *entries = [NSMutableArray array];
while (entry = [[e nextObject] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]])
{
if ([entry hasPrefix:@"#"] || [entry isEqualToString:@""]) //Ignore extra info
continue;
//Need to add basePath, and convert to URL
[entries addObject:[self urlForPath:entry relativeTo:filename]];
}
[self addURLs:entries sort:NO];
return YES;
} }
- (BOOL)saveM3u:(NSString *)filename - (BOOL)saveM3u:(NSString *)filename
@ -94,18 +140,23 @@
if (!fileHandle) { if (!fileHandle) {
return NO; return NO;
} }
[fileHandle truncateFileAtOffset:0];
NSLog(@"Saving: %@", filename);
PlaylistEntry *pe; PlaylistEntry *pe;
NSEnumerator *e = [[playlistController content] objectEnumerator]; NSEnumerator *e = [[playlistController content] objectEnumerator];
while (pe = [e nextObject]) while (pe = [e nextObject])
{ {
NSString *path = [self pathRelativeTo:filename forEntry:pe]; NSString *path = [self relativePathFrom:filename toURL:[pe url]];
[fileHandle writeData:[[path stringByAppendingString:@"\n"] dataUsingEncoding:NSUTF8StringEncoding]]; [fileHandle writeData:[[path stringByAppendingString:@"\n"] dataUsingEncoding:NSUTF8StringEncoding]];
} }
[fileHandle closeFile];
[self setCurrentFile:filename]; [self setCurrentFile:filename];
[self setType:kPlaylistM3u]; [self setCurrentType:kPlaylistM3u];
return YES; return YES;
} }
@ -113,34 +164,37 @@
- (BOOL)loadPls:(NSString *)filename - (BOOL)loadPls:(NSString *)filename
{ {
NSError *error; NSError *error;
NSStringEncoding enc; NSString *contents = [NSString stringWithContentsOfFile:filename encoding:NSUTF8StringEncoding error:&error];
NSString *contents = [NSString stringWithContentsOfFile:filename encoding:&enc error:&error];
if (error || !contents) { if (error || !contents) {
return NO; return NO;
} }
NSString *entry; NSString *entry;
NSEnumerator *e = [[contents componentsSeparatedByString:@"\n"] objectEnumerator]; NSEnumerator *e = [[contents componentsSeparatedByString:@"\n"] objectEnumerator];
NSMutableArray *entries = [NSMutableArray array];
while (entry = [e nextObject]) while (entry = [[e nextObject] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]])
{ {
NSScanner *scanner = [[NSScanner alloc] initWithString:entry];
NSString *lhs = nil; NSString *lhs = nil;
if (![scanner scanUpToString:@"=" intoString:&lhs]) //get LHS NSString *rhs = nil;
continue;
if (![scanner scanString:@"=" intoString:nil]) //skip the =
continue;
NSString *nameString = nil;
if (![scanner scanUpToString:@"" intoString:&rhs]) //get RHS
continue;
if (![lhs isEqualToString:@"File"]) if (![scanner scanUpToString:@"=" intoString:&lhs] || // get LHS
![scanner scanString:@"=" intoString:nil] || // skip the =
![scanner scanUpToString:@"" intoString:&rhs] || // get RHS
![lhs isEqualToString:@"File"]) // We only want file entries
{
[scanner release];
continue; continue;
//get url if its a file?
// [entries addObject:nameString];
} }
[playlistController addURLs:urls]; //need to add basepath if its a file, and convert to URL
[entries addObject:[self urlForPath:rhs relativeTo:filename]];
[scanner release];
}
[self addURLs:entries sort:NO];
return YES; return YES;
} }
@ -151,28 +205,188 @@
if (!fileHandle) { if (!fileHandle) {
return NO; return NO;
} }
[fileHandle truncateFileAtOffset:0];
[fileHandle writeData:[[NSString stringWithFormat:@"[playlist]\nnumberOfEntries=%i\n\n",[[playlistController content] count]] dataUsingEncoding:NSUTF8StringEncoding]];
NSEnumerator *e = [[playlistController content] objectEnumerator]; NSEnumerator *e = [[playlistController content] objectEnumerator];
PlaylistEntry *pe; PlaylistEntry *pe;
int i = 1; int i = 1;
while (pe = [e nextObject]) while (pe = [e nextObject])
{ {
NSString *path = [self pathRelativeTo:filename forEntry:pe]; NSString *path = [self relativePathFrom:filename toURL:[pe url]];
NSString *entry = [NSString stringWithFormat:@"File%i=%@\n",i,path]; NSString *entry = [NSString stringWithFormat:@"File%i=%@\n",i,path];
[fileHandle writeData:[entry dataUsingEncoding:NSUTF8StringEncoding]]; [fileHandle writeData:[entry dataUsingEncoding:NSUTF8StringEncoding]];
i++; i++;
} }
[fileHandle writeData:[@"\nVERSION=2" dataUsingEncoding:NSUTF8StringEncoding]];
[fileHandle closeFile];
[self setCurrentFile:filename]; [self setCurrentFile:filename];
[self setType:kPlaylistM3u]; [self setCurrentType:kPlaylistM3u];
return YES; return YES;
} }
- (NSArray *)fileURLsAtPath:(NSString *)path
{
NSFileManager *manager = [NSFileManager defaultManager];
NSMutableArray *urls = [NSMutableArray array];
NSString *subpath;
NSArray *subpaths = [manager subpathsAtPath:path];
NSEnumerator *e = [subpaths objectEnumerator];
while(subpath = [e nextObject])
{
NSString *absoluteSubpath = [NSString pathWithComponents:[NSArray arrayWithObjects:path,subpath,nil]];
BOOL isDir;
if ( [manager fileExistsAtPath:absoluteSubpath isDirectory:&isDir] && isDir == NO)
{
[urls addObject:[NSURL fileURLWithPath:absoluteSubpath]];
}
}
return urls;
}
- (void)insertURLs:(NSArray *)urls atIndex:(int)index sort:(BOOL)sort
{
NSMutableArray *allURLs = [[NSMutableArray alloc] init];
NSMutableArray *validURLs = [[NSMutableArray alloc] init];
NSArray *finalURLs;
if (!urls)
return;
if (index < 0)
index = 0;
NSLog(@"URLS: %@", urls);
NSEnumerator *urlEnumerator = [urls objectEnumerator];
NSURL *url;
while (url = [urlEnumerator nextObject])
{
if ([url isFileURL]) {
BOOL isDir;
if ([[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDir])
{
if (isDir == YES)
{
//Get subpaths
[allURLs addObjectsFromArray:[self fileURLsAtPath:[url path]]];
}
else
{
//File url
[allURLs addObject:url];
}
}
}
else
{
//Non-file URL..
[allURLs addObject:url];
}
}
urlEnumerator = [allURLs objectEnumerator];
while (url = [urlEnumerator nextObject])
{
if (![[AudioPlayer schemes] containsObject:[url scheme]])
continue;
//Need a better way to determine acceptable file types than basing it on extensions.
if (![[self acceptableFileTypes] containsObject:[[[url path] pathExtension] lowercaseString]])
continue;
[validURLs addObject:url];
}
finalURLs = validURLs;
if (sort == YES)
{
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"absoluteString" ascending:YES];
finalURLs = [validURLs sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];
}
//Create actual entries
int i;
NSMutableArray *entries = [NSMutableArray array];
for (i = 0; i < [finalURLs count]; i++)
{
PlaylistEntry *pe = [[PlaylistEntry alloc] init];
NSURL *url = [finalURLs objectAtIndex:i];
[pe setURL:url];
[pe setIndex:index+i];
[pe setTitle:[[url path] lastPathComponent]];
[entries addObject:pe];
[pe release];
}
NSIndexSet *is = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(index, [entries count])];
[playlistController insertObjects:entries atArrangedObjectIndexes:is];
//Select the first entry in the group that was just added
[playlistController setSelectionIndex:index];
//Other thread for reading things...
[NSThread detachNewThreadSelector:@selector(readEntriesInfoThread:) toTarget:self withObject:entries];
[allURLs release];
[validURLs release];
return;
}
- (void)readEntriesInfoThread:(NSArray *)entries
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSEnumerator *e = [entries objectEnumerator];
PlaylistEntry *pe;
while (pe = [e nextObject])
{
[pe readPropertiesThread];
[pe readMetadataThread];
//Hack so the display gets updated
if (pe == [playlistController currentEntry])
[playlistController performSelectorOnMainThread:@selector(setCurrentEntry:) withObject:[playlistController currentEntry] waitUntilDone:YES];
}
[playlistController performSelectorOnMainThread:@selector(updateTotalTime) withObject:nil waitUntilDone:NO];
[pool release];
}
- (void)addURLs:(NSArray *)urls sort:(BOOL)sort
{
[self insertURLs:urls atIndex:[[playlistController content] count] sort:sort];
}
- (NSArray *)acceptableFileTypes
{
return [AudioPlayer fileTypes];
}
- (NSArray *)acceptablePlaylistTypes - (NSArray *)acceptablePlaylistTypes
{ {
return [NSArray arrayWithObject:@"m3u",@"pls",nil]; return [NSArray arrayWithObjects:@"m3u",@"pls",nil];
} }
- (PlaylistType)currentType - (PlaylistType)currentType