diff --git a/Plugins/CoreAudio/CoreAudioDecoder.h b/Plugins/CoreAudio/CoreAudioDecoder.h index ef599953b..4dcb311dc 100644 --- a/Plugins/CoreAudio/CoreAudioDecoder.h +++ b/Plugins/CoreAudio/CoreAudioDecoder.h @@ -31,6 +31,9 @@ id _audioSource; AudioFileID _audioFile; ExtAudioFileRef _in; + + long rewindStart; + NSMutableData * rewindBuffer; int bitrate; int bitsPerSample; diff --git a/Plugins/CoreAudio/CoreAudioDecoder.m b/Plugins/CoreAudio/CoreAudioDecoder.m index 24e2369c1..014e1fac2 100644 --- a/Plugins/CoreAudio/CoreAudioDecoder.m +++ b/Plugins/CoreAudio/CoreAudioDecoder.m @@ -24,6 +24,8 @@ #import "Logging.h" +#define REWIND_SIZE 131072 + @interface CoreAudioDecoder (Private) - (BOOL) readInfoFromExtAudioFileRef; @end @@ -42,16 +44,49 @@ static OSStatus readProc(void* clientData, if (position != pSelf->_lastPosition) { if ([source seekable]) [source seek:position whence:SEEK_SET]; - else + else if (position < pSelf->rewindStart) return seekErr; } - size_t bytesRead = [source read:buffer amount:requestCount]; + size_t copyMax = 0; + size_t bytesRead = 0; + size_t rewindBytes = 0; + + if (![source seekable]) { + long rewindStart = pSelf->rewindStart; + rewindBytes = [pSelf->rewindBuffer length]; + + if ( position < rewindStart + rewindBytes ) { + const uint8_t * rewindBuffer = (const uint8_t *)([pSelf->rewindBuffer bytes]); + copyMax = rewindStart + rewindBytes - position; + if (copyMax > requestCount) + copyMax = requestCount; + memcpy(buffer, rewindBuffer + (position - rewindStart), copyMax); + requestCount -= copyMax; + position += copyMax; + } + } + + if ( requestCount ) + bytesRead = [source read:(((uint8_t *)buffer) + copyMax) amount:requestCount]; + + if (![source seekable]) { + size_t copyBytes = bytesRead; + if (copyBytes) { + ssize_t removeBytes = ((rewindBytes + copyBytes) - REWIND_SIZE); + if (removeBytes > 0) { + NSRange range = NSMakeRange(0, removeBytes); + [pSelf->rewindBuffer replaceBytesInRange:range withBytes:NULL length:0]; + pSelf->rewindStart += removeBytes; + } + [pSelf->rewindBuffer appendBytes:buffer length:copyBytes]; + } + } pSelf->_lastPosition = position + bytesRead; if(actualCount) - *actualCount = (UInt32) bytesRead; + *actualCount = (UInt32) (copyMax + bytesRead); return noErr; } @@ -106,6 +141,9 @@ static SInt64 getSizeProc(void* clientData) { _audioSource = source; _lastPosition = [source tell]; + + rewindStart = _lastPosition; + rewindBuffer = [[NSMutableData alloc] init]; err = AudioFileOpenWithCallbacks((__bridge void *)self, readProc, 0, getSizeProc, 0, 0, &_audioFile); if(noErr != err) { @@ -244,7 +282,17 @@ static SInt64 getSizeProc(void* clientData) { + (NSArray *)mimeTypes { - return nil; + OSStatus err; + UInt32 size; + NSArray *sAudioMIMETypes; + + size = sizeof(sAudioMIMETypes); + err = AudioFileGetGlobalInfo(kAudioFileGlobalInfo_AllMIMETypes, 0, NULL, &size, &sAudioMIMETypes); + if(noErr != err) { + return nil; + } + + return sAudioMIMETypes; } + (float)priority