From eb96a75a1f0fc00da950a346a5ed3d53446cc31f Mon Sep 17 00:00:00 2001 From: vspader Date: Sun, 4 Mar 2007 04:36:10 +0000 Subject: [PATCH] Modified CoreAudioDecoder to use new source based system. It just ignores the source and uses its own, since the ExtAudioFile API is absolutely hopeless when it comes to streaming. --- Audio/Plugin.h | 2 +- Plugins/CoreAudio/CoreAudioDecoder.h | 9 - Plugins/CoreAudio/CoreAudioDecoder.m | 175 ++---------------- Plugins/CoreAudio/CoreAudioPropertiesReader.m | 4 +- Plugins/FileSource/FileSource.h | 4 + Plugins/FileSource/FileSource.m | 15 ++ Plugins/HTTPSource/HTTPSource.h | 4 + Plugins/HTTPSource/HTTPSource.m | 21 +++ 8 files changed, 61 insertions(+), 173 deletions(-) diff --git a/Audio/Plugin.h b/Audio/Plugin.h index cbf7a06da..4c122ea74 100644 --- a/Audio/Plugin.h +++ b/Audio/Plugin.h @@ -17,7 +17,7 @@ @protocol CogSource + (NSArray *)schemes; //http, file, etc -- (BOOL)buffered; //Return YES if the input should be buffered, NO if it shouldn't. Used for remote connections (HTTP), not local stuff (file). +- (NSURL *)url; - (BOOL)open:(NSURL *)url; - (NSDictionary *)properties; //Perhaps contains header info for HTTP stream, or path for a regular file. diff --git a/Plugins/CoreAudio/CoreAudioDecoder.h b/Plugins/CoreAudio/CoreAudioDecoder.h index 6a54c6497..103efebce 100644 --- a/Plugins/CoreAudio/CoreAudioDecoder.h +++ b/Plugins/CoreAudio/CoreAudioDecoder.h @@ -24,20 +24,11 @@ #import "Plugin.h" -#undef _USE_WRAPPER_ @interface CoreAudioDecoder : NSObject { ExtAudioFileRef _in; -#ifdef _USE_WRAPPER_ - int _inFd; - AudioFileID _audioID; - - SInt64 _fileSize; - SInt64 _startOffset; -#endif - int bitrate; int bitsPerSample; int channels; diff --git a/Plugins/CoreAudio/CoreAudioDecoder.m b/Plugins/CoreAudio/CoreAudioDecoder.m index f63f40051..6446b8669 100644 --- a/Plugins/CoreAudio/CoreAudioDecoder.m +++ b/Plugins/CoreAudio/CoreAudioDecoder.m @@ -28,167 +28,25 @@ @implementation CoreAudioDecoder -#ifdef _USE_WRAPPER_ -OSStatus readFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, void *buffer, ByteCount* actualCount) -{ - CoreAudioFile *caf = (CoreAudioFile *)inRefCon; - int fd = caf->_inFd; - - // fseek(fd, inPosition, SEEK_SET); -// NSLog(@"Requesting %u", requestCount); -// NSLog(@"Currently at %lli", inPosition); - - *actualCount = pread(fd, buffer, requestCount, inPosition+caf->_startOffset); - - if (*actualCount <= 0) - { - return -1000; //Error? - } - - return noErr; -} - -SInt64 getSizeFunc(void *inRefCon) -{ - CoreAudioFile *caf = (CoreAudioFile *)inRefCon; - int fd = caf->_inFd; - - if (caf->_fileSize != 0) - { - return caf->_fileSize; - } - - /* long curPos; - - curPos = ftell(fd); - - fseek(fd, 0, SEEK_END); - - caf->_fileSize = ftell(fd); - - fseek(fd, curPos, SEEK_SET); - */ - - caf->_fileSize = lseek(fd, 0, SEEK_END) - caf->_startOffset; - NSLog(@"SIZE at %lli", caf->_fileSize); - - NSLog(@"ERROR: %i = %i %i %i", errno, EBADF, ESPIPE, EINVAL); - return caf->_fileSize; -} - -OSStatus setSizeFunc(void * inRefCon, SInt64 inSize) -{ - NSLog(@"setsize FUNC"); - - return -1000; //Not supported at the moment -} - -OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, const void *buffer, ByteCount* actualCount) -{ - NSLog(@"WRITE FUNC"); - return -1000; //Not supported at the moment -} -#endif - - (void) close { OSStatus err; -#ifdef _USE_WRAPPER_ - if (_inFd) - close(_inFd); - AudioFileClose(_audioID); -#endif - err = ExtAudioFileDispose(_in); if(noErr != err) { NSLog(@"Error closing ExtAudioFile"); } } -- (BOOL) open:(NSURL *)url +- (BOOL)open:(id)source; { OSStatus err; - -#ifdef _USE_WRAPPER_ - AudioFileTypeID type = 0; - NSString *ext; - - // Open the input file - _inFd = open([[url path] UTF8String], O_RDONLY, 0777); - if (_inFd < 0) - { - NSLog(@"Error operning file: %s", url); - return NO; - } - _startOffset = 0; - - ext = [[url path] pathExtension]; - //Find first sync frame for MP3 - if([ext caseInsensitiveCompare:@"mp3"] == NSOrderedSame) { - size_t bytesRead; - uint8_t buf[2]; - - type = kAudioFileMP3Type; - - for(;;) { - bytesRead = read(_inFd, buf, 2); - - - if(2 != bytesRead) { - NSLog(@"Error finding mp3 sync frame"); - close(_inFd); - return NO; - } - - - // found some kind of data - if(0x00 != buf[0] || 0x00 != buf[1]) { - _startOffset = lseek(_inFd, 0, SEEK_CUR) - 2; - NSLog(@"Found sync frame at: %llx", _startOffset); - break; - } - } - } - else if([ext caseInsensitiveCompare:@"aac"] == NSOrderedSame) { - type = kAudioFileAAC_ADTSType; - } - else if([ext caseInsensitiveCompare:@"m4a"] == NSOrderedSame) { - type = kAudioFileM4AType; - } - else if([ext caseInsensitiveCompare:@"mp4"] == NSOrderedSame) { - type = kAudioFileMPEG4Type; - } - - //Using callbacks with fopen, ftell, fseek, fclose, because the default pread hangs when accessing the same file from multiple threads. - err = AudioFileOpenWithCallbacks(self, readFunc, writeFunc, getSizeFunc, setSizeFunc, type, &_audioID); - if(noErr != err) - { - NSLog(@"Error opening with callbacks, falling back: %s", (char *)&err); - FSRef ref; - close(_inFd); - _inFd = 0; - - err = FSPathMakeRef((const UInt8 *)[[url path] UTF8String], &ref, NULL); - if(noErr != err) { - return NO; - } - - err = AudioFileOpen(&ref, fsRdPerm, type, &_audioID); - if(noErr != err) { - NSLog(@"Error opening AudioFile: %s", (char *)&err); - return NO; - } - } - - err = ExtAudioFileWrapAudioFileID(_audioID, NO, &_in); - if(noErr != err) { - return NO; - } - -#else FSRef ref; + NSURL *url = [source url]; + if (![[url scheme] isEqualToString:@"file"]) + return NO; + // Open the input file err = FSPathMakeRef((const UInt8 *)[[url path] UTF8String], &ref, NULL); if(noErr != err) { @@ -200,7 +58,7 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c NSLog(@"Error opening file: %s", &err); return NO; } -#endif + return [self readInfoFromExtAudioFileRef]; } @@ -226,21 +84,8 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c return NO; } -#ifdef _USE_WRAPPER_ - SInt64 totalBytes; - - size = sizeof(totalBytes); - err = AudioFileGetProperty(_audioID, kAudioFilePropertyAudioDataByteCount, &size, &totalBytes); - if(err != noErr) { - [self close]; - return NO; - } - - bitrate = round(((totalBytes*8.0)/((double)(totalFrames)/asbd.mSampleRate))/1000.0); -#else //Is there a way to get bitrate with extAudioFile? bitrate = 0; -#endif // Set our properties bitsPerSample = asbd.mBitsPerChannel; @@ -276,6 +121,9 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c return NO; } + [self willChangeValueForKey:@"properties"]; + [self didChangeValueForKey:@"properties"]; + return YES; } @@ -340,5 +188,10 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c nil]; } +- (BOOL)seekable +{ + return YES; //Are you kidding me? it HAS to be seekable. The AudioFile API is 100% impossible to stream in any way. Even using callbacks gives problems. Sigh. +} + @end diff --git a/Plugins/CoreAudio/CoreAudioPropertiesReader.m b/Plugins/CoreAudio/CoreAudioPropertiesReader.m index 77d7e43be..30ed22f8f 100644 --- a/Plugins/CoreAudio/CoreAudioPropertiesReader.m +++ b/Plugins/CoreAudio/CoreAudioPropertiesReader.m @@ -11,13 +11,13 @@ @implementation CoreAudioPropertiesReader -- (NSDictionary *)propertiesForURL:(NSURL *)url ++ (NSDictionary *)propertiesForSource:(id)source { NSDictionary *properties; CoreAudioDecoder *decoder; decoder = [[CoreAudioDecoder alloc] init]; - if (![decoder open:url]) + if (![decoder open:source]) { return nil; } diff --git a/Plugins/FileSource/FileSource.h b/Plugins/FileSource/FileSource.h index 9ae4baa7f..18e3e6557 100644 --- a/Plugins/FileSource/FileSource.h +++ b/Plugins/FileSource/FileSource.h @@ -13,6 +13,10 @@ @interface FileSource : NSObject { FILE *_fd; + + NSURL *_url; } +- (void)setURL:(NSURL *)url; + @end diff --git a/Plugins/FileSource/FileSource.m b/Plugins/FileSource/FileSource.m index 6343a5c09..95c71054c 100644 --- a/Plugins/FileSource/FileSource.m +++ b/Plugins/FileSource/FileSource.m @@ -18,6 +18,8 @@ - (BOOL)open:(NSURL *)url { + [self setURL:url]; + _fd = fopen([[url path] UTF8String], "r"); return (_fd != NULL); @@ -53,6 +55,19 @@ fclose(_fd); } +- (NSURL *)url +{ + return _url; +} + +- (void)setURL:(NSURL *)url +{ + [url retain]; + [_url release]; + _url = url; +} + + + (NSArray *)schemes { return [NSArray arrayWithObject:@"file"]; diff --git a/Plugins/HTTPSource/HTTPSource.h b/Plugins/HTTPSource/HTTPSource.h index 5977ba95e..b64c8fe2e 100644 --- a/Plugins/HTTPSource/HTTPSource.h +++ b/Plugins/HTTPSource/HTTPSource.h @@ -15,9 +15,13 @@ { Socket *_socket; + NSURL *_url; + BOOL pastHeader; long byteCount; } +- (void)setURL:(NSURL *)url; + @end diff --git a/Plugins/HTTPSource/HTTPSource.m b/Plugins/HTTPSource/HTTPSource.m index 1c6c9d925..8b04c734b 100644 --- a/Plugins/HTTPSource/HTTPSource.m +++ b/Plugins/HTTPSource/HTTPSource.m @@ -18,6 +18,7 @@ - (BOOL)open:(NSURL *)url { + [self setURL:url]; unsigned int port = [[url port] unsignedIntValue]; if (!port) @@ -112,6 +113,26 @@ [_socket close]; } +- (void)dealloc +{ + [_socket release]; + [_url release]; + + [super dealloc]; +} + +- (NSURL *)url +{ + return _url; +} + +- (void)setURL:(NSURL *)url +{ + [url retain]; + [_url release]; + _url = url; +} + + (NSArray *)schemes { return [NSArray arrayWithObject:@"http"];