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

View File

@ -1,5 +1,13 @@
#import "AppController.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
@ -124,7 +132,7 @@ increase/decrease as long as the user holds the left/right, plus/minus button */
[p setCanChooseDirectories: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];
/* 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)
{
[playlistController addPaths:[panel filenames] sort:YES];
[playlistLoader addURLs:[panel URLs] sort:YES];
}
// [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";
[playlistController loadPlaylist:[filename stringByExpandingTildeInPath]];
NSString *filename = @"~/Library/Application Support/Cog/Default.m3u";
[playlistLoader loadM3u:[filename stringByExpandingTildeInPath]];
}
- (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];
}
NSString *fileName = @"Default.playlist";
NSString *fileName = @"Default.m3u";
[playlistController savePlaylist:[folder stringByAppendingPathComponent: fileName]];
[playlistLoader saveM3u:[folder stringByAppendingPathComponent: fileName]];
}
- (IBAction)savePlaylist:(id)sender
{
if ([playlistController playlistFilename] == nil)
[self savePlaylistAs:sender];
[playlistController savePlaylist:[playlistController playlistFilename]];
[playlistLoader save];
}
- (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 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]];
[playlistController savePlaylist:[p filename]];
[playlistLoader save:[p filename]];
}
}
@ -295,11 +298,9 @@ increase/decrease as long as the user holds the left/right, plus/minus button */
[p setCanChooseDirectories:NO];
[p setAllowsMultipleSelection:NO];
if ([p runModalForTypes:[playlistController acceptablePlaylistTypes]] == NSOKButton)
if ([p runModalForTypes:[playlistLoader acceptablePlaylistTypes]] == NSOKButton)
{
[playlistController setPlaylistFilename:[p filename]];
[playlistController loadPlaylist:[p filename]];
[playlistLoader load:[p filename]];
}
[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
{
DBLog(@"Adding path: %@", filename);
[playlistController addPaths:[NSArray arrayWithObject:filename] sort:NO];
[playlistLoader addURLs:[NSArray arrayWithObject:[NSURL fileURLWithPath:filename]] sort:NO];
return YES;
}
- (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];
}

View File

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

View File

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

View File

@ -11,6 +11,8 @@
170680630B950158006BA573 /* Growl.framework in Frameworks */ = {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 */; };
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 */; };
175D8B670B9A5153005B3CD9 /* CogAudio.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 175D8B630B9A514C005B3CD9 /* CogAudio.framework */; };
1766C6930B911DF1004A7AE4 /* AudioScrobbler.m in Sources */ = {isa = PBXBuildFile; fileRef = 1766C68F0B911DF1004A7AE4 /* AudioScrobbler.m */; };
@ -138,6 +140,7 @@
175D8B670B9A5153005B3CD9 /* CogAudio.framework in CopyFiles */,
170680840B950164006BA573 /* Growl.framework in CopyFiles */,
17F94CCD0B8D090800A34E87 /* Sparkle.framework in CopyFiles */,
1755E1F80BA0D2B600CA3560 /* PlaylistLoader.h in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -150,6 +153,8 @@
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>"; };
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>"; };
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>"; };
@ -613,6 +618,8 @@
children = (
8E1296D80A2BA9CE00443124 /* PlaylistHeaderView.h */,
8E1296D90A2BA9CE00443124 /* PlaylistHeaderView.m */,
1755E1F60BA0D2B600CA3560 /* PlaylistLoader.h */,
1755E1F70BA0D2B600CA3560 /* PlaylistLoader.m */,
8E75752B09F31D5A0080F1EE /* DNDArrayController.h */,
8E75752C09F31D5A0080F1EE /* DNDArrayController.m */,
8E75752D09F31D5A0080F1EE /* PlaylistController.h */,
@ -638,7 +645,6 @@
8EFFCD410AA093AF00C458A5 /* FileDrawer */ = {
isa = PBXGroup;
children = (
8EFFCD540AA093AF00C458A5 /* UKKQueue */,
8EFFCD440AA093AF00C458A5 /* FileIconCell.h */,
8EFFCD450AA093AF00C458A5 /* FileIconCell.m */,
8EFFCD500AA093AF00C458A5 /* PathIcon.h */,
@ -661,13 +667,6 @@
path = FileDrawer;
sourceTree = "<group>";
};
8EFFCD540AA093AF00C458A5 /* UKKQueue */ = {
isa = PBXGroup;
children = (
);
path = UKKQueue;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -796,6 +795,7 @@
1770429E0B8BC53600B86321 /* PlaybackController.m in Sources */,
1766C6930B911DF1004A7AE4 /* AudioScrobbler.m in Sources */,
1766C6950B911DF1004A7AE4 /* AudioScrobblerClient.m in Sources */,
1755E1F90BA0D2B600CA3560 /* PlaylistLoader.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -836,21 +836,9 @@
buildSettings = {
COPY_PHASE_STRIP = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(SRCROOT)/Frameworks/CogAudio/build/Release",
"$(SRCROOT)/Audio/build/Release",
"$(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_ENABLE_FIX_AND_CONTINUE = YES;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
@ -881,21 +869,9 @@
i386,
);
FRAMEWORK_SEARCH_PATHS = (
"$(SRCROOT)/Frameworks/CogAudio/build/Release",
"$(SRCROOT)/Audio/build/Release",
"$(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_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_MODEL_TUNING = G5;

View File

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

View File

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

Binary file not shown.

View File

@ -23,7 +23,7 @@
- (void)alertDidEnd:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
if (contextInfo == YES)
if ([(NSNumber *)contextInfo boolValue]== YES)
{
[feedbackWindow close];
}
@ -39,7 +39,7 @@
[alert setMessageText:NSLocalizedString(@"FeedbackFailedMessageText", @"")];
[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
@ -52,7 +52,7 @@
[alert setMessageText:NSLocalizedString(@"FeedbackSuccessMessageText", @"")];
[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 "FileTreeWatcher.h"
#import "PlaylistController.h"
@class FileTreeWatcher;
@class PlaylistLoader;
@interface FileTreeController : NSTreeController
{
IBOutlet PlaylistController *playlistController;
IBOutlet PlaylistLoader *playlistLoader;
NSString *rootPath;
@ -21,5 +22,6 @@
- (id)rootPath;
- (void)setRootPath:(id)r;
- (void) refreshRoot;
@end

View File

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

View File

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

View File

@ -11,15 +11,8 @@ NSString *iTunesDropType = @"CorePasteboardFlavorType 0x6974756E";
- (void)awakeFromNib
{
// register for drag and drop
NSLog(@"AWOKE");
[tableView registerForDraggedTypes:[NSArray arrayWithObjects:MovedRowsType, NSFilenamesPboardType,
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
toPasteboard:(NSPasteboard*)pboard
{
NSLog(@"WRITE ROWS");
NSData *data;
data = [NSKeyedArchiver archivedDataWithRootObject:rows];
@ -66,11 +57,10 @@ NSString *iTunesDropType = @"CorePasteboardFlavorType 0x6974756E";
{
row = 0;
}
NSLog(@"ACCEPTATING");
// if drag source is self, it's a move
if ([info draggingSource] == tableView)
{
// DBLog(@"ACCEPTATED");
NSArray *rows = [NSKeyedUnarchiver unarchiveObjectWithData:[[info draggingPasteboard] dataForType: MovedRowsType]];
NSIndexSet *indexSet = [self indexSetFromRows:rows];

View File

@ -8,13 +8,13 @@
#import <Cocoa/Cocoa.h>
#import "DNDArrayController.h"
#import "PlaylistEntry.h"
@class PlaylistLoader;
@class PlaylistEntry;
@interface PlaylistController : DNDArrayController {
NSArray *acceptableFileTypes;
NSArray *acceptablePlaylistTypes;
NSString *playlistFilename;
IBOutlet PlaylistLoader *playlistLoader;
NSString *totalTimeDisplay;
NSMutableArray *shuffleList;
@ -27,22 +27,12 @@
int selectedRow;
}
//All these return the number of things actually added
//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)updateTotalTime;
//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;
- (BOOL)shuffle;
- (void)setRepeat:(BOOL)r;
@ -51,7 +41,10 @@
- (IBAction)takeShuffleFromObject:(id)sender;
- (IBAction)takeRepeatFromObject:(id)sender;
- (IBAction)sortByPath:(id)sender;
- (IBAction)sortByPath;
- (IBAction)randomizeList;
- (IBAction)showEntryInFinder:(id)sender;
- (void)setTotalTimeDisplay:(NSString *)ttd;
- (NSString *)totalTimeDisplay;
@ -63,21 +56,10 @@
- (BOOL)next;
- (BOOL)prev;
- (PlaylistEntry *)entryAtIndex:(int)i;
- (void)addShuffledListToBack;
- (void)addShuffledListToFront;
- (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;
@end

View File

@ -6,6 +6,7 @@
// Copyright 2005 Vincent Spader All rights reserved.
//
#import "PlaylistLoader.h"
#import "PlaylistController.h"
#import "PlaylistEntry.h"
#import "Shuffle.h"
@ -22,11 +23,7 @@
if (self)
{
acceptableFileTypes = [[AudioPlayer fileTypes] retain];
acceptablePlaylistTypes = [[NSArray alloc] initWithObjects:@"playlist",nil];
shuffleList = [[NSMutableArray alloc] init];
// DBLog(@"DAH BUTTER CHORNAR: %@", history);
}
return self;
@ -40,150 +37,6 @@
[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
didClickTableColumn:(NSTableColumn *)tableColumn
@ -199,27 +52,20 @@
row:(int)row
dropOperation:(NSTableViewDropOperation)op
{
int i;
NSLog(@"DROPPED");
[super tableView:tv acceptDrop:info row:row dropOperation:op];
if ([info draggingSource] == tableView)
{
//DNDArrayController handles moving...still need to update the uhm...indices
NSLog(@"Archive stuff");
//DNDArrayController handles moving...still need to update the indexes
int i;
NSArray *rows = [NSKeyedUnarchiver unarchiveObjectWithData:[[info draggingPasteboard] dataForType: MovedRowsType]];
NSLog(@"Whatever");
NSIndexSet *indexSet = [self indexSetFromRows:rows];
int firstIndex = [indexSet firstIndex];
int firstIndex = [[self indexSetFromRows:rows] firstIndex];
if (firstIndex > row)
{
i = row;
}
else
{
i = firstIndex;
}
NSLog(@"Updating indexes: %i", i);
[self updateIndexesFromRow:i];
return YES;
@ -235,10 +81,18 @@
// Get files from a normal file drop (such as from Finder)
if ([bestType isEqualToString:NSFilenamesPboardType]) {
NSArray *files = [[info draggingPasteboard] propertyListForType:NSFilenamesPboardType];
NSMutableArray *urls = [[NSMutableArray alloc] init];
NSEnumerator *e = [[[info draggingPasteboard] propertyListForType:NSFilenamesPboardType] objectEnumerator];
NSString *file;
while (file = [e nextObject])
{
[urls addObject:[NSURL fileURLWithPath:file]];
}
NSLog(@"INSERTING PATHS: %@", files);
[self insertPaths:files atIndex:row sort:YES];
[playlistLoader insertURLs:urls atIndex:row sort:YES];
[urls release];
}
// Get files from an iTunes drop
@ -246,26 +100,19 @@
NSDictionary *iTunesDict = [pboard propertyListForType:iTunesDropType];
NSDictionary *tracks = [iTunesDict valueForKey:@"Tracks"];
// Convert the iTunes URLs to filenames
NSMutableArray *files = [[NSMutableArray alloc] init];
// Convert the iTunes URLs to URLs....MWAHAHAH!
NSMutableArray *urls = [[NSMutableArray alloc] init];
NSEnumerator *e = [[tracks allValues] objectEnumerator];
NSDictionary *trackInfo;
NSURL *url;
while (trackInfo = [e nextObject]) {
url = [[NSURL alloc] initWithString:[trackInfo valueForKey:@"Location"]];
if ([url isFileURL]) {
[files addObject:[url path]];
}
[url release];
[urls addObject:[NSURL URLWithString:[trackInfo valueForKey:@"Location"]]];
}
NSLog(@"INSERTING ITUNES PATHS: %@", files);
[self insertPaths:files atIndex:row sort:YES];
[files release];
[playlistLoader insertURLs:urls atIndex:row sort:YES];
[urls release];
}
NSLog(@"UPDATING");
[self updateIndexesFromRow:row];
[self updateTotalTime];
@ -295,7 +142,6 @@
[ttd retain];
[totalTimeDisplay release];
totalTimeDisplay = ttd;
NSLog(@"Displaying: %@", ttd);
}
- (NSString *)totalTimeDisplay;
@ -305,7 +151,6 @@
- (void)updateIndexesFromRow:(int) row
{
// DBLog(@"UPDATE INDEXES: %i", row);
int j;
for (j = row; j < [[self arrangedObjects] count]; j++)
{
@ -318,20 +163,8 @@
- (void)removeObjectsAtArrangedObjectIndexes:(NSIndexSet *)indexes
{
unsigned int *indexBuffer;
NSMutableArray *a = [[NSMutableArray alloc] init];
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
NSLog(@"REMOVING");
NSArray *a = [[self arrangedObjects] objectsAtIndexes:indexes]; //Screw 10.3
if ([a containsObject:currentEntry])
{
@ -344,8 +177,6 @@
if (shuffle == YES)
[self resetShuffleList];
[a release];
}
- (void)setSortDescriptors:(NSArray *)sortDescriptors
@ -363,7 +194,7 @@
[super setSortDescriptors:sortDescriptors];
}
- (IBAction)sortByPath:(id)sender
- (IBAction)sortByPath
{
NSSortDescriptor *s = [[NSSortDescriptor alloc] initWithKey:@"url" ascending:YES selector:@selector(compare:)];
@ -378,7 +209,7 @@
[self updateIndexesFromRow:0];
}
- (void)randomizeList
- (IBAction)randomizeList
{
[self setSortDescriptors:nil];
@ -423,9 +254,9 @@
return [[self arrangedObjects] objectAtIndex:i];
}
- (PlaylistEntry *)shuffledEntryAtIndex:(int)i
{
// NSLog(@"SHUFFLE: %i %i %i %i", i, shuffleIndex, offset, [shuffleList count]);
while (i < 0)
{
if (repeat == YES)
@ -455,67 +286,6 @@
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
{
if (shuffle == YES)
@ -673,75 +443,18 @@
{
[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];
}
- (void)savePlaylist:(NSString *)filename
{
// 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
- (IBAction)showEntryInFinder:(id)sender
{
NSWorkspace* ws = [NSWorkspace sharedWorkspace];
if ([self selectionIndex] < 0)
return;
PlaylistEntry* curr = [self entryAtIndex:[self selectionIndex]];
[ws selectFile:[[curr url] path] inFileViewerRootedAtPath:[[curr url] path]];
NSURL *url = [[self entryAtIndex:[self selectionIndex]] url];
if ([url isFileURL])
[ws selectFile:[url path] inFileViewerRootedAtPath:[url path]];
}
- (void)handlePlaylistViewHeaderNotification:(NSNotification*)notif
@ -750,6 +463,9 @@
NSNumber *colIdx = [[notif userInfo] objectForKey:@"column"];
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*
SEL sel;
NSString* identifier = [col identifier];

View File

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

View File

@ -164,7 +164,7 @@
return track;
}
- (void)readInfoThreadedSetVariables:(NSDictionary *)dict
- (void)setProperties:(NSDictionary *)dict
{
[self setLength: [[dict objectForKey:@"length" ] doubleValue]];
[self setBitrate: [[dict objectForKey:@"bitrate" ] intValue]];
@ -175,11 +175,11 @@
[self setLengthString:[[dict objectForKey:@"length"] doubleValue]];
}
- (void)readInfoThreaded
- (void)readPropertiesThread
{
NSDictionary *properties = [AudioPropertiesReader propertiesForURL:url];
[self performSelectorOnMainThread:@selector(readInfoThreadedSetVariables:) withObject:properties waitUntilDone:YES];
[self performSelectorOnMainThread:@selector(setProperties:) withObject:properties waitUntilDone:YES];
}
- (NSString *)lengthString
@ -240,7 +240,7 @@
return sampleRate;
}
- (void)readTagsThreadedSetVariables: (NSDictionary *)m
- (void)setMetadata: (NSDictionary *)m
{
NSString *ti = [m objectForKey:@"title"];
@ -248,7 +248,7 @@
[self setTitle:[[url path] lastPathComponent]];
}
else {
[self setTitle:[m objectForKey:@"title"]];
[self setTitle:ti];
}
[self setArtist:[m objectForKey:@"artist"]];
@ -258,11 +258,11 @@
[self setTrack:[[m objectForKey:@"track"] intValue]];
}
- (void)readTagsThreaded
- (void)readMetadataThread
{
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;
@interface PlaylistLoader : NSObject {
PlaylistController *playlistController;
IBOutlet PlaylistController *playlistController;
PlaylistType currentType; //m3u or pls
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.
- (BOOL)load:(NSString *)filename;
@ -37,6 +39,7 @@ typedef enum {
- (BOOL)saveM3u:(NSString *)filename;
- (BOOL)savePls:(NSString *)filename;
- (NSArray *)acceptableFileTypes;
- (NSArray *)acceptablePlaylistTypes;
- (PlaylistType)currentType;

View File

@ -10,6 +10,8 @@
#import "PlaylistController.h"
#import "PlaylistEntry.h"
#import "CogAudio/AudioPlayer.h"
@implementation PlaylistLoader
//load/save playlist auto-determines type to be either pls or m3u.
@ -32,7 +34,7 @@
- (BOOL)save
{
[self save:currentFilename asType:currentType];
return [self save:currentFile asType:currentType];
}
- (BOOL)save:(NSString *)filename
@ -62,20 +64,15 @@
return NO;
}
- (BOOL)loadM3u:(NSString *)filename
{
}
- (NSString *)pathRelativeTo:(NSString *)filename forEntry:(PlaylistEntry *)pe
- (NSString *)relativePathFrom:(NSString *)filename toURL:(NSURL *)entryURL
{
NSString *basePath = [[[filename stringByStandardizingPath] stringByDeletingLastPathComponent] stringByAppendingString:@"/"];
NSURL *entryURL = [pe url];
if ([[entryURL scheme] isEqualToString:@"file"]) {
if ([entryURL isFileURL]) {
//We want relative paths.
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;
}
@ -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
@ -94,18 +140,23 @@
if (!fileHandle) {
return NO;
}
[fileHandle truncateFileAtOffset:0];
NSLog(@"Saving: %@", filename);
PlaylistEntry *pe;
NSEnumerator *e = [[playlistController content] objectEnumerator];
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 closeFile];
[self setCurrentFile:filename];
[self setType:kPlaylistM3u];
[self setCurrentType:kPlaylistM3u];
return YES;
}
@ -113,34 +164,37 @@
- (BOOL)loadPls:(NSString *)filename
{
NSError *error;
NSStringEncoding enc;
NSString *contents = [NSString stringWithContentsOfFile:filename encoding:&enc error:&error];
NSString *contents = [NSString stringWithContentsOfFile:filename encoding:NSUTF8StringEncoding error:&error];
if (error || !contents) {
return NO;
}
NSString *entry;
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;
if (![scanner scanUpToString:@"=" intoString:&lhs]) //get LHS
continue;
if (![scanner scanString:@"=" intoString:nil]) //skip the =
continue;
NSString *nameString = nil;
if (![scanner scanUpToString:@"" intoString:&rhs]) //get RHS
continue;
NSString *rhs = nil;
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;
//get url if its a file?
// [entries addObject:nameString];
}
//need to add basepath if its a file, and convert to URL
[entries addObject:[self urlForPath:rhs relativeTo:filename]];
[scanner release];
}
[playlistController addURLs:urls];
[self addURLs:entries sort:NO];
return YES;
}
@ -151,28 +205,188 @@
if (!fileHandle) {
return NO;
}
[fileHandle truncateFileAtOffset:0];
[fileHandle writeData:[[NSString stringWithFormat:@"[playlist]\nnumberOfEntries=%i\n\n",[[playlistController content] count]] dataUsingEncoding:NSUTF8StringEncoding]];
NSEnumerator *e = [[playlistController content] objectEnumerator];
PlaylistEntry *pe;
int i = 1;
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];
[fileHandle writeData:[entry dataUsingEncoding:NSUTF8StringEncoding]];
i++;
}
[fileHandle writeData:[@"\nVERSION=2" dataUsingEncoding:NSUTF8StringEncoding]];
[fileHandle closeFile];
[self setCurrentFile:filename];
[self setType:kPlaylistM3u];
[self setCurrentType:kPlaylistM3u];
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
{
return [NSArray arrayWithObject:@"m3u",@"pls",nil];
return [NSArray arrayWithObjects:@"m3u",@"pls",nil];
}
- (PlaylistType)currentType