cog/Playlist/PlaylistController.m

644 lines
13 KiB
Matlab
Raw Normal View History

2005-06-02 18:16:43 +00:00
//
// PlaylistController.m
// Cog
//
// Created by Vincent Spader on 3/18/05.
2005-07-02 21:02:06 +00:00
// Copyright 2005 Vincent Spader All rights reserved.
2005-06-02 18:16:43 +00:00
//
#import "PlaylistController.h"
#import "PlaylistEntry.h"
2006-01-20 15:22:03 +00:00
#import "Shuffle.h"
2005-06-02 18:16:43 +00:00
@implementation PlaylistController
2006-01-20 15:22:03 +00:00
#define SHUFFLE_HISTORY_SIZE 100
2005-06-02 18:16:43 +00:00
- (id)initWithCoder:(NSCoder *)decoder
{
self = [super initWithCoder:decoder];
if (self)
{
2005-06-06 17:47:29 +00:00
acceptableFileTypes = [[NSArray alloc] initWithObjects:@"shn",@"wv",@"ogg",@"wav",@"mpc",@"flac",@"ape",@"mp3",@"aiff",@"aif",@"aac",nil];
2005-06-02 18:16:43 +00:00
acceptablePlaylistTypes = [[NSArray alloc] initWithObjects:@"playlist",nil];
shuffleList = [[NSMutableArray alloc] init];
// DBLog(@"DAH BUTTER CHORNAR: %@", history);
}
return self;
}
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (int)insertFile:(NSString *)filename atIndex:(int)index
{
2005-06-29 15:28:20 +00:00
if ([acceptableFileTypes containsObject:[[filename pathExtension] lowercaseString]] && [[NSFileManager defaultManager] fileExistsAtPath:filename])
2005-06-02 18:16:43 +00:00
{
PlaylistEntry *pe = [[PlaylistEntry alloc] init];
[pe setFilename:filename]; //Setfilename takes car of opening the soundfile..cheap hack, but works for now
2006-04-15 14:17:46 +00:00
[pe setIndex:index];
2005-06-02 18:16:43 +00:00
[pe readTags];
[pe readInfo];
[self insertObject:pe atArrangedObjectIndex:index];
2006-01-20 15:22:03 +00:00
[pe release];
2005-06-02 18:16:43 +00:00
return 1;
}
return 0;
}
- (int)insertPath:(NSString *)path atIndex:(int)index
{
BOOL isDir;
NSFileManager *manager;
manager = [NSFileManager defaultManager];
DBLog(@"Checking if path is a directory: %@", path);
2005-06-02 18:16:43 +00:00
if ([manager fileExistsAtPath:path isDirectory:&isDir] && isDir == YES)
{
DBLog(@"path is directory");
2005-06-02 18:16:43 +00:00
int count;
int j;
NSArray *subpaths;
count = 0;
subpaths = [manager subpathsAtPath:path];
DBLog(@"Subpaths: %@", subpaths);
2005-06-02 18:16:43 +00:00
for (j = 0; j < [subpaths count]; j++)
{
NSString *filepath;
filepath = [NSString pathWithComponents:[NSArray arrayWithObjects:path,[subpaths objectAtIndex:j],nil]];
count += [self insertFile:filepath atIndex:index+count];
}
return count;
}
else
{
// DBLog(@"Adding fiiiiile: %@", path);
DBLog(@"path is a file");
2005-06-02 18:16:43 +00:00
return [self insertFile:path atIndex:index];
}
}
- (int)insertPaths:(NSArray *)paths atIndex:(int)index sort:(BOOL)sort
{
NSArray *sortedFiles;
int count;
int i;
if (!paths)
return 0;
if (index < 0)
index = 0;
count = 0;
DBLog(@"Sorting paths");
2005-06-02 18:16:43 +00:00
if (sort == YES)
2005-06-29 15:28:20 +00:00
{
2005-06-02 18:16:43 +00:00
sortedFiles = [paths sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
2005-06-29 15:28:20 +00:00
}
2005-06-02 18:16:43 +00:00
else
2005-06-29 15:28:20 +00:00
{
2005-06-02 18:16:43 +00:00
sortedFiles = paths;
2005-06-29 15:28:20 +00:00
}
2005-06-02 18:16:43 +00:00
DBLog(@"Paths sorted: %@", sortedFiles);
2005-06-02 18:16:43 +00:00
for(i=0; i < [sortedFiles count]; i++)
{
int j;
NSString *f;
f = [sortedFiles objectAtIndex:i];
DBLog(@"Inserting path");
2005-06-02 18:16:43 +00:00
j = [self insertPath:f atIndex:(index+count)];
// DBLog(@"Number added: %i", j);
count+=j;
}
if (shuffle == YES)
2006-01-20 15:22:03 +00:00
[self resetShuffleList];
2005-06-02 18:16:43 +00:00
2005-06-30 17:46:07 +00:00
[self setSelectionIndex:index];
2006-04-13 18:40:23 +00:00
[self updateTotalTime];
2005-06-30 17:46:07 +00:00
2005-06-02 18:16:43 +00:00
return count;
}
- (int)addFile:(NSString *)filename
{
return [self insertFile:filename atIndex:[[self arrangedObjects] count]];
}
- (int)addPath:(NSString *)path
{
return [self insertPath:path atIndex:[[self arrangedObjects] count]];
}
- (int)addPaths:(NSArray *)paths sort:(BOOL)sort
{
return [self insertPaths:paths atIndex:[[self arrangedObjects] count] sort:sort];
}
- (NSArray *)acceptableFileTypes
{
return acceptableFileTypes;
}
2006-04-29 00:03:28 +00:00
- (void)tableView:(NSTableView *)tableView
didClickTableColumn:(NSTableColumn *)tableColumn
{
2006-04-30 13:01:33 +00:00
if (shuffle == YES)
[self resetShuffleList];
2006-04-29 00:03:28 +00:00
[self updateIndexesFromRow:0];
}
2005-06-02 18:16:43 +00:00
- (BOOL)tableView:(NSTableView*)tv
acceptDrop:(id <NSDraggingInfo>)info
row:(int)row
dropOperation:(NSTableViewDropOperation)op
{
int i;
2006-04-29 00:03:28 +00:00
NSLog(@"DRAGGING?");
2005-06-02 18:16:43 +00:00
[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");
2005-06-02 18:16:43 +00:00
NSArray *rows = [NSKeyedUnarchiver unarchiveObjectWithData:[[info draggingPasteboard] dataForType: MovedRowsType]];
NSLog(@"Whatever");
2005-06-02 18:16:43 +00:00
NSIndexSet *indexSet = [self indexSetFromRows:rows];
int firstIndex = [indexSet firstIndex];
if (firstIndex > row)
{
i = row;
}
else
{
i = firstIndex;
}
2006-04-29 00:03:28 +00:00
NSLog(@"Updating indexes: %i", i);
2005-06-02 18:16:43 +00:00
[self updateIndexesFromRow:i];
return YES;
}
if (row < 0)
row = 0;
NSArray *files = [[info draggingPasteboard] propertyListForType:NSFilenamesPboardType];
[self insertPaths:files atIndex:row sort:YES];
2005-06-29 22:41:49 +00:00
[self updateIndexesFromRow:row];
2006-04-13 18:40:23 +00:00
[self updateTotalTime];
2005-06-02 18:16:43 +00:00
if (shuffle == YES)
2006-01-20 15:22:03 +00:00
[self resetShuffleList];
2005-06-02 18:16:43 +00:00
return YES;
}
2006-04-13 18:40:23 +00:00
- (void)updateTotalTime
{
double tt=0;
2006-04-29 00:03:28 +00:00
NSEnumerator *enumerator = [[self arrangedObjects] objectEnumerator];
2006-04-13 18:40:23 +00:00
PlaylistEntry* pe;
while (pe = [enumerator nextObject]) {
NSLog(@"Updating :%i", pe);
NSLog(@"Updating :%@", pe);
2006-04-13 18:40:23 +00:00
tt += [pe length];
NSLog(@"UpdateD");
2006-04-13 18:40:23 +00:00
}
int sec = (int)(tt/1000.0);
[self setTotalTimeDisplay:[NSString stringWithFormat:@"%i:%02i",sec/60, sec%60]];
}
- (void)setTotalTimeDisplay:(NSString *)ttd
{
[ttd retain];
[totalTimeDisplay release];
totalTimeDisplay = ttd;
NSLog(@"Displaying: %@", ttd);
}
- (NSString *)totalTimeDisplay;
{
return totalTimeDisplay;
}
2005-06-02 18:16:43 +00:00
- (void)updateIndexesFromRow:(int) row
{
// DBLog(@"UPDATE INDEXES: %i", row);
int j;
2006-04-29 00:03:28 +00:00
for (j = row; j < [[self arrangedObjects] count]; j++)
2005-06-02 18:16:43 +00:00
{
PlaylistEntry *p;
2006-04-29 00:03:28 +00:00
p = [[self arrangedObjects] objectAtIndex:j];
2005-06-02 18:16:43 +00:00
2006-04-15 14:17:46 +00:00
[p setIndex:j];
2005-06-02 18:16:43 +00:00
}
}
- (void)removeObjectsAtArrangedObjectIndexes:(NSIndexSet *)indexes
{
2005-06-06 04:37:35 +00:00
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]);
2005-06-06 04:37:35 +00:00
[a addObject:[[self arrangedObjects] objectAtIndex:(indexBuffer[i])]];
}
// a = [[self arrangedObjects] objectsAtIndexes:indexes]; //10.4 only
2005-06-02 18:16:43 +00:00
if ([a containsObject:currentEntry])
{
[currentEntry setIndex:-1];
}
[super removeObjectsAtArrangedObjectIndexes:indexes];
[self updateIndexesFromRow:[indexes firstIndex]];
2006-04-13 18:40:23 +00:00
[self updateTotalTime];
2005-06-02 18:16:43 +00:00
if (shuffle == YES)
2006-01-20 15:22:03 +00:00
[self resetShuffleList];
2005-06-06 04:37:35 +00:00
[a release];
2005-06-02 18:16:43 +00:00
}
2006-04-30 13:01:33 +00:00
- (void)sortByPath
{
NSSortDescriptor *s = [[NSSortDescriptor alloc] initWithKey:@"filename" ascending:YES selector:@selector(compare:)];
[self setSortDescriptors:[NSArray arrayWithObject:s]];
[s release];
if (shuffle == YES)
[self resetShuffleList];
[self updateIndexesFromRow:0];
}
- (void)randomizeList
{
[self setSortDescriptors:nil];
[self setContent:[Shuffle shuffleList:[self content]]];
if (shuffle == YES)
[self resetShuffleList];
[self updateIndexesFromRow:0];
}
2005-06-02 18:16:43 +00:00
- (IBAction)takeShuffleFromObject:(id)sender
{
if( [sender respondsToSelector: @selector(boolValue)] )
[self setShuffle: [sender boolValue]];
else
[self setShuffle: [sender state]];
}
- (IBAction)takeRepeatFromObject:(id)sender
{
if( [sender respondsToSelector: @selector(boolValue)] )
[self setRepeat: [sender boolValue]];
else
[self setRepeat: [sender state]];
}
2006-04-13 02:51:22 +00:00
- (PlaylistEntry *)entryAtIndex:(int)i
{
2006-04-15 13:51:40 +00:00
if (i < 0)
2006-04-13 02:51:22 +00:00
{
2006-04-15 13:51:40 +00:00
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 *)shuffledEntryAtIndex:(int)i
{
// NSLog(@"SHUFFLE: %i %i %i %i", i, shuffleIndex, offset, [shuffleList count]);
while (i < 0)
{
if (repeat == YES)
{
2006-04-15 13:51:40 +00:00
[self addShuffledListToFront];
//change i appropriately
i += [[self arrangedObjects] count];
}
2006-04-15 13:51:40 +00:00
else
{
2006-04-15 13:51:40 +00:00
return nil;
}
2006-04-13 02:51:22 +00:00
}
2006-04-15 13:51:40 +00:00
while (i >= [shuffleList count])
2006-04-13 02:51:22 +00:00
{
2006-04-15 13:51:40 +00:00
if (repeat == YES)
{
2006-04-15 13:51:40 +00:00
NSLog(@"Adding shuffled list to back!");
[self addShuffledListToBack];
}
2006-04-15 13:51:40 +00:00
else
{
2006-04-15 13:51:40 +00:00
return nil;
}
2006-04-15 13:51:40 +00:00
}
return [shuffleList objectAtIndex:i];
2006-04-13 02:51:22 +00:00
}
/*- (PlaylistEntry *)entryAtOffset:(int)offset
2006-01-20 15:22:03 +00:00
{
if (shuffle == YES)
{
int i = shuffleIndex;
i += offset;
2006-04-05 17:25:51 +00:00
// NSLog(@"SHUFFLE: %i %i %i %i", i, shuffleIndex, offset, [shuffleList count]);
2006-01-20 15:22:03 +00:00
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)
{
2006-04-05 17:25:51 +00:00
NSLog(@"Adding shuffled list to back!");
2006-01-20 15:22:03 +00:00
[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];
}
}
*/
2006-04-15 13:51:40 +00:00
- (PlaylistEntry *)getNextEntry:(PlaylistEntry *)pe
{
if (shuffle == YES)
{
return [self shuffledEntryAtIndex:[pe shuffleIndex] + 1];
}
else
{
return [self entryAtIndex:[pe index] + 1];
}
}
- (PlaylistEntry *)getPrevEntry:(PlaylistEntry *)pe
{
if (shuffle == YES)
{
return [self shuffledEntryAtIndex:[pe shuffleIndex] - 1];
}
else
{
2006-04-15 14:17:46 +00:00
//Fix for removing a track, then pressing prev with repeat turned on
if ([pe index] == -1)
{
return [self entryAtIndex:[pe index]];
}
else
{
return [self entryAtIndex:[pe index] - 1];
}
2006-04-15 13:51:40 +00:00
}
}
2006-01-29 14:57:48 +00:00
- (BOOL)next
2005-06-02 18:16:43 +00:00
{
PlaylistEntry *pe;
2006-04-15 13:51:40 +00:00
pe = [self getNextEntry:[self currentEntry]];
2005-06-02 18:16:43 +00:00
if (pe == nil)
2006-01-29 14:57:48 +00:00
return NO;
2005-06-02 18:16:43 +00:00
2006-01-20 15:22:03 +00:00
[self setCurrentEntry:pe];
2006-01-29 14:57:48 +00:00
return YES;
2005-06-02 18:16:43 +00:00
}
2006-01-29 14:57:48 +00:00
- (BOOL)prev
2005-06-02 18:16:43 +00:00
{
PlaylistEntry *pe;
2006-04-15 13:51:40 +00:00
pe = [self getPrevEntry:[self currentEntry]];
2005-06-02 18:16:43 +00:00
if (pe == nil)
2006-01-29 14:57:48 +00:00
return NO;
2005-06-02 18:16:43 +00:00
2006-01-20 15:22:03 +00:00
[self setCurrentEntry:pe];
2006-01-29 14:57:48 +00:00
return YES;
2005-06-02 18:16:43 +00:00
}
2006-04-14 20:34:14 +00:00
2006-04-15 13:51:40 +00:00
//Need to do...when first generated, need to have current entry at the beginning of the list.
- (void)addShuffledListToFront
2005-06-02 18:16:43 +00:00
{
2006-01-20 15:22:03 +00:00
NSArray *newList = [Shuffle shuffleList:[self arrangedObjects]];
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [newList count])];
2005-06-02 18:16:43 +00:00
2006-04-05 17:25:51 +00:00
[shuffleList insertObjects:newList atIndexes:indexSet];
2006-04-15 13:51:40 +00:00
int i;
for (i = 0; i < [shuffleList count]; i++)
{
[[shuffleList objectAtIndex:i] setShuffleIndex:i];
}
2005-06-02 18:16:43 +00:00
}
2006-04-15 13:51:40 +00:00
- (void)addShuffledListToBack
2005-06-02 18:16:43 +00:00
{
2006-01-20 15:22:03 +00:00
NSArray *newList = [Shuffle shuffleList:[self arrangedObjects]];
2006-04-05 17:25:51 +00:00
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange([shuffleList count], [newList count])];
2006-04-15 13:51:40 +00:00
2006-04-05 17:25:51 +00:00
[shuffleList insertObjects:newList atIndexes:indexSet];
2006-04-15 13:51:40 +00:00
int i;
for (i = ([shuffleList count] - [newList count]); i < [shuffleList count]; i++)
{
[[shuffleList objectAtIndex:i] setShuffleIndex:i];
}
2005-06-02 18:16:43 +00:00
}
2006-01-20 15:22:03 +00:00
- (void)resetShuffleList
2005-06-02 18:16:43 +00:00
{
2006-01-20 15:22:03 +00:00
[shuffleList removeAllObjects];
2006-04-15 13:51:40 +00:00
2006-04-05 17:25:51 +00:00
[self addShuffledListToFront];
2006-04-15 13:51:40 +00:00
2006-04-15 14:17:46 +00:00
if (currentEntry && [currentEntry index] != -1)
2006-04-15 13:51:40 +00:00
{
2006-04-15 14:17:46 +00:00
[shuffleList insertObject:currentEntry atIndex:0];
[currentEntry setShuffleIndex:0];
//Need to rejigger so the current entry is at the start now...
int i;
BOOL found = NO;
for (i = 1; i < [shuffleList count]; i++)
2006-04-15 13:51:40 +00:00
{
2006-04-15 14:17:46 +00:00
if (found == NO && [[shuffleList objectAtIndex:i] filename] == [currentEntry filename])
{
found = YES;
[shuffleList removeObjectAtIndex:i];
}
2006-04-15 13:51:40 +00:00
[[shuffleList objectAtIndex:i] setShuffleIndex:i];
2006-04-15 14:17:46 +00:00
}
2006-04-15 13:51:40 +00:00
}
2005-06-02 18:16:43 +00:00
}
- (id)currentEntry
{
return currentEntry;
}
- (void)setCurrentEntry:(id)pe
{
[currentEntry setCurrent:NO];
[pe setCurrent:YES];
2005-07-02 21:02:06 +00:00
[tableView scrollRowToVisible:([(PlaylistEntry *)pe index]-1)];
2005-06-02 18:16:43 +00:00
[pe retain];
[currentEntry release];
currentEntry = pe;
}
- (void)setShuffle:(BOOL)s
{
shuffle = s;
if (shuffle == YES)
2006-01-20 15:22:03 +00:00
[self resetShuffleList];
2005-06-02 18:16:43 +00:00
}
- (BOOL)shuffle
{
return shuffle;
}
- (void)setRepeat:(BOOL)r
{
repeat = r;
}
- (BOOL)repeat
{
return repeat;
}
- (void)savePlaylist:(NSString *)filename
{
// DBLog(@"SAVING PLAYLIST: %@", filename);
NSString *fileContents;
NSMutableArray *filenames = [NSMutableArray array];
NSEnumerator *enumerator;
PlaylistEntry *entry;
2006-04-30 14:05:07 +00:00
enumerator = [[self content] objectEnumerator];
2005-06-02 18:16:43 +00:00
while (entry = [enumerator nextObject])
{
[filenames addObject:[entry filename]];
}
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;
}
@end