bool SFB::FileInputSource::_Open(CFErrorRef *error) { UInt8 buf [PATH_MAX]; Boolean success = CFURLGetFileSystemRepresentation(GetURL(), FALSE, buf, PATH_MAX); if(!success) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, EIO, nullptr); return false; } mFile = unique_FILE_ptr(std::fopen((const char *)buf, "r"), std::fclose); if(!mFile) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, errno, nullptr); return false; } if(-1 == stat((const char *)buf, &mFilestats)) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, errno, nullptr); mFile.reset(); return false; } return true; }
bool HTTPInputSource::Open(CFErrorRef *error) { if(IsOpen()) { LOGGER_WARNING("org.sbooth.AudioEngine.InputSource.HTTP", "Open() called on an InputSource that is already open"); return true; } // Set up the HTTP request mRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), mURL, kCFHTTPVersion1_1); if(NULL == mRequest) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); return false; } CFHTTPMessageSetHeaderFieldValue(mRequest, CFSTR("User-Agent"), CFSTR("SFBAudioEngine")); // Seek support if(0 < mDesiredOffset) { CFStringRef byteRange = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("bytes=%ld-"), mDesiredOffset); CFHTTPMessageSetHeaderFieldValue(mRequest, CFSTR("Range"), byteRange); CFRelease(byteRange), byteRange = NULL; } mReadStream = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, mRequest, NULL); if(NULL == mReadStream) { CFRelease(mRequest), mRequest = NULL; if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); return false; } // Start the HTTP connection CFStreamClientContext myContext = { 0, this, NULL, NULL, NULL }; CFOptionFlags clientFlags = kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered; if(!CFReadStreamSetClient(mReadStream, clientFlags, myCFReadStreamClientCallBack, &myContext)) { CFRelease(mRequest), mRequest = NULL; CFRelease(mReadStream), mReadStream = NULL; if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); return false; } CFReadStreamScheduleWithRunLoop(mReadStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); if(!CFReadStreamOpen(mReadStream)) { CFRelease(mRequest), mRequest = NULL; CFRelease(mReadStream), mReadStream = NULL; if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); return false; } while(NULL == mResponseHeaders) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); mIsOpen = true; return true; }
__private_extern__ CFErrorRef _CFErrorFromStreamError(CFAllocatorRef alloc, CFStreamError *streamError) { CFErrorRef result; Boolean canUpCall; __CFSpinLock(&(CFNetworkSupport.lock)); if (!__CFBitIsSet(CFNetworkSupport.flags, kTriedToLoad)) initializeCFNetworkSupport(); canUpCall = (CFNetworkSupport._CFErrorCreateWithStreamError != NULL); __CFSpinUnlock(&(CFNetworkSupport.lock)); if (canUpCall) { result = CFNETWORK_CALL(_CFErrorCreateWithStreamError, (alloc, streamError)); } else { if (streamError->domain == kCFStreamErrorDomainPOSIX) { return CFErrorCreate(alloc, kCFErrorDomainPOSIX, streamError->error, NULL); } else if (streamError->domain == kCFStreamErrorDomainMacOSStatus) { return CFErrorCreate(alloc, kCFErrorDomainOSStatus, streamError->error, NULL); } else { CFStringRef key = CFSTR("CFStreamErrorDomainKey"); CFNumberRef value = CFNumberCreate(alloc, kCFNumberCFIndexType, &streamError->domain); CFDictionaryRef dict = CFDictionaryCreate(alloc, (const void **)(&key), (const void **)(&value), 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); result = CFErrorCreate(alloc, CFSTR("BogusCFStreamErrorCompatibilityDomain"), streamError->error, dict); CFRelease(value); CFRelease(dict); } } return result; }
bool SFB::Audio::Converter::Open(CFErrorRef *error) { if(!mDecoder) return false; // Open the decoder if necessary if(!mDecoder->IsOpen() && !mDecoder->Open(error)) { if(error) LOGGER_ERR("org.sbooth.AudioEngine.AudioConverter", "Error opening decoder: " << error); return false; } AudioStreamBasicDescription inputFormat = mDecoder->GetFormat(); OSStatus result = AudioConverterNew(&inputFormat, &mFormat, &mConverter); if(noErr != result) { LOGGER_ERR("org.sbooth.AudioEngine.AudioConverter", "AudioConverterNewfailed: " << result << "'" << SFB::StringForOSType((OSType)result) << "'"); if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, result, nullptr); return false; } // TODO: Set kAudioConverterPropertyCalculateInputBufferSize mConverterState = std::unique_ptr<ConverterStateData>(new ConverterStateData(*mDecoder)); mConverterState->AllocateBufferList(BUFFER_SIZE_FRAMES); // Create the channel map if(mChannelLayout) { SInt32 channelMap [ mFormat.mChannelsPerFrame ]; UInt32 dataSize = (UInt32)sizeof(channelMap); const AudioChannelLayout *channelLayouts [] = { mDecoder->GetChannelLayout(), mChannelLayout }; result = AudioFormatGetProperty(kAudioFormatProperty_ChannelMap, sizeof(channelLayouts), channelLayouts, &dataSize, channelMap); if(noErr != result) { LOGGER_ERR("org.sbooth.AudioEngine.AudioConverter", "AudioFormatGetProperty (kAudioFormatProperty_ChannelMap) failed: " << result); if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, result, nullptr); return false; } } mIsOpen = true; return true; }
bool MemoryMappedFileInputSource::Close(CFErrorRef *error) { if(!IsOpen()) { LOGGER_WARNING("org.sbooth.AudioEngine.InputSource.MemoryMappedFile", "Close() called on an InputSource that hasn't been opened"); return true; } memset(&mFilestats, 0, sizeof(mFilestats)); if(nullptr != mMemory) { int result = munmap(mMemory, mFilestats.st_size); mMemory = nullptr; mCurrentPosition = nullptr; if(-1 == result) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, errno, nullptr); return false; } } mIsOpen = false; return true; }
inline SQLite3StatementRef _SQLite3StatementCreate(CFAllocatorRef allocator, SQLite3ConnectionRef connection, CFStringRef sql, CFErrorRef *error) { SQLite3StatementRef statement = NULL; if (connection && sql) { statement = CFAllocatorAllocate(allocator, sizeof(__SQLite3Statement), 0); if (statement) { statement->connection = SQLite3ConnectionRetain(connection); // Let's retain connection statement->allocator = allocator ? CFRetain(allocator) : NULL; // ...and allocator if not null statement->retainCount = 1; statement->stmt = NULL; CFDataRef sqlData = CFStringCreateExternalRepresentation(statement->allocator, sql, kCFStringEncodingUTF8, 0); if (sqlData) { SQLite3Status status = sqlite3_prepare_v2(connection->db, (const char *)CFDataGetBytePtr(sqlData), -1, &statement->stmt, NULL); if (kSQLite3StatusOK != status) { if (error) { *error = CFErrorCreate(allocator, CFSTR("com.github.mirek.SQLite3"), status, NULL); } printf("ERROR: %s\n", sqlite3_errmsg(connection->db)); statement = SQLite3StatementRelease(statement); // ...will be set to NULL } CFRelease(sqlData); } } } return statement; }
static CFErrorRef GTMCFLaunchCreateUnlocalizedError(CFIndex code, CFStringRef format, ...) { CFDictionaryRef user_info = NULL; if (format) { va_list args; va_start(args, format); CFStringRef string = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, NULL, format, args); user_info = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&kCFErrorDescriptionKey, (const void **)&string, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFRelease(string); va_end(args); } CFErrorRef error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, code, user_info); if (user_info) { CFRelease(user_info); } return error; }
InputSource * InputSource::CreateInputSourceForURL(CFURLRef url, int flags, CFErrorRef *error) { if(nullptr == url) return nullptr; InputSource *inputSource = nullptr; CFStringRef scheme = CFURLCopyScheme(url); // If there is no scheme the URL is invalid if(nullptr == scheme) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, EINVAL, nullptr); return nullptr; } if(kCFCompareEqualTo == CFStringCompare(CFSTR("file"), scheme, kCFCompareCaseInsensitive)) { if(InputSourceFlagMemoryMapFiles & flags) inputSource = new MemoryMappedFileInputSource(url); else if(InputSourceFlagLoadFilesInMemory & flags) inputSource = new InMemoryFileInputSource(url); else inputSource = new FileInputSource(url); } else if(kCFCompareEqualTo == CFStringCompare(CFSTR("http"), scheme, kCFCompareCaseInsensitive)) inputSource = new HTTPInputSource(url); CFRelease(scheme), scheme = nullptr; return inputSource; }
SFB::InputSource::unique_ptr SFB::InputSource::CreateForURL(CFURLRef url, int flags, CFErrorRef *error) { if(nullptr == url) return nullptr; // If there is no scheme the URL is invalid SFB::CFString scheme = CFURLCopyScheme(url); if(!scheme) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, EINVAL, nullptr); return nullptr; } if(kCFCompareEqualTo == CFStringCompare(CFSTR("file"), scheme, kCFCompareCaseInsensitive)) { if(InputSource::MemoryMapFiles & flags) return unique_ptr(new MemoryMappedFileInputSource(url)); else if(InputSource::LoadFilesInMemory & flags) return unique_ptr(new InMemoryFileInputSource(url)); else return unique_ptr(new FileInputSource(url)); } else if(kCFCompareEqualTo == CFStringCompare(CFSTR("http"), scheme, kCFCompareCaseInsensitive)) return unique_ptr(new HTTPInputSource(url)); return nullptr; }
CFErrorRef ResourceError::cfError() const { if (m_isNull) { ASSERT(!m_platformError); return 0; } if (!m_platformError) { RetainPtr<CFMutableDictionaryRef> userInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); if (!m_localizedDescription.isEmpty()) { RetainPtr<CFStringRef> localizedDescriptionString(AdoptCF, m_localizedDescription.createCFString()); CFDictionarySetValue(userInfo.get(), kCFErrorLocalizedDescriptionKey, localizedDescriptionString.get()); } if (!m_failingURL.isEmpty()) { RetainPtr<CFStringRef> failingURLString(AdoptCF, m_failingURL.createCFString()); CFDictionarySetValue(userInfo.get(), failingURLStringKey, failingURLString.get()); RetainPtr<CFURLRef> url(AdoptCF, KURL(ParsedURLString, m_failingURL).createCFURL()); CFDictionarySetValue(userInfo.get(), failingURLKey, url.get()); } #if PLATFORM(WIN) if (m_certificate) wkSetSSLPeerCertificateData(userInfo.get(), m_certificate.get()); #endif RetainPtr<CFStringRef> domainString(AdoptCF, m_domain.createCFString()); m_platformError.adoptCF(CFErrorCreate(0, domainString.get(), m_errorCode, userInfo.get())); } return m_platformError.get(); }
CFErrorRef SFB::CreateErrorForURL(CFStringRef domain, CFIndex code, CFStringRef descriptionFormatStringForURL, CFURLRef url, CFStringRef failureReason, CFStringRef recoverySuggestion) { if(nullptr == domain) return nullptr; SFB::CFMutableDictionary errorDictionary(0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if(!errorDictionary) return nullptr; if(descriptionFormatStringForURL && url) { CFDictionarySetValue(errorDictionary, kCFErrorURLKey, url); SFB::CFString displayName(CreateDisplayNameForURL(url)); if(displayName) { SFB::CFString description(nullptr, descriptionFormatStringForURL, displayName.Object()); if(description) CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, description); } } if(failureReason) CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, failureReason); if(recoverySuggestion) CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, recoverySuggestion); return CFErrorCreate(kCFAllocatorDefault, domain, code, errorDictionary); }
void SecKeyGeneratePairAsync(CFDictionaryRef parametersWhichMightBeMutiable, dispatch_queue_t deliveryQueue, SecKeyGeneratePairBlock result) { CFDictionaryRef parameters = CFDictionaryCreateCopy(NULL, parametersWhichMightBeMutiable); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ SecKeyRef publicKey = NULL; SecKeyRef privateKey = NULL; OSStatus status = SecKeyGeneratePair(parameters, &publicKey, &privateKey); dispatch_async(deliveryQueue, ^{ CFErrorRef error = NULL; if (noErr != status) { error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, status, NULL); } result(publicKey, privateKey, error); if (error) { CFRelease(error); } if (publicKey) { CFRelease(publicKey); } if (privateKey) { CFRelease(privateKey); } CFRelease(parameters); }); });
bool MemoryMappedFileInputSource::Close(CFErrorRef *error) { if(!IsOpen()) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.InputSource.MemoryMappedFile"); LOG4CXX_WARN(logger, "Close() called on an InputSource that hasn't been opened"); return true; } memset(&mFilestats, 0, sizeof(mFilestats)); if(NULL != mMemory) { int result = munmap(mMemory, mFilestats.st_size); mMemory = NULL; mCurrentPosition = NULL; if(-1 == result) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, errno, NULL); return false; } } mIsOpen = false; return true; }
CFErrorRef _CFErrorCreateWithStreamError(CFAllocatorRef allocator, CFStreamError *err) { CFStringRef domain = NULL; if (err->domain == kCFStreamErrorDomainPOSIX) { domain = CFStreamErrorDomainPOSIX; } else if (err->domain == kCFStreamErrorDomainFTP) { domain = CFStreamErrorDomainFTP; } else if (err->domain == kCFStreamErrorDomainNetDB) { domain = CFStreamErrorDomainNetDB; } else if (err->domain == kCFStreamErrorDomainSystemConfiguration) { domain = CFStreamErrorDomainSystemConfiguration; } else if (err->domain == kCFStreamErrorDomainHTTP) { domain = CFStreamErrorDomainHTTP; } else if (err->domain == kCFStreamErrorDomainMach) { domain = CFStreamErrorDomainMach; } else if (err->domain == kCFStreamErrorDomainNetServices) { domain = CFStreamErrorDomainNetServices; } else if (err->domain == kCFStreamErrorDomainSOCKS) { domain = CFStreamErrorDomainSOCKS; } else if (err->domain == kCFStreamErrorDomainSSL) { domain = CFStreamErrorDomainSSL; } else if (err->domain == kCFStreamErrorDomainMacOSStatus) { domain = CFStreamErrorDomainMacOSStatus; } else if (err->domain == kCFStreamErrorDomainCustom) { domain = CFStreamErrorDomainCustom; } else { domain = CFSTR("Unknown"); } return CFErrorCreate(allocator, domain, err->error, NULL); }
SFB::Audio::Metadata::unique_ptr SFB::Audio::Metadata::CreateMetadataForURL(CFURLRef url, CFErrorRef *error) { if(nullptr == url) return nullptr; // If this is a file URL, use the extension-based resolvers SFB::CFString scheme = CFURLCopyScheme(url); // If there is no scheme the URL is invalid if(!scheme) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, EINVAL, nullptr); return nullptr; } if(kCFCompareEqualTo == CFStringCompare(CFSTR("file"), scheme, kCFCompareCaseInsensitive)) { // Verify the file exists SInt32 errorCode = noErr; SFB::CFBoolean fileExists = (CFBooleanRef)CFURLCreatePropertyFromResource(kCFAllocatorDefault, url, kCFURLFileExists, &errorCode); if(fileExists) { if(CFBooleanGetValue(fileExists)) { SFB::CFString pathExtension = CFURLCopyPathExtension(url); if(pathExtension) { // Some extensions (.oga for example) support multiple audio codecs (Vorbis, FLAC, Speex) for(auto subclassInfo : sRegisteredSubclasses) { if(subclassInfo.mHandlesFilesWithExtension(pathExtension)) { unique_ptr metadata(subclassInfo.mCreateMetadata(url)); if(metadata->ReadMetadata(error)) return metadata; } } } } else { LOGGER_WARNING("org.sbooth.AudioEngine.Metadata", "The requested URL doesn't exist"); if(error) { SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” does not exist."), ""); SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("File not found"), ""); SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file may exist on removable media or may have been deleted."), ""); *error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, url, failureReason, recoverySuggestion); } } } else LOGGER_WARNING("org.sbooth.AudioEngine.Metadata", "CFURLCreatePropertyFromResource failed: " << errorCode); } return nullptr; }
void WebCoreSynchronousLoaderClient::willSendRequest(ResourceHandle* handle, ResourceRequest& request, const ResourceResponse& /*redirectResponse*/) { // FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests. if (!protocolHostAndPortAreEqual(handle->firstRequest().url(), request.url())) { ASSERT(!m_error.cfError()); RetainPtr<CFErrorRef> cfError(AdoptCF, CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainCFNetwork, kCFURLErrorBadServerResponse, 0)); m_error = cfError.get(); m_isDone = true; CFURLRequestRef nullRequest = 0; request = nullRequest; return; } }
bool FileInputSource::Open(CFErrorRef *error) { if(IsOpen()) { LOGGER_WARNING("org.sbooth.AudioEngine.InputSource.File", "Open() called on an InputSource that is already open"); return true; } UInt8 buf [PATH_MAX]; Boolean success = CFURLGetFileSystemRepresentation(mURL, FALSE, buf, PATH_MAX); if(!success) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, EIO, nullptr); return false; } mFile = fopen((const char *)buf, "r"); if(nullptr == mFile) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, errno, nullptr); return false; } if(-1 == stat((const char *)buf, &mFilestats)) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, errno, nullptr); if(0 != fclose(mFile)) LOGGER_WARNING("org.sbooth.AudioEngine.InputSource.File", "Unable to close the file: " << strerror(errno)); mFile = nullptr; return false; } mIsOpen = true; return true; }
SecKeyRef SecKeyCreateFromData(CFDictionaryRef parameters, CFDataRef keyData, CFErrorRef *error) { CSSM_ALGORITHMS algorithm; uint32 keySizeInBits; CSSM_KEYUSE keyUsage; CSSM_KEYCLASS keyClass; CSSM_RETURN crtn; utilGetKeyParametersFromCFDict(parameters, &algorithm, &keySizeInBits, &keyUsage, &keyClass); CSSM_CSP_HANDLE cspHandle = cuCspStartup(CSSM_FALSE); // TRUE => CSP, FALSE => CSPDL SecKeyImportExportParameters iparam; memset(&iparam, 0, sizeof(iparam)); iparam.keyUsage = keyUsage; SecExternalItemType itype; switch (keyClass) { case CSSM_KEYCLASS_PRIVATE_KEY: itype = kSecItemTypePrivateKey; break; case CSSM_KEYCLASS_PUBLIC_KEY: itype = kSecItemTypePublicKey; break; case CSSM_KEYCLASS_SESSION_KEY: itype = kSecItemTypeSessionKey; break; default: itype = kSecItemTypeUnknown; break; } CFMutableArrayRef ka = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); // NOTE: if we had a way to specify values other then kSecFormatUnknown we might be more useful. crtn = impExpImportRawKey(keyData, kSecFormatUnknown, itype, algorithm, NULL, cspHandle, 0, NULL, NULL, ka); if (crtn == CSSM_OK && CFArrayGetCount((CFArrayRef)ka)) { SecKeyRef sk = (SecKeyRef)CFArrayGetValueAtIndex((CFArrayRef)ka, 0); CFRetain(sk); CFRelease(ka); return sk; } else { if (error) { *error = CFErrorCreate(NULL, kCFErrorDomainOSStatus, crtn ? crtn : CSSM_ERRCODE_INTERNAL_ERROR, NULL); } return NULL; } }
CFErrorRef SFB::CreateError(CFStringRef domain, CFIndex code, CFStringRef description, CFStringRef failureReason, CFStringRef recoverySuggestion) { if(nullptr == domain) return nullptr; SFB::CFMutableDictionary errorDictionary(0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if(!errorDictionary) return nullptr; if(description) CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, description); if(failureReason) CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, failureReason); if(recoverySuggestion) CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, recoverySuggestion); return CFErrorCreate(kCFAllocatorDefault, domain, code, errorDictionary); }
CFStringRef SecTaskCopySigningIdentifier(SecTaskRef task, CFErrorRef *error) { CFStringRef signingId = NULL; char *data = NULL; struct csheader header; uint32_t bufferlen; int ret; ret = csops_task(task, CS_OPS_IDENTITY, &header, sizeof(header)); if (ret != -1 || errno != ERANGE) return NULL; bufferlen = ntohl(header.length); /* check for insane values */ if (bufferlen > 1024 * 1024 || bufferlen < 8) { ret = EINVAL; goto out; } data = malloc(bufferlen + 1); if (data == NULL) { ret = ENOMEM; goto out; } ret = csops_task(task, CS_OPS_IDENTITY, data, bufferlen); if (ret) { ret = errno; goto out; } data[bufferlen] = '\0'; signingId = CFStringCreateWithCString(NULL, data + 8, kCFStringEncodingUTF8); out: if (data) free(data); if (ret && error) *error = CFErrorCreate(NULL, kCFErrorDomainPOSIX, ret, NULL); return signingId; }
bool FileInputSource::Close(CFErrorRef *error) { if(!IsOpen()) { LOGGER_WARNING("org.sbooth.AudioEngine.InputSource.File", "Close() called on an InputSource that hasn't been opened"); return true; } memset(&mFilestats, 0, sizeof(mFilestats)); if(nullptr != mFile) { int result = fclose(mFile); mFile = nullptr; if(-1 == result) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, errno, nullptr); return false; } } mIsOpen = false; return true; }
OSStatus CSError::cfError(CFErrorRef *errors, OSStatus rc) { if (errors) *errors = CFErrorCreate(NULL, kCFErrorDomainOSStatus, rc, NULL); return rc; }
AudioDecoder * AudioDecoder::CreateDecoderForInputSource(InputSource *inputSource, CFStringRef mimeType, CFErrorRef *error) { if(NULL == inputSource) return NULL; AudioDecoder *decoder = NULL; // Open the input source if it isn't already if(AutomaticallyOpenDecoders() && !inputSource->IsOpen() && !inputSource->Open(error)) return NULL; // As a factory this class has knowledge of its subclasses // It would be possible (and perhaps preferable) to switch to a generic // plugin interface at a later date #if 0 // If the input is an instance of HTTPInputSource, use the MIME type from the server // This code is disabled because most HTTP servers don't send the correct MIME types HTTPInputSource *httpInputSource = dynamic_cast<HTTPInputSource *>(inputSource); bool releaseMIMEType = false; if(!mimeType && httpInputSource && httpInputSource->IsOpen()) { mimeType = httpInputSource->CopyContentMIMEType(); if(mimeType) releaseMIMEType = true; } #endif // The MIME type takes precedence over the file extension if(mimeType) { #if BUILD_FOR_MAC_OSX if(FLACDecoder::HandlesMIMEType(mimeType)) { decoder = new FLACDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && WavPackDecoder::HandlesMIMEType(mimeType)) { decoder = new WavPackDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && MPEGDecoder::HandlesMIMEType(mimeType)) { decoder = new MPEGDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && OggVorbisDecoder::HandlesMIMEType(mimeType)) { decoder = new OggVorbisDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && MusepackDecoder::HandlesMIMEType(mimeType)) { decoder = new MusepackDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && MonkeysAudioDecoder::HandlesMIMEType(mimeType)) { decoder = new MonkeysAudioDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && OggSpeexDecoder::HandlesMIMEType(mimeType)) { decoder = new OggSpeexDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && MODDecoder::HandlesMIMEType(mimeType)) { decoder = new MODDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && LibsndfileDecoder::HandlesMIMEType(mimeType)) { decoder = new LibsndfileDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } #endif if(NULL == decoder && CoreAudioDecoder::HandlesMIMEType(mimeType)) { decoder = new CoreAudioDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } #if 0 if(releaseMIMEType) CFRelease(mimeType), mimeType = NULL; #endif if(decoder) return decoder; } // If no MIME type was specified, use the extension-based resolvers CFURLRef inputURL = inputSource->GetURL(); if(!inputURL) return NULL; CFStringRef pathExtension = CFURLCopyPathExtension(inputURL); if(!pathExtension) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 32, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CFURLCopyLastPathComponent(inputURL); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The type of the file “%@” could not be determined."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Unknown file type"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may be missing or may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, InputSourceErrorDomain, InputSourceFileNotFoundError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } return NULL; } // TODO: Some extensions (.oga for example) support multiple audio codecs (Vorbis, FLAC, Speex) // and if openDecoder is false the wrong decoder type may be returned, since the file isn't analyzed // until Open() is called #if BUILD_FOR_MAC_OSX if(FLACDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new FLACDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && WavPackDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new WavPackDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && MPEGDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new MPEGDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && OggVorbisDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new OggVorbisDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && MusepackDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new MusepackDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && MonkeysAudioDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new MonkeysAudioDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && OggSpeexDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new OggSpeexDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && MODDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new MODDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } if(NULL == decoder && LibsndfileDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new LibsndfileDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } #endif if(NULL == decoder && CoreAudioDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new CoreAudioDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = NULL; delete decoder, decoder = NULL; } } CFRelease(pathExtension), pathExtension = NULL; return decoder; }
bool MonkeysAudioMetadata::ReadMetadata(CFErrorRef *error) { // Start from scratch CFDictionaryRemoveAllValues(mMetadata); CFDictionaryRemoveAllValues(mChangedMetadata); UInt8 buf [PATH_MAX]; if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX)) return false; TagLib::IOStream *stream = new TagLib::FileStream(reinterpret_cast<const char *>(buf), true); TagLib::APE::File file(stream); if(!file.isValid()) { if(NULL != error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mURL); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Monkey's Audio file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not a Monkey's Audio file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioMetadataErrorDomain, AudioMetadataInputOutputError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } return false; } CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("Monkey's Audio")); if(file.audioProperties()) { AddAudioPropertiesToDictionary(mMetadata, file.audioProperties()); if(0 != file.audioProperties()->bitsPerSample()) { int value = file.audioProperties()->bitsPerSample(); CFNumberRef bitsPerChannel = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &value); CFDictionarySetValue(mMetadata, kPropertiesBitsPerChannelKey, bitsPerChannel); CFRelease(bitsPerChannel), bitsPerChannel = NULL; } } if(file.ID3v1Tag()) AddID3v1TagToDictionary(mMetadata, file.ID3v1Tag()); if(file.APETag()) AddAPETagToDictionary(mMetadata, file.APETag()); return true; }
bool MonkeysAudioMetadata::WriteMetadata(CFErrorRef *error) { UInt8 buf [PATH_MAX]; if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX)) return false; TagLib::IOStream *stream = new TagLib::FileStream(reinterpret_cast<const char *>(buf)); TagLib::APE::File file(stream, false); if(!file.isValid()) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mURL); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Mpnkey's Audio file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not a Mpnkey's Audio file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioMetadataErrorDomain, AudioMetadataInputOutputError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } return false; } // Although both ID3v1 and APE tags are read, only APE tags are written if(file.APETag()) SetAPETagFromMetadata(*this, file.APETag()); if(!file.save()) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mURL); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Mpnkey's Audio file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Unable to write metadata"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioMetadataErrorDomain, AudioMetadataInputOutputError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } return false; } MergeChangedMetadataIntoMetadata(); return true; }
bool OggSpeexDecoder::Open(CFErrorRef *error) { if(IsOpen()) { LOGGER_WARNING("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Open() called on an AudioDecoder that is already open"); return true; } // Ensure the input source is open if(!mInputSource->IsOpen() && !mInputSource->Open(error)) return false; // Initialize Ogg data struct ogg_sync_init(&mOggSyncState); // Get the ogg buffer for writing char *data = ogg_sync_buffer(&mOggSyncState, READ_SIZE_BYTES); // Read bitstream from input file ssize_t bytesRead = GetInputSource()->Read(data, READ_SIZE_BYTES); if(-1 == bytesRead) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL()); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” could not be read."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Read error"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("Unable to read from the input file."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioDecoderErrorDomain, AudioDecoderInputOutputError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } ogg_sync_destroy(&mOggSyncState); return false; } // Tell the sync layer how many bytes were written to its internal buffer int result = ogg_sync_wrote(&mOggSyncState, bytesRead); if(-1 == result) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL()); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” does not appear to be an Ogg file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not an Ogg file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioDecoderErrorDomain, AudioDecoderFileFormatNotRecognizedError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } ogg_sync_destroy(&mOggSyncState); return false; } // Turn the data we wrote into an ogg page result = ogg_sync_pageout(&mOggSyncState, &mOggPage); if(1 != result) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL()); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” does not appear to be an Ogg file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not an Ogg file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioDecoderErrorDomain, AudioDecoderFileFormatNotRecognizedError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } ogg_sync_destroy(&mOggSyncState); return false; } // Initialize the stream and grab the serial number ogg_stream_init(&mOggStreamState, ogg_page_serialno(&mOggPage)); // Get the first Ogg page result = ogg_stream_pagein(&mOggStreamState, &mOggPage); if(0 != result) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL()); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” does not appear to be an Ogg file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not an Ogg file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioDecoderErrorDomain, AudioDecoderFileFormatNotRecognizedError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } ogg_sync_destroy(&mOggSyncState); return false; } // Get the first packet (should be the header) from the page ogg_packet op; result = ogg_stream_packetout(&mOggStreamState, &op); if(1 != result) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL()); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” does not appear to be an Ogg file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not an Ogg file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioDecoderErrorDomain, AudioDecoderFileFormatNotRecognizedError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } ogg_sync_destroy(&mOggSyncState); return false; } if(op.bytes >= 5 && !memcmp(op.packet, "Speex", 5)) mSpeexSerialNumber = mOggStreamState.serialno; ++mOggPacketCount; // Convert the packet to the Speex header SpeexHeader *header = speex_packet_to_header((char *)op.packet, static_cast<int>(op.bytes)); if(NULL == header) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL()); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The file “%@” does not appear to be an Ogg Speex file."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Not an Ogg Speex file"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioDecoderErrorDomain, AudioDecoderFileFormatNotRecognizedError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } ogg_sync_destroy(&mOggSyncState); return false; } else if(SPEEX_NB_MODES <= header->mode) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL()); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The Speex mode in the file “%@” is not supported."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Unsupported Ogg Speex file mode"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("This file may have been encoded with a newer version of Speex."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioDecoderErrorDomain, AudioDecoderFileFormatNotSupportedError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } speex_header_free(header), header = NULL; ogg_sync_destroy(&mOggSyncState); return false; } const SpeexMode *mode = speex_lib_get_mode(header->mode); if(mode->bitstream_version != header->mode_bitstream_version) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFStringRef displayName = CreateDisplayNameForURL(mInputSource->GetURL()); CFStringRef errorString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFCopyLocalizedString(CFSTR("The Speex version in the file “%@” is not supported."), ""), displayName); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, errorString); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedFailureReasonKey, CFCopyLocalizedString(CFSTR("Unsupported Ogg Speex file version"), "")); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedRecoverySuggestionKey, CFCopyLocalizedString(CFSTR("This file was encoded with a different version of Speex."), "")); CFRelease(errorString), errorString = NULL; CFRelease(displayName), displayName = NULL; *error = CFErrorCreate(kCFAllocatorDefault, AudioDecoderErrorDomain, AudioDecoderFileFormatNotSupportedError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } speex_header_free(header), header = NULL; ogg_sync_destroy(&mOggSyncState); return false; } // Initialize the decoder mSpeexDecoder = speex_decoder_init(mode); if(NULL== mSpeexDecoder) { if(error) { CFMutableDictionaryRef errorDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(errorDictionary, kCFErrorLocalizedDescriptionKey, CFCopyLocalizedString(CFSTR("Unable to initialize the Speex decoder."), "")); // CFDictionarySetValue(errorDictionary, // kCFErrorLocalizedFailureReasonKey, // CFCopyLocalizedString(CFSTR("Unsupported Ogg Speex file version"), "")); // CFDictionarySetValue(errorDictionary, // kCFErrorLocalizedRecoverySuggestionKey, // CFCopyLocalizedString(CFSTR("This file was encoded with a different version of Speex."), "")); *error = CFErrorCreate(kCFAllocatorDefault, AudioDecoderErrorDomain, AudioDecoderInputOutputError, errorDictionary); CFRelease(errorDictionary), errorDictionary = NULL; } speex_header_free(header), header = NULL; ogg_sync_destroy(&mOggSyncState); return false; } speex_decoder_ctl(mSpeexDecoder, SPEEX_SET_SAMPLING_RATE, &header->rate); mSpeexFramesPerOggPacket = (0 == header->frames_per_packet ? 1 : header->frames_per_packet); mExtraSpeexHeaderCount = header->extra_headers; // Initialize the speex bit-packing data structure speex_bits_init(&mSpeexBits); // Initialize the stereo mode mSpeexStereoState = speex_stereo_state_init(); if(2 == header->nb_channels) { SpeexCallback callback; callback.callback_id = SPEEX_INBAND_STEREO; callback.func = speex_std_stereo_request_handler; callback.data = mSpeexStereoState; speex_decoder_ctl(mSpeexDecoder, SPEEX_SET_HANDLER, &callback); } // Canonical Core Audio format mFormat.mFormatID = kAudioFormatLinearPCM; mFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; mFormat.mBitsPerChannel = 8 * sizeof(float); mFormat.mSampleRate = header->rate; mFormat.mChannelsPerFrame = header->nb_channels; mFormat.mBytesPerPacket = (mFormat.mBitsPerChannel / 8); mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mFormat.mReserved = 0; // Set up the source format mSourceFormat.mFormatID = 'SPEE'; mSourceFormat.mSampleRate = header->rate; mSourceFormat.mChannelsPerFrame = header->nb_channels; switch(header->nb_channels) { case 1: mChannelLayout = CreateChannelLayoutWithTag(kAudioChannelLayoutTag_Mono); break; case 2: mChannelLayout = CreateChannelLayoutWithTag(kAudioChannelLayoutTag_Stereo); break; } speex_header_free(header), header = NULL; // Allocate the buffer list spx_int32_t speexFrameSize = 0; speex_decoder_ctl(mSpeexDecoder, SPEEX_GET_FRAME_SIZE, &speexFrameSize); mBufferList = AllocateABL(mFormat, speexFrameSize); if(NULL == mBufferList) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); speex_header_free(header), header = NULL; speex_stereo_state_destroy(mSpeexStereoState), mSpeexStereoState = NULL; speex_decoder_destroy(mSpeexDecoder), mSpeexDecoder = NULL; speex_bits_destroy(&mSpeexBits); ogg_sync_destroy(&mOggSyncState); return false; } for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i) mBufferList->mBuffers[i].mDataByteSize = 0; mIsOpen = true; return true; }
bool MemoryMappedFileInputSource::Open(CFErrorRef *error) { if(IsOpen()) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.InputSource.MemoryMappedFile"); LOG4CXX_WARN(logger, "Open() called on an InputSource that is already open"); return true; } UInt8 buf [PATH_MAX]; Boolean success = CFURLGetFileSystemRepresentation(mURL, FALSE, buf, PATH_MAX); if(!success) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, EIO, NULL); return false; } int fd = open(reinterpret_cast<const char *>(buf), O_RDONLY); if(-1 == fd) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, errno, NULL); return false; } if(-1 == fstat(fd, &mFilestats)) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, errno, NULL); if(-1 == close(fd)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.InputSource.MemoryMappedFile"); LOG4CXX_WARN(logger, "Unable to close the file: " << strerror(errno)); } return false; } // Only regular files can be mapped if(!S_ISREG(mFilestats.st_mode)) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, EBADF, NULL); if(-1 == close(fd)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.InputSource.MemoryMappedFile"); LOG4CXX_WARN(logger, "Unable to close the file: " << strerror(errno)); } memset(&mFilestats, 0, sizeof(mFilestats)); return false; } mMemory = static_cast<int8_t *>(mmap(0, mFilestats.st_size, PROT_READ, MAP_FILE | MAP_SHARED, fd, 0)); if(MAP_FAILED == mMemory) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, errno, NULL); if(-1 == close(fd)) { log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("org.sbooth.AudioEngine.InputSource.MemoryMappedFile"); LOG4CXX_WARN(logger, "Unable to close the file: " << strerror(errno)); } memset(&mFilestats, 0, sizeof(mFilestats)); return false; } if(-1 == close(fd)) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, errno, NULL); memset(&mFilestats, 0, sizeof(mFilestats)); return false; } mCurrentPosition = mMemory; mIsOpen = true; return true; }
bool SFB::Audio::MusepackDecoder::_Open(CFErrorRef *error) { UInt8 buf [PATH_MAX]; if(!CFURLGetFileSystemRepresentation(mInputSource->GetURL(), FALSE, buf, PATH_MAX)) return false; mReader.read = read_callback; mReader.seek = seek_callback; mReader.tell = tell_callback; mReader.get_size = get_size_callback; mReader.canseek = canseek_callback; mReader.data = this; mDemux = mpc_demux_init(&mReader); if(nullptr == mDemux) { if(error) { SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Musepack file."), ""); SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Not a Musepack file"), ""); SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""); *error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion); } mpc_reader_exit_stdio(&mReader); return false; } // Get input file information mpc_streaminfo streaminfo; mpc_demux_get_info(mDemux, &streaminfo); mTotalFrames = mpc_streaminfo_get_length_samples(&streaminfo); // Canonical Core Audio format mFormat.mFormatID = kAudioFormatLinearPCM; mFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; mFormat.mSampleRate = streaminfo.sample_freq; mFormat.mChannelsPerFrame = streaminfo.channels; mFormat.mBitsPerChannel = 8 * sizeof(float); mFormat.mBytesPerPacket = (mFormat.mBitsPerChannel / 8); mFormat.mFramesPerPacket = 1; mFormat.mBytesPerFrame = mFormat.mBytesPerPacket * mFormat.mFramesPerPacket; mFormat.mReserved = 0; // Set up the source format mSourceFormat.mFormatID = 'MUSE'; mSourceFormat.mSampleRate = streaminfo.sample_freq; mSourceFormat.mChannelsPerFrame = streaminfo.channels; mSourceFormat.mFramesPerPacket = (1 << streaminfo.block_pwr); // Setup the channel layout switch(streaminfo.channels) { case 1: mChannelLayout = ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Mono); break; case 2: mChannelLayout = ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Stereo); break; case 4: mChannelLayout = ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Quadraphonic); break; } // Allocate the buffer list if(!mBufferList.Allocate(mFormat, MPC_FRAME_LENGTH)) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, nullptr); mpc_demux_exit(mDemux), mDemux = nullptr; mpc_reader_exit_stdio(&mReader); return false; } for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i) mBufferList->mBuffers[i].mDataByteSize = 0; return true; }
// // Convert exception-carried error information to CFError form // OSStatus CSError::cfError(CFErrorRef *errors) const { if (errors) // errors argument was specified *errors = CFErrorCreate(NULL, kCFErrorDomainOSStatus, this->osStatus(), this->infoDict()); return this->osStatus(); }
ResourceError SynchronousLoaderClient::platformBadResponseError() { RetainPtr<CFErrorRef> cfError = adoptCF(CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainCFNetwork, kCFURLErrorBadServerResponse, 0)); return cfError.get(); }