Basic cue sheet support working. Bug city.
parent
4935c5ddfc
commit
50395e6e72
|
@ -204,11 +204,11 @@ static PluginController *sharedPluginController = nil;
|
|||
|
||||
- (void)printPluginInfo
|
||||
{
|
||||
//NSLog(@"Sources: %@", sources);
|
||||
//NSLog(@"Containers: %@", containers);
|
||||
//NSLog(@"Decoders: %@", decoders);
|
||||
//NSLog(@"Metadata Readers: %@", metadataReaders);
|
||||
//NSLog(@"Properties Readers: %@", propertiesReaders);
|
||||
NSLog(@"Sources: %@", sources);
|
||||
NSLog(@"Containers: %@", containers);
|
||||
NSLog(@"Decoders: %@", decoders);
|
||||
NSLog(@"Metadata Readers: %@", metadataReaders);
|
||||
NSLog(@"Properties Readers: %@", propertiesReaders);
|
||||
}
|
||||
|
||||
- (NSDictionary *)sources
|
||||
|
|
|
@ -88,6 +88,7 @@
|
|||
17C809E60C3BD487005707C4 /* CoreAudio.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17C809E30C3BD46D005707C4 /* CoreAudio.bundle */; };
|
||||
17E41E070C130DFF00AC744D /* Credits.html in Resources */ = {isa = PBXBuildFile; fileRef = 17E41E060C130DFF00AC744D /* Credits.html */; };
|
||||
17E41E230C130EE200AC744D /* Help in Resources */ = {isa = PBXBuildFile; fileRef = 17E41E220C130EE200AC744D /* Help */; };
|
||||
17F3BB890CBC565900864489 /* CueSheet.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17F3BB880CBC565100864489 /* CueSheet.bundle */; };
|
||||
17F561400C3BD4F30019975C /* CogAudio.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17F561330C3BD4DC0019975C /* CogAudio.framework */; };
|
||||
17F562390C3BD91B0019975C /* General.preferencePane in Resources */ = {isa = PBXBuildFile; fileRef = 17F5622E0C3BD8FB0019975C /* General.preferencePane */; };
|
||||
17F94CC20B8D08FB00A34E87 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17F94CC10B8D08FB00A34E87 /* Sparkle.framework */; };
|
||||
|
@ -279,6 +280,20 @@
|
|||
remoteGlobalIDString = 8D5B49AC048680CD000E48DA;
|
||||
remoteInfo = CoreAudio;
|
||||
};
|
||||
17F3BB870CBC565100864489 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 17F3BB830CBC565100864489 /* CueSheet.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 8D5B49B6048680CD000E48DA /* CueSheet.bundle */;
|
||||
remoteInfo = CueSheet;
|
||||
};
|
||||
17F3BB8A0CBC566200864489 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 17F3BB830CBC565100864489 /* CueSheet.xcodeproj */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 8D5B49AC048680CD000E48DA /* CueSheet */;
|
||||
remoteInfo = CueSheet;
|
||||
};
|
||||
17F561320C3BD4DC0019975C /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 17F5612A0C3BD4DC0019975C /* CogAudio.xcodeproj */;
|
||||
|
@ -311,28 +326,28 @@
|
|||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 8E8D40820CBB036600135C1B /* M3u.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 8D5B49B6048680CD000E48DA /* M3u.bundle */;
|
||||
remoteGlobalIDString = 8D5B49B6048680CD000E48DA;
|
||||
remoteInfo = M3u;
|
||||
};
|
||||
8E8D40920CBB03AF00135C1B /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 8E8D40820CBB036600135C1B /* M3u.xcodeproj */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 8D5B49AC048680CD000E48DA /* M3u */;
|
||||
remoteGlobalIDString = 8D5B49AC048680CD000E48DA;
|
||||
remoteInfo = M3u;
|
||||
};
|
||||
8E8D41C60CBB0DA000135C1B /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 8E8D41C20CBB0DA000135C1B /* Pls.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 8D5B49B6048680CD000E48DA /* Pls.bundle */;
|
||||
remoteGlobalIDString = 8D5B49B6048680CD000E48DA;
|
||||
remoteInfo = Pls;
|
||||
};
|
||||
8E8D41CB0CBB0DD200135C1B /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 8E8D41C20CBB0DA000135C1B /* Pls.xcodeproj */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 8D5B49AC048680CD000E48DA /* Pls */;
|
||||
remoteGlobalIDString = 8D5B49AC048680CD000E48DA;
|
||||
remoteInfo = Pls;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
@ -344,6 +359,7 @@
|
|||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
17F3BB890CBC565900864489 /* CueSheet.bundle in CopyFiles */,
|
||||
8E8D41C80CBB0DA900135C1B /* Pls.bundle in CopyFiles */,
|
||||
8E8D40880CBB038E00135C1B /* M3u.bundle in CopyFiles */,
|
||||
17C809E60C3BD487005707C4 /* CoreAudio.bundle in CopyFiles */,
|
||||
|
@ -507,6 +523,7 @@
|
|||
17E41C470C1304BB00AC744D /* Swedish */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = Swedish; path = Swedish.lproj/MainMenu.nib; sourceTree = "<group>"; };
|
||||
17E41C480C1304C700AC744D /* Swedish */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = Swedish; path = Swedish.lproj/OpenURLPanel.nib; sourceTree = "<group>"; };
|
||||
17E41C490C1304D200AC744D /* Swedish */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Swedish; path = Swedish.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
17F3BB830CBC565100864489 /* CueSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CueSheet.xcodeproj; path = Plugins/CueSheet/CueSheet.xcodeproj; sourceTree = "<group>"; };
|
||||
17F5612A0C3BD4DC0019975C /* CogAudio.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CogAudio.xcodeproj; path = Audio/CogAudio.xcodeproj; sourceTree = "<group>"; };
|
||||
17F562260C3BD8FB0019975C /* General.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = General.xcodeproj; path = Preferences/General/General.xcodeproj; sourceTree = "<group>"; };
|
||||
17F94CC10B8D08FB00A34E87 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = ThirdParty/Frameworks/Sparkle.framework; sourceTree = "<group>"; };
|
||||
|
@ -791,6 +808,7 @@
|
|||
17B619FF0B909ED400BC003F /* PlugIns */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
17F3BB830CBC565100864489 /* CueSheet.xcodeproj */,
|
||||
8E8D41C20CBB0DA000135C1B /* Pls.xcodeproj */,
|
||||
8E8D40820CBB036600135C1B /* M3u.xcodeproj */,
|
||||
17C808C00C3BD1DD005707C4 /* WavPack.xcodeproj */,
|
||||
|
@ -896,6 +914,14 @@
|
|||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
17F3BB840CBC565100864489 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
17F3BB880CBC565100864489 /* CueSheet.bundle */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
17F5612B0C3BD4DC0019975C /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1117,6 +1143,7 @@
|
|||
17F5623B0C3BD9280019975C /* PBXTargetDependency */,
|
||||
8E8D40930CBB03AF00135C1B /* PBXTargetDependency */,
|
||||
8E8D41CC0CBB0DD200135C1B /* PBXTargetDependency */,
|
||||
17F3BB8B0CBC566200864489 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Cog;
|
||||
productInstallPath = "$(HOME)/Applications";
|
||||
|
@ -1151,6 +1178,10 @@
|
|||
ProductGroup = 17C809DF0C3BD46D005707C4 /* Products */;
|
||||
ProjectRef = 17C808660C3BD0F8005707C4 /* CoreAudio.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 17F3BB840CBC565100864489 /* Products */;
|
||||
ProjectRef = 17F3BB830CBC565100864489 /* CueSheet.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 17C808720C3BD167005707C4 /* Products */;
|
||||
ProjectRef = 17C808710C3BD167005707C4 /* FileSource.xcodeproj */;
|
||||
|
@ -1288,6 +1319,13 @@
|
|||
remoteRef = 17C809E20C3BD46D005707C4 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
17F3BB880CBC565100864489 /* CueSheet.bundle */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.cfbundle;
|
||||
path = CueSheet.bundle;
|
||||
remoteRef = 17F3BB870CBC565100864489 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
17F561330C3BD4DC0019975C /* CogAudio.framework */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.framework;
|
||||
|
@ -1483,6 +1521,11 @@
|
|||
name = CoreAudio;
|
||||
targetProxy = 17C809E40C3BD47C005707C4 /* PBXContainerItemProxy */;
|
||||
};
|
||||
17F3BB8B0CBC566200864489 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = CueSheet;
|
||||
targetProxy = 17F3BB8A0CBC566200864489 /* PBXContainerItemProxy */;
|
||||
};
|
||||
17F5613F0C3BD4E90019975C /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = CogAudio;
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
- (id)initWithFile:(NSString *)filename;
|
||||
|
||||
- (void)parseFile:(NSString *)filename;
|
||||
|
||||
- (NSArray *)tracks;
|
||||
|
||||
- (CueSheetTrack *)track:(NSString *)fragment;
|
||||
|
|
|
@ -16,27 +16,146 @@
|
|||
return [[[CueSheet alloc] initWithFile:filename] autorelease];
|
||||
}
|
||||
|
||||
- (NSURL *)urlForPath:(NSString *)path relativeTo:(NSString *)baseFilename
|
||||
{
|
||||
if ([path hasPrefix:@"/"]) {
|
||||
return [NSURL fileURLWithPath:path];
|
||||
}
|
||||
|
||||
NSRange foundRange = [path rangeOfString:@"://"];
|
||||
if (foundRange.location != NSNotFound)
|
||||
{
|
||||
return [NSURL URLWithString:path];
|
||||
}
|
||||
|
||||
NSString *basePath = [[[baseFilename stringByStandardizingPath] stringByDeletingLastPathComponent] stringByAppendingString:@"/"];
|
||||
NSMutableString *unixPath = [path mutableCopy];
|
||||
|
||||
//Only relative paths would have windows backslashes.
|
||||
[unixPath replaceOccurrencesOfString:@"\\" withString:@"/" options:0 range:NSMakeRange(0, [unixPath length])];
|
||||
|
||||
return [NSURL fileURLWithPath:[basePath stringByAppendingString:[unixPath autorelease]]];
|
||||
}
|
||||
|
||||
|
||||
- (void)parseFile:(NSString *)filename
|
||||
{
|
||||
NSError *error = nil;
|
||||
NSString *contents = [NSString stringWithContentsOfFile:filename encoding:NSUTF8StringEncoding error:&error];
|
||||
if (error || !contents) {
|
||||
NSLog(@"Could not open file...%@ %@ %@", filename, contents, error);
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableArray *entries = [[NSMutableArray alloc] init];
|
||||
|
||||
NSString *track = nil;
|
||||
NSString *path = nil;
|
||||
BOOL trackAdded = NO;
|
||||
|
||||
NSCharacterSet *whitespace = [NSCharacterSet whitespaceAndNewlineCharacterSet];
|
||||
|
||||
NSString *line;
|
||||
NSScanner *scanner = nil;
|
||||
NSEnumerator *e = [[contents componentsSeparatedByString:@"\n"] objectEnumerator];
|
||||
while (line = [e nextObject])
|
||||
{
|
||||
[scanner release];
|
||||
scanner = [[NSScanner alloc] initWithString:line];
|
||||
|
||||
NSString *command;
|
||||
if (![scanner scanUpToCharactersFromSet:whitespace intoString:&command]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//FILE "filename.shn" WAVE
|
||||
if ([command isEqualToString:@"FILE"]) {
|
||||
track = nil;
|
||||
trackAdded = NO;
|
||||
|
||||
if (![scanner scanString:@"\"" intoString:&command]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//Read in the path
|
||||
if (![scanner scanUpToString:@"\"" intoString:&path]) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//TRACK 01 AUDIO
|
||||
else if ([command isEqualToString:@"TRACK"]) {
|
||||
trackAdded = NO;
|
||||
|
||||
if (![scanner scanUpToCharactersFromSet:whitespace intoString:&track]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NSString *type = nil;
|
||||
if (![scanner scanUpToCharactersFromSet:whitespace intoString:&type]
|
||||
|| ![type isEqualToString:@"AUDIO"]) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//INDEX 01 00:00:10
|
||||
//Note that time is written in Minutes:Seconds:Frames, where frames are 1/75 of a second
|
||||
else if ([command isEqualToString:@"INDEX"]) {
|
||||
if (trackAdded) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NSString *index = nil;
|
||||
if (![scanner scanUpToCharactersFromSet:whitespace intoString:&index]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
[scanner scanCharactersFromSet:whitespace intoString:nil];
|
||||
|
||||
NSString *time = nil;
|
||||
if (![scanner scanUpToCharactersFromSet:whitespace intoString:&time]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NSArray *msf = [time componentsSeparatedByString:@":"];
|
||||
if ([msf count] != 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double seconds = (60*[[msf objectAtIndex:0] intValue]) + [[msf objectAtIndex:1] intValue] + ([[msf objectAtIndex:2] floatValue]/75);
|
||||
|
||||
if (track == nil) {
|
||||
track = @"01";
|
||||
}
|
||||
|
||||
//Need to add basePath, and convert to URL
|
||||
[entries addObject:
|
||||
[CueSheetTrack trackWithURL:[self urlForPath:path relativeTo:filename]
|
||||
track: track
|
||||
time: seconds]];
|
||||
trackAdded = YES;
|
||||
}
|
||||
}
|
||||
|
||||
[scanner release];
|
||||
|
||||
tracks = [entries copy];
|
||||
|
||||
[entries release];
|
||||
}
|
||||
|
||||
- (id)initWithFile:(NSString *)filename
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
|
||||
NSError *error = nil;
|
||||
NSString *contents = [NSString stringWithContentsOfFile:filename encoding:NSUTF8StringEncoding error:&error];
|
||||
if (error || !contents) {
|
||||
NSLog(@"Could not open file...%@ %@", contents, error);
|
||||
return nil;
|
||||
}
|
||||
|
||||
tracks = [[NSMutableArray alloc] init];
|
||||
|
||||
//Actually parse file here.
|
||||
[self parseFile:filename];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *)tracks
|
||||
{
|
||||
return tracks;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
17F3BB680CBC560700864489 /* CueSheetPropertiesReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 17F3BB670CBC560700864489 /* CueSheetPropertiesReader.m */; };
|
||||
8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
|
||||
8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
|
||||
8E8D42190CBB0F3C00135C1B /* CueSheetPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E8D42180CBB0F3C00135C1B /* CueSheetPlugin.m */; };
|
||||
|
@ -21,6 +22,8 @@
|
|||
089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
|
||||
1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
|
||||
17F3BB660CBC560700864489 /* CueSheetPropertiesReader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CueSheetPropertiesReader.h; sourceTree = "<group>"; };
|
||||
17F3BB670CBC560700864489 /* CueSheetPropertiesReader.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = CueSheetPropertiesReader.m; sourceTree = "<group>"; };
|
||||
32DBCF630370AF2F00C91783 /* CueSheet_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CueSheet_Prefix.pch; sourceTree = "<group>"; };
|
||||
8D5B49B6048680CD000E48DA /* CueSheet.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CueSheet.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
|
@ -90,6 +93,8 @@
|
|||
8E8D42250CBB0F5800135C1B /* CueSheetContainer.m */,
|
||||
8E8D42350CBB0F9800135C1B /* CueSheetDecoder.h */,
|
||||
8E8D42360CBB0F9800135C1B /* CueSheetDecoder.m */,
|
||||
17F3BB660CBC560700864489 /* CueSheetPropertiesReader.h */,
|
||||
17F3BB670CBC560700864489 /* CueSheetPropertiesReader.m */,
|
||||
8E8D424B0CBB11C600135C1B /* CueSheet.h */,
|
||||
8E8D424C0CBB11C600135C1B /* CueSheet.m */,
|
||||
8E8D43550CBB1AE900135C1B /* CueSheetTrack.h */,
|
||||
|
@ -189,6 +194,7 @@
|
|||
8E8D42370CBB0F9800135C1B /* CueSheetDecoder.m in Sources */,
|
||||
8E8D424D0CBB11C600135C1B /* CueSheet.m in Sources */,
|
||||
8E8D43570CBB1AE900135C1B /* CueSheetTrack.m in Sources */,
|
||||
17F3BB680CBC560700864489 /* CueSheetPropertiesReader.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -18,13 +18,16 @@
|
|||
return [NSArray arrayWithObject:@"cue"];
|
||||
}
|
||||
|
||||
+ (NSArray *)urlsForContainerURL:(NSURL *)url {
|
||||
+ (NSArray *)urlsForContainerURL:(NSURL *)url
|
||||
{
|
||||
if (![url isFileURL]) {
|
||||
return [NSArray array];
|
||||
}
|
||||
|
||||
NSMutableArray *tracks = [NSMutableArray array];
|
||||
CueSheet *cuesheet = [[CueSheet alloc] initWithFile:[url path]];
|
||||
|
||||
CueSheet *cuesheet = [CueSheet cueSheetWithFile:[url path]];
|
||||
|
||||
NSEnumerator *e = [[cuesheet tracks] objectEnumerator];
|
||||
CueSheetTrack *track;
|
||||
while (track = [e nextObject]) {
|
||||
|
|
|
@ -13,10 +13,12 @@
|
|||
@class CueSheetTrack;
|
||||
|
||||
@interface CueSheetDecoder : NSObject <CogDecoder> {
|
||||
id<CogSource> source;
|
||||
id<CogDecoder> decoder;
|
||||
|
||||
|
||||
int bytesPerSecond;
|
||||
int trackPosition;
|
||||
int bytePosition;
|
||||
double trackEnd;
|
||||
|
||||
CueSheetTrack *track;
|
||||
}
|
||||
|
|
|
@ -10,49 +10,105 @@
|
|||
|
||||
#import "CueSheet.h"
|
||||
#import "CueSheetTrack.h"
|
||||
#import "CueSheetContainer.h"
|
||||
|
||||
@implementation CueSheetDecoder
|
||||
|
||||
+ (NSArray *)fileTypes
|
||||
{
|
||||
return [NSArray arrayWithObject:@"cue"];
|
||||
return [CueSheetContainer fileTypes];
|
||||
}
|
||||
|
||||
- (NSDictionary *)properties
|
||||
{
|
||||
return [decoder properties];
|
||||
NSMutableDictionary *properties = [[decoder properties] mutableCopy];
|
||||
|
||||
//Need to alter length
|
||||
[properties setObject:[NSNumber numberWithDouble:((trackEnd - [track time]) * 1000)] forKey:@"length"];
|
||||
|
||||
return [properties autorelease];
|
||||
}
|
||||
|
||||
- (BOOL)open:(id<CogSource>)source
|
||||
- (BOOL)open:(id<CogSource>)s
|
||||
{
|
||||
//Kind of a hackish way of accessing AudioDecoder
|
||||
decoder = [NSClassFromString(@"AudioDecoder") audioDecoderForURL:[source url]];
|
||||
[decoder retain];
|
||||
|
||||
BOOL r = [decoder open:source];
|
||||
if (r)
|
||||
{
|
||||
CueSheet *cuesheet = [CueSheet cueSheetWithFile:[[source url] path]];
|
||||
|
||||
track = [cuesheet track:[[source url] fragment]];
|
||||
|
||||
NSDictionary *properties = [decoder properties];
|
||||
int bitsPerSample = [[properties objectForKey:@"bitsPerSample"] intValue];
|
||||
int channels = [[properties objectForKey:@"channels"] intValue];
|
||||
float sampleRate = [[properties objectForKey:@"sampleRate"] floatValue];
|
||||
|
||||
bytesPerSecond = (int)((bitsPerSample/8) * channels * sampleRate);
|
||||
|
||||
[decoder seekToTime: [track start] * 1000.0];
|
||||
if (![[s url] isFileURL]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSURL *url = [s url];
|
||||
[s close];
|
||||
|
||||
CueSheet *cuesheet = [CueSheet cueSheetWithFile:[url path]];
|
||||
|
||||
NSArray *tracks = [cuesheet tracks];
|
||||
int i;
|
||||
for (i = 0; i < [tracks count]; i++)
|
||||
{
|
||||
if ([[[tracks objectAtIndex:i] track] isEqualToString:[url fragment]]){
|
||||
track = [tracks objectAtIndex:i];
|
||||
|
||||
//Kind of a hackish way of accessing outside classes.
|
||||
source = [NSClassFromString(@"AudioSource") audioSourceForURL:[track url]];
|
||||
[source retain];
|
||||
|
||||
if (![source open:[track url]]) {
|
||||
NSLog(@"Could not open cuesheet source");
|
||||
return NO;
|
||||
}
|
||||
|
||||
decoder = [NSClassFromString(@"AudioDecoder") audioDecoderForURL:[source url]];
|
||||
[decoder retain];
|
||||
|
||||
if (![decoder open:source]) {
|
||||
NSLog(@"Could not open cuesheet decoder");
|
||||
return NO;
|
||||
}
|
||||
|
||||
CueSheetTrack *nextTrack = nil;
|
||||
if (i + 1 < [tracks count]) {
|
||||
nextTrack = [tracks objectAtIndex:i + 1];
|
||||
}
|
||||
|
||||
NSDictionary *properties = [decoder properties];
|
||||
int bitsPerSample = [[properties objectForKey:@"bitsPerSample"] intValue];
|
||||
int channels = [[properties objectForKey:@"channels"] intValue];
|
||||
float sampleRate = [[properties objectForKey:@"sampleRate"] floatValue];
|
||||
|
||||
bytesPerSecond = (int)((bitsPerSample/8) * channels * sampleRate);
|
||||
|
||||
[decoder seekToTime: [track time] * 1000.0];
|
||||
|
||||
if (nextTrack && [[[nextTrack url] absoluteString] isEqualToString:[[track url] absoluteString]]) {
|
||||
trackEnd = [nextTrack time];
|
||||
}
|
||||
else {
|
||||
trackEnd = [[properties objectForKey:@"length"] doubleValue]/1000.0;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
if (decoder) {
|
||||
[decoder close];
|
||||
[decoder release];
|
||||
decoder = nil;
|
||||
}
|
||||
|
||||
if (source) {
|
||||
[source release];
|
||||
source = nil;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
- (double)seekToTime:(double)time //milliseconds
|
||||
{
|
||||
double trackStartMs = [track start] * 1000.0;
|
||||
double trackEndMs = [track end] * 1000.0;
|
||||
double trackStartMs = [track time] * 1000.0;
|
||||
double trackEndMs = trackEnd * 1000.0;
|
||||
|
||||
if (time > trackEndMs - trackStartMs) {
|
||||
//need a better way of returning fail.
|
||||
|
@ -61,34 +117,29 @@
|
|||
|
||||
time += trackStartMs;
|
||||
|
||||
trackPosition = (time/1000.0) * bytesPerSecond;
|
||||
bytePosition = (time/1000.0) * bytesPerSecond;
|
||||
|
||||
return [decoder seekToTime:time];
|
||||
}
|
||||
|
||||
- (int)fillBuffer:(void *)buf ofSize:(UInt32)size
|
||||
{
|
||||
int n;
|
||||
long trackByteEnd = trackEnd * bytesPerSecond;
|
||||
|
||||
n = [decoder fillBuffer:buf ofSize:size];
|
||||
|
||||
trackPosition += n;
|
||||
|
||||
int trackEnd = [track end] * bytesPerSecond;
|
||||
|
||||
if (trackPosition + n > trackEnd) {
|
||||
return trackEnd - trackPosition;
|
||||
if (bytePosition + size > trackByteEnd) {
|
||||
size = trackByteEnd - bytePosition;
|
||||
}
|
||||
|
||||
if (!size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n = [decoder fillBuffer:buf ofSize:size];
|
||||
|
||||
bytePosition += n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[decoder release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#import "CueSheetContainer.h"
|
||||
#import "CueSheetDecoder.h"
|
||||
#import "CueSheetPropertiesReader.h"
|
||||
|
||||
@implementation CueSheetPlugin
|
||||
|
||||
|
@ -17,7 +18,9 @@
|
|||
{
|
||||
return [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
kCogContainer, [CueSheetContainer className],
|
||||
kCogDecoder, [CueSheetDecoder className]];
|
||||
kCogDecoder, [CueSheetDecoder className],
|
||||
kCogPropertiesReader, [CueSheetPropertiesReader className],
|
||||
nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -11,16 +11,18 @@
|
|||
|
||||
@interface CueSheetTrack : NSObject {
|
||||
NSString *track;
|
||||
NSURL *url;
|
||||
|
||||
double start;
|
||||
double end;
|
||||
double time;
|
||||
}
|
||||
|
||||
- (void)initWithTrack:(NSString *)t start:(double)s end:(double)e;
|
||||
+ (id)trackWithURL:(NSURL *)u track:(NSString *)t time:(double)t;
|
||||
- (id)initWithURL:(NSURL *)u track:(NSString *)t time:(double)t;
|
||||
|
||||
|
||||
- (NSString *)track;
|
||||
- (NSURL *)url;
|
||||
|
||||
- (double)start;
|
||||
- (double)end;
|
||||
- (double)time;
|
||||
|
||||
@end
|
||||
|
|
|
@ -11,14 +11,19 @@
|
|||
|
||||
@implementation CueSheetTrack
|
||||
|
||||
- (void)initWithTrack:(NSString *)t start:(double)s end:(double)e
|
||||
+ (id)trackWithURL:(NSURL *)u track:(NSString *)t time:(double)s
|
||||
{
|
||||
return [[[CueSheetTrack alloc] initWithURL:u track:t time:s] autorelease];
|
||||
}
|
||||
|
||||
- (id)initWithURL:(NSURL *)u track:(NSString *)t time:(double)s
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
{
|
||||
track = [t copy];
|
||||
start = s;
|
||||
end = e;
|
||||
url = [u copy];
|
||||
time = s;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -29,14 +34,14 @@
|
|||
return track;
|
||||
}
|
||||
|
||||
- (double)start
|
||||
- (NSURL *)url
|
||||
{
|
||||
return start;
|
||||
return url;
|
||||
}
|
||||
|
||||
- (double)end
|
||||
- (double)time
|
||||
{
|
||||
return end;
|
||||
return time;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -567,7 +567,8 @@ static inline signed int scale (mad_fixed_t sample)
|
|||
new_position = ((double) seconds / (double) total_seconds) * _fileSize;
|
||||
|
||||
[_source seek:new_position whence:SEEK_SET];
|
||||
mad_stream_sync(&_stream);
|
||||
|
||||
//mad_stream_sync(&_stream);
|
||||
_stream.error = MAD_ERROR_BUFLEN;
|
||||
_stream.sync = 0;
|
||||
_outputAvailable = 0;
|
||||
|
|
Loading…
Reference in New Issue