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.
parent
e452cbe3db
commit
eb96a75a1f
|
@ -17,7 +17,7 @@
|
||||||
@protocol CogSource <NSObject>
|
@protocol CogSource <NSObject>
|
||||||
+ (NSArray *)schemes; //http, file, etc
|
+ (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;
|
- (BOOL)open:(NSURL *)url;
|
||||||
- (NSDictionary *)properties; //Perhaps contains header info for HTTP stream, or path for a regular file.
|
- (NSDictionary *)properties; //Perhaps contains header info for HTTP stream, or path for a regular file.
|
||||||
|
|
|
@ -24,20 +24,11 @@
|
||||||
|
|
||||||
#import "Plugin.h"
|
#import "Plugin.h"
|
||||||
|
|
||||||
#undef _USE_WRAPPER_
|
|
||||||
|
|
||||||
@interface CoreAudioDecoder : NSObject <CogDecoder>
|
@interface CoreAudioDecoder : NSObject <CogDecoder>
|
||||||
{
|
{
|
||||||
ExtAudioFileRef _in;
|
ExtAudioFileRef _in;
|
||||||
|
|
||||||
#ifdef _USE_WRAPPER_
|
|
||||||
int _inFd;
|
|
||||||
AudioFileID _audioID;
|
|
||||||
|
|
||||||
SInt64 _fileSize;
|
|
||||||
SInt64 _startOffset;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int bitrate;
|
int bitrate;
|
||||||
int bitsPerSample;
|
int bitsPerSample;
|
||||||
int channels;
|
int channels;
|
||||||
|
|
|
@ -28,167 +28,25 @@
|
||||||
|
|
||||||
@implementation CoreAudioDecoder
|
@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
|
- (void) close
|
||||||
{
|
{
|
||||||
OSStatus err;
|
OSStatus err;
|
||||||
|
|
||||||
#ifdef _USE_WRAPPER_
|
|
||||||
if (_inFd)
|
|
||||||
close(_inFd);
|
|
||||||
AudioFileClose(_audioID);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
err = ExtAudioFileDispose(_in);
|
err = ExtAudioFileDispose(_in);
|
||||||
if(noErr != err) {
|
if(noErr != err) {
|
||||||
NSLog(@"Error closing ExtAudioFile");
|
NSLog(@"Error closing ExtAudioFile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) open:(NSURL *)url
|
- (BOOL)open:(id<CogSource>)source;
|
||||||
{
|
{
|
||||||
OSStatus err;
|
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;
|
FSRef ref;
|
||||||
|
|
||||||
|
NSURL *url = [source url];
|
||||||
|
if (![[url scheme] isEqualToString:@"file"])
|
||||||
|
return NO;
|
||||||
|
|
||||||
// Open the input file
|
// Open the input file
|
||||||
err = FSPathMakeRef((const UInt8 *)[[url path] UTF8String], &ref, NULL);
|
err = FSPathMakeRef((const UInt8 *)[[url path] UTF8String], &ref, NULL);
|
||||||
if(noErr != err) {
|
if(noErr != err) {
|
||||||
|
@ -200,7 +58,7 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c
|
||||||
NSLog(@"Error opening file: %s", &err);
|
NSLog(@"Error opening file: %s", &err);
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return [self readInfoFromExtAudioFileRef];
|
return [self readInfoFromExtAudioFileRef];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,21 +84,8 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c
|
||||||
return NO;
|
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?
|
//Is there a way to get bitrate with extAudioFile?
|
||||||
bitrate = 0;
|
bitrate = 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
// Set our properties
|
// Set our properties
|
||||||
bitsPerSample = asbd.mBitsPerChannel;
|
bitsPerSample = asbd.mBitsPerChannel;
|
||||||
|
@ -276,6 +121,9 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[self willChangeValueForKey:@"properties"];
|
||||||
|
[self didChangeValueForKey:@"properties"];
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,5 +188,10 @@ OSStatus writeFunc(void * inRefCon, SInt64 inPosition, ByteCount requestCount, c
|
||||||
nil];
|
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
|
@end
|
||||||
|
|
|
@ -11,13 +11,13 @@
|
||||||
|
|
||||||
@implementation CoreAudioPropertiesReader
|
@implementation CoreAudioPropertiesReader
|
||||||
|
|
||||||
- (NSDictionary *)propertiesForURL:(NSURL *)url
|
+ (NSDictionary *)propertiesForSource:(id<CogSource>)source
|
||||||
{
|
{
|
||||||
NSDictionary *properties;
|
NSDictionary *properties;
|
||||||
CoreAudioDecoder *decoder;
|
CoreAudioDecoder *decoder;
|
||||||
|
|
||||||
decoder = [[CoreAudioDecoder alloc] init];
|
decoder = [[CoreAudioDecoder alloc] init];
|
||||||
if (![decoder open:url])
|
if (![decoder open:source])
|
||||||
{
|
{
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
@interface FileSource : NSObject <CogSource>
|
@interface FileSource : NSObject <CogSource>
|
||||||
{
|
{
|
||||||
FILE *_fd;
|
FILE *_fd;
|
||||||
|
|
||||||
|
NSURL *_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setURL:(NSURL *)url;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
- (BOOL)open:(NSURL *)url
|
- (BOOL)open:(NSURL *)url
|
||||||
{
|
{
|
||||||
|
[self setURL:url];
|
||||||
|
|
||||||
_fd = fopen([[url path] UTF8String], "r");
|
_fd = fopen([[url path] UTF8String], "r");
|
||||||
|
|
||||||
return (_fd != NULL);
|
return (_fd != NULL);
|
||||||
|
@ -53,6 +55,19 @@
|
||||||
fclose(_fd);
|
fclose(_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSURL *)url
|
||||||
|
{
|
||||||
|
return _url;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setURL:(NSURL *)url
|
||||||
|
{
|
||||||
|
[url retain];
|
||||||
|
[_url release];
|
||||||
|
_url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+ (NSArray *)schemes
|
+ (NSArray *)schemes
|
||||||
{
|
{
|
||||||
return [NSArray arrayWithObject:@"file"];
|
return [NSArray arrayWithObject:@"file"];
|
||||||
|
|
|
@ -15,9 +15,13 @@
|
||||||
{
|
{
|
||||||
Socket *_socket;
|
Socket *_socket;
|
||||||
|
|
||||||
|
NSURL *_url;
|
||||||
|
|
||||||
BOOL pastHeader;
|
BOOL pastHeader;
|
||||||
|
|
||||||
long byteCount;
|
long byteCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setURL:(NSURL *)url;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
- (BOOL)open:(NSURL *)url
|
- (BOOL)open:(NSURL *)url
|
||||||
{
|
{
|
||||||
|
[self setURL:url];
|
||||||
|
|
||||||
unsigned int port = [[url port] unsignedIntValue];
|
unsigned int port = [[url port] unsignedIntValue];
|
||||||
if (!port)
|
if (!port)
|
||||||
|
@ -112,6 +113,26 @@
|
||||||
[_socket close];
|
[_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
|
+ (NSArray *)schemes
|
||||||
{
|
{
|
||||||
return [NSArray arrayWithObject:@"http"];
|
return [NSArray arrayWithObject:@"http"];
|
||||||
|
|
Loading…
Reference in New Issue