CFURLRef Caching_Stream::createFileURLWithPath(CFStringRef path) { CFURLRef regularUrl = CFURLCreateWithString(kCFAllocatorDefault, path, NULL); CFURLRef fileUrl = CFURLCreateFilePathURL(kCFAllocatorDefault, regularUrl, NULL); CFRelease(regularUrl); return fileUrl; }
CFURLRef Caching_Stream::createFileURLWithPath(CFStringRef path) { CFURLRef fileUrl = NULL; if (!path) { return fileUrl; } CFStringRef escapedPath = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, path, NULL, NULL, kCFStringEncodingUTF8); CFURLRef regularUrl = CFURLCreateWithString(kCFAllocatorDefault, (escapedPath ? escapedPath : path), NULL); if (regularUrl) { fileUrl = CFURLCreateFilePathURL(kCFAllocatorDefault, regularUrl, NULL); CFRelease(regularUrl); } if (escapedPath) { CFRelease(escapedPath); } return fileUrl; }
QString absolutePathFromOSX(const QString& s) { QString result; #if !(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1060) CFStringRef cfStr = CFStringCreateWithCString(kCFAllocatorDefault, s.toUtf8().constData(), kCFStringEncodingUTF8); if (cfStr) { CFURLRef cfUrl = CFURLCreateWithString(kCFAllocatorDefault, cfStr, NULL); if (cfUrl) { CFErrorRef error = 0; CFURLRef cfUrlAbs = CFURLCreateFilePathURL(kCFAllocatorDefault, cfUrl, &error); if (cfUrlAbs) { CFStringRef cfStrAbsUrl = CFURLGetString(cfUrlAbs); result = fromCFString(cfStrAbsUrl); CFRelease(cfUrlAbs); } CFRelease(cfUrl); } CFRelease(cfStr); } #else Q_UNUSED(s); #endif return result; }
AudioDecoder * AudioDecoder::CreateDecoderForInputSource(InputSource *inputSource, CFStringRef mimeType, CFErrorRef *error) { if(nullptr == inputSource) return nullptr; AudioDecoder *decoder = nullptr; // Open the input source if it isn't already if(AutomaticallyOpenDecoders() && !inputSource->IsOpen() && !inputSource->Open(error)) return nullptr; // 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(FLACDecoder::HandlesMIMEType(mimeType)) { decoder = new FLACDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && WavPackDecoder::HandlesMIMEType(mimeType)) { decoder = new WavPackDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && MPEGDecoder::HandlesMIMEType(mimeType)) { decoder = new MPEGDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && OggVorbisDecoder::HandlesMIMEType(mimeType)) { decoder = new OggVorbisDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && OggSpeexDecoder::HandlesMIMEType(mimeType)) { decoder = new OggSpeexDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } #if !TARGET_OS_IPHONE if(nullptr == decoder && MusepackDecoder::HandlesMIMEType(mimeType)) { decoder = new MusepackDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && MonkeysAudioDecoder::HandlesMIMEType(mimeType)) { decoder = new MonkeysAudioDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && MODDecoder::HandlesMIMEType(mimeType)) { decoder = new MODDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && TrueAudioDecoder::HandlesMIMEType(mimeType)) { decoder = new TrueAudioDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && LibsndfileDecoder::HandlesMIMEType(mimeType)) { decoder = new LibsndfileDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } #endif if(nullptr == decoder && CoreAudioDecoder::HandlesMIMEType(mimeType)) { decoder = new CoreAudioDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } #if 0 if(releaseMIMEType) CFRelease(mimeType), mimeType = nullptr; #endif if(decoder) return decoder; } // If no MIME type was specified, use the extension-based resolvers CFURLRef inputURL = inputSource->GetURL(); if(!inputURL) return nullptr; // Determining the extension isn't as simple as using CFURLCopyPathExtension (wouldn't that be nice?), // because although the behavior on Lion works like one would expect, on Snow Leopard it returns // a number that I believe is part of the inode number, but is definitely NOT the extension CFStringRef pathExtension = nullptr; #if !TARGET_OS_IPHONE CFURLRef filePathURL = CFURLCreateFilePathURL(kCFAllocatorDefault, inputURL, nullptr); if(filePathURL) { pathExtension = CFURLCopyPathExtension(filePathURL); CFRelease(filePathURL), filePathURL = nullptr; } else #endif pathExtension = CFURLCopyPathExtension(inputURL); if(!pathExtension) { if(error) { CFStringRef description = CFCopyLocalizedString(CFSTR("The type of the file “%@” could not be determined."), ""); CFStringRef failureReason = CFCopyLocalizedString(CFSTR("Unknown file type"), ""); CFStringRef recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may be missing or may not match the file's type."), ""); *error = CreateErrorForURL(InputSourceErrorDomain, InputSourceFileNotFoundError, description, inputURL, failureReason, recoverySuggestion); CFRelease(description), description = nullptr; CFRelease(failureReason), failureReason = nullptr; CFRelease(recoverySuggestion), recoverySuggestion = nullptr; } return nullptr; } // 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(FLACDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new FLACDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && WavPackDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new WavPackDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && MPEGDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new MPEGDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && OggVorbisDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new OggVorbisDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && OggSpeexDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new OggSpeexDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } #if !TARGET_OS_IPHONE if(nullptr == decoder && MusepackDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new MusepackDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && MonkeysAudioDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new MonkeysAudioDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && MODDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new MODDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && TrueAudioDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new TrueAudioDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } if(nullptr == decoder && LibsndfileDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new LibsndfileDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } #endif if(nullptr == decoder && CoreAudioDecoder::HandlesFilesWithExtension(pathExtension)) { decoder = new CoreAudioDecoder(inputSource); if(AutomaticallyOpenDecoders() && !decoder->Open(error)) { decoder->mInputSource = nullptr; delete decoder, decoder = nullptr; } } CFRelease(pathExtension), pathExtension = nullptr; return decoder; }
// Resolve a path and append it to the CLI settings structure // The FSEvents API will, internally, resolve paths using a similar scheme. // Performing this ahead of time makes things less confusing, IMHO. static void append_path(const char* path) { #ifdef DEBUG fprintf(stderr, "\n"); fprintf(stderr, "append_path called for: %s\n", path); #endif #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 #ifdef DEBUG fprintf(stderr, "compiled against 10.6+, using CFURLCreateFileReferenceURL\n"); #endif CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8*)path, (CFIndex)strlen(path), false); CFURLRef placeholder = CFURLCopyAbsoluteURL(url); CFRelease(url); CFMutableArrayRef imaginary = NULL; // if we don't have an existing url, spin until we get to a parent that // does exist, saving any imaginary components for appending back later while(!CFURLResourceIsReachable(placeholder, NULL)) { #ifdef DEBUG fprintf(stderr, "path does not exist\n"); #endif CFStringRef child; if (imaginary == NULL) { imaginary = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); } child = CFURLCopyLastPathComponent(placeholder); CFArrayInsertValueAtIndex(imaginary, 0, child); CFRelease(child); url = CFURLCreateCopyDeletingLastPathComponent(NULL, placeholder); CFRelease(placeholder); placeholder = url; #ifdef DEBUG fprintf(stderr, "parent: "); CFShow(placeholder); #endif } #ifdef DEBUG fprintf(stderr, "path exists\n"); #endif // realpath() doesn't always return the correct case for a path, so this // is a funky workaround that converts a path into a (volId/inodeId) pair // and asks what the path should be for that. since it looks at the actual // inode instead of returning the same case passed in like realpath() // appears to do for HFS+, it should always be correct. url = CFURLCreateFileReferenceURL(NULL, placeholder, NULL); CFRelease(placeholder); placeholder = CFURLCreateFilePathURL(NULL, url, NULL); CFRelease(url); #ifdef DEBUG fprintf(stderr, "path resolved to: "); CFShow(placeholder); #endif // if we stripped off any imaginary path components, append them back on if (imaginary != NULL) { CFIndex count = CFArrayGetCount(imaginary); for (CFIndex i = 0; i<count; i++) { CFStringRef component = CFArrayGetValueAtIndex(imaginary, i); #ifdef DEBUG fprintf(stderr, "appending component: "); CFShow(component); #endif url = CFURLCreateCopyAppendingPathComponent(NULL, placeholder, component, false); CFRelease(placeholder); placeholder = url; } CFRelease(imaginary); } #ifdef DEBUG fprintf(stderr, "result: "); CFShow(placeholder); #endif CFStringRef cfPath = CFURLCopyFileSystemPath(placeholder, kCFURLPOSIXPathStyle); CFArrayAppendValue(config.paths, cfPath); CFRelease(cfPath); CFRelease(placeholder); #else #ifdef DEBUG fprintf(stderr, "compiled against 10.5, using realpath()\n"); #endif char fullPath[PATH_MAX + 1]; if (realpath(path, fullPath) == NULL) { #ifdef DEBUG fprintf(stderr, " realpath not directly resolvable from path\n"); #endif if (path[0] != '/') { #ifdef DEBUG fprintf(stderr, " passed path is not absolute\n"); #endif size_t len; getcwd(fullPath, sizeof(fullPath)); #ifdef DEBUG fprintf(stderr, " result of getcwd: %s\n", fullPath); #endif len = strlen(fullPath); fullPath[len] = '/'; strlcpy(&fullPath[len + 1], path, sizeof(fullPath) - (len + 1)); } else { #ifdef DEBUG fprintf(stderr, " assuming path does not YET exist\n"); #endif strlcpy(fullPath, path, sizeof(fullPath)); } } #ifdef DEBUG fprintf(stderr, " resolved path to: %s\n", fullPath); fprintf(stderr, "\n"); #endif CFStringRef pathRef = CFStringCreateWithCString(kCFAllocatorDefault, fullPath, kCFStringEncodingUTF8); CFArrayAppendValue(config.paths, pathRef); CFRelease(pathRef); #endif }