bool WavPackMetadata::ReadMetadata(CFErrorRef *error) { // Start from scratch CFDictionaryRemoveAllValues(mMetadata); CFDictionaryRemoveAllValues(mChangedMetadata); UInt8 buf [PATH_MAX]; if(!CFURLGetFileSystemRepresentation(mURL, FALSE, buf, PATH_MAX)) return false; auto stream = new TagLib::FileStream(reinterpret_cast<const char *>(buf), true); TagLib::WavPack::File file(stream); if(!file.isValid()) { if(nullptr != error) { CFStringRef description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid WavPack file."), ""); CFStringRef failureReason = CFCopyLocalizedString(CFSTR("Not a WavPack file"), ""); CFStringRef recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""); *error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion); CFRelease(description), description = nullptr; CFRelease(failureReason), failureReason = nullptr; CFRelease(recoverySuggestion), recoverySuggestion = nullptr; } return false; } CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("WavPack")); if(file.audioProperties()) { auto properties = file.audioProperties(); AddAudioPropertiesToDictionary(mMetadata, properties); if(properties->bitsPerSample()) AddIntToDictionary(mMetadata, kPropertiesBitsPerChannelKey, properties->bitsPerSample()); if(properties->sampleFrames()) AddIntToDictionary(mMetadata, kPropertiesTotalFramesKey, properties->sampleFrames()); } if(file.ID3v1Tag()) AddID3v1TagToDictionary(mMetadata, file.ID3v1Tag()); if(file.APETag()) { std::vector<AttachedPicture *> pictures; AddAPETagToDictionary(mMetadata, pictures, file.APETag()); for(auto picture : pictures) AddSavedPicture(picture); } return true; }
bool SFB::Audio::TrueAudioMetadata::_ReadMetadata(CFErrorRef *error) { UInt8 buf [PATH_MAX]; if(!CFURLGetFileSystemRepresentation(mURL, FALSE, buf, PATH_MAX)) return false; std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf, true)); if(!stream->isOpen()) { if(error) { SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), ""); SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Input/output error"), ""); SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), ""); *error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion); } return false; } TagLib::TrueAudio::File file(stream.get()); if(!file.isValid()) { if(nullptr != error) { SFB::CFString description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid True Audio file."), ""); SFB::CFString failureReason = CFCopyLocalizedString(CFSTR("Not a True Audio file"), ""); SFB::CFString recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""); *error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion); } return false; } CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("True Audio")); if(file.audioProperties()) { auto properties = file.audioProperties(); AddAudioPropertiesToDictionary(mMetadata, properties); if(properties->bitsPerSample()) AddIntToDictionary(mMetadata, kBitsPerChannelKey, properties->bitsPerSample()); if(properties->sampleFrames()) AddIntToDictionary(mMetadata, kTotalFramesKey, (int)properties->sampleFrames()); } // Add all tags that are present if(file.ID3v1Tag()) AddID3v1TagToDictionary(mMetadata, file.ID3v1Tag()); if(file.ID3v2Tag()) AddID3v2TagToDictionary(mMetadata, mPictures, file.ID3v2Tag()); return true; }
bool TrueAudioMetadata::ReadMetadata(CFErrorRef *error) { // Start from scratch CFDictionaryRemoveAllValues(mMetadata); CFDictionaryRemoveAllValues(mChangedMetadata); UInt8 buf [PATH_MAX]; if(!CFURLGetFileSystemRepresentation(mURL, FALSE, buf, PATH_MAX)) return false; // TODO: Use unique_ptr once the switch to C++11 STL is made std::auto_ptr<TagLib::FileStream> stream(new TagLib::FileStream(reinterpret_cast<const char *>(buf), true)); if(!stream->isOpen()) { if(error) { CFStringRef description = CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), ""); CFStringRef failureReason = CFCopyLocalizedString(CFSTR("Input/output error"), ""); CFStringRef recoverySuggestion = CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), ""); *error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion); CFRelease(description), description = nullptr; CFRelease(failureReason), failureReason = nullptr; CFRelease(recoverySuggestion), recoverySuggestion = nullptr; } return false; } TagLib::TrueAudio::File file(stream.get()); if(!file.isValid()) { if(nullptr != error) { CFStringRef description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid True Audio file."), ""); CFStringRef failureReason = CFCopyLocalizedString(CFSTR("Not a True Audio file"), ""); CFStringRef recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""); *error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion); CFRelease(description), description = nullptr; CFRelease(failureReason), failureReason = nullptr; CFRelease(recoverySuggestion), recoverySuggestion = nullptr; } return false; } CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("True Audio")); if(file.audioProperties()) { auto properties = file.audioProperties(); AddAudioPropertiesToDictionary(mMetadata, properties); if(properties->bitsPerSample()) AddIntToDictionary(mMetadata, kPropertiesBitsPerChannelKey, properties->bitsPerSample()); if(properties->sampleFrames()) AddIntToDictionary(mMetadata, kPropertiesTotalFramesKey, properties->sampleFrames()); } // Add all tags that are present if(file.ID3v1Tag()) AddID3v1TagToDictionary(mMetadata, file.ID3v1Tag()); if(file.ID3v2Tag()) { std::vector<AttachedPicture *> pictures; AddID3v2TagToDictionary(mMetadata, pictures, file.ID3v2Tag()); for(auto picture : pictures) AddSavedPicture(picture); } return true; }
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 SFB::Audio::MP3Metadata::_ReadMetadata(CFErrorRef *error) { UInt8 buf [PATH_MAX]; if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX)) return false; std::unique_ptr<TagLib::FileStream> stream(new TagLib::FileStream((const char *)buf, true)); if(!stream->isOpen()) { if(error) { SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” could not be opened for reading."), "")); SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Input/output error"), "")); SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file may have been renamed, moved, deleted, or you may not have appropriate permissions."), "")); *error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion); } return false; } TagLib::MPEG::File file(stream.get(), TagLib::ID3v2::FrameFactory::instance()); if(!file.isValid()) { if(nullptr != error) { SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MPEG file."), "")); SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an MPEG file"), "")); SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), "")); *error = CreateErrorForURL(Metadata::ErrorDomain, Metadata::InputOutputError, description, mURL, failureReason, recoverySuggestion); } return false; } CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("MP3")); if(file.audioProperties()) { auto properties = file.audioProperties(); AddAudioPropertiesToDictionary(mMetadata, properties); // TODO: Is this too much information? #if 0 switch(properties->version()) { case TagLib::MPEG::Header::Version1: switch(properties->layer()) { case 1: CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("MPEG-1 Layer I")); break; case 2: CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("MPEG-1 Layer II")); break; case 3: CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("MPEG-1 Layer III")); break; } break; case TagLib::MPEG::Header::Version2: switch(properties->layer()) { case 1: CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("MPEG-2 Layer I")); break; case 2: CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("MPEG-2 Layer II")); break; case 3: CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("MPEG-2 Layer III")); break; } break; case TagLib::MPEG::Header::Version2_5: switch(properties->layer()) { case 1: CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("MPEG-2.5 Layer I")); break; case 2: CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("MPEG-2.5 Layer II")); break; case 3: CFDictionarySetValue(mMetadata, kFormatNameKey, CFSTR("MPEG-2.5 Layer III")); break; } break; } #endif if(properties->xingHeader() && properties->xingHeader()->totalFrames()) AddIntToDictionary(mMetadata, kTotalFramesKey, (int)properties->xingHeader()->totalFrames()); } if(file.APETag()) AddAPETagToDictionary(mMetadata, mPictures, file.APETag()); if(file.ID3v1Tag()) AddID3v1TagToDictionary(mMetadata, file.ID3v1Tag()); if(file.ID3v2Tag()) AddID3v2TagToDictionary(mMetadata, mPictures, file.ID3v2Tag()); return true; }
bool FLACMetadata::ReadMetadata(CFErrorRef *error) { // Start from scratch CFDictionaryRemoveAllValues(mMetadata); CFDictionaryRemoveAllValues(mChangedMetadata); UInt8 buf [PATH_MAX]; if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX)) return false; auto stream = new TagLib::FileStream(reinterpret_cast<const char *>(buf), true); TagLib::FLAC::File file(stream, TagLib::ID3v2::FrameFactory::instance()); if(!file.isValid()) { if(nullptr != error) { CFStringRef description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid FLAC file."), ""); CFStringRef failureReason = CFCopyLocalizedString(CFSTR("Not a FLAC file"), ""); CFStringRef recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""); *error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion); CFRelease(description), description = nullptr; CFRelease(failureReason), failureReason = nullptr; CFRelease(recoverySuggestion), recoverySuggestion = nullptr; } return false; } CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("FLAC")); if(file.audioProperties()) { auto properties = file.audioProperties(); AddAudioPropertiesToDictionary(mMetadata, properties); if(properties->sampleWidth()) AddIntToDictionary(mMetadata, kPropertiesBitsPerChannelKey, properties->sampleWidth()); if(properties->sampleFrames()) AddLongLongToDictionary(mMetadata, kPropertiesTotalFramesKey, properties->sampleFrames()); } // Add all tags that are present if(file.ID3v1Tag()) AddID3v1TagToDictionary(mMetadata, file.ID3v1Tag()); if(file.ID3v2Tag()) { std::vector<AttachedPicture *> pictures; AddID3v2TagToDictionary(mMetadata, pictures, file.ID3v2Tag()); for(auto picture : pictures) AddSavedPicture(picture); } if(file.xiphComment()) { std::vector<AttachedPicture *> pictures; AddXiphCommentToDictionary(mMetadata, pictures, file.xiphComment()); for(auto picture : pictures) AddSavedPicture(picture); } // Add album art for(auto iter : file.pictureList()) { CFDataRef data = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(iter->data().data()), iter->data().size()); CFStringRef description = nullptr; if(!iter->description().isNull()) description = CFStringCreateWithCString(kCFAllocatorDefault, iter->description().toCString(true), kCFStringEncodingUTF8); AttachedPicture *picture = new AttachedPicture(data, static_cast<AttachedPicture::Type>(iter->type()), description); AddSavedPicture(picture); if(data) CFRelease(data), data = nullptr; if(description) CFRelease(description), description = nullptr; } return true; }
bool MP3Metadata::ReadMetadata(CFErrorRef *error) { // Start from scratch CFDictionaryRemoveAllValues(mMetadata); CFDictionaryRemoveAllValues(mChangedMetadata); UInt8 buf [PATH_MAX]; if(!CFURLGetFileSystemRepresentation(mURL, false, buf, PATH_MAX)) return false; auto stream = new TagLib::FileStream(reinterpret_cast<const char *>(buf), true); TagLib::MPEG::File file(stream, TagLib::ID3v2::FrameFactory::instance()); if(!file.isValid()) { if(nullptr != error) { CFStringRef description = CFCopyLocalizedString(CFSTR("The file “%@” is not a valid MPEG file."), ""); CFStringRef failureReason = CFCopyLocalizedString(CFSTR("Not an MPEG file"), ""); CFStringRef recoverySuggestion = CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""); *error = CreateErrorForURL(AudioMetadataErrorDomain, AudioMetadataInputOutputError, description, mURL, failureReason, recoverySuggestion); CFRelease(description), description = nullptr; CFRelease(failureReason), failureReason = nullptr; CFRelease(recoverySuggestion), recoverySuggestion = nullptr; } return false; } CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MP3")); if(file.audioProperties()) { auto properties = file.audioProperties(); AddAudioPropertiesToDictionary(mMetadata, properties); // TODO: Is this too much information? #if 0 switch(properties->version()) { case TagLib::MPEG::Header::Version1: switch(properties->layer()) { case 1: CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-1 Layer I")); break; case 2: CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-1 Layer II")); break; case 3: CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-1 Layer III")); break; } break; case TagLib::MPEG::Header::Version2: switch(properties->layer()) { case 1: CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-2 Layer I")); break; case 2: CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-2 Layer II")); break; case 3: CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-2 Layer III")); break; } break; case TagLib::MPEG::Header::Version2_5: switch(properties->layer()) { case 1: CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-2.5 Layer I")); break; case 2: CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-2.5 Layer II")); break; case 3: CFDictionarySetValue(mMetadata, kPropertiesFormatNameKey, CFSTR("MPEG-2.5 Layer III")); break; } break; } #endif if(properties->xingHeader() && properties->xingHeader()->totalFrames()) AddIntToDictionary(mMetadata, kPropertiesTotalFramesKey, properties->xingHeader()->totalFrames()); } if(file.APETag()) { std::vector<AttachedPicture *> pictures; AddAPETagToDictionary(mMetadata, pictures, file.APETag()); for(auto picture : pictures) AddSavedPicture(picture); } if(file.ID3v1Tag()) AddID3v1TagToDictionary(mMetadata, file.ID3v1Tag()); if(file.ID3v2Tag()) { std::vector<AttachedPicture *> pictures; AddID3v2TagToDictionary(mMetadata, pictures, file.ID3v2Tag()); for(auto picture : pictures) AddSavedPicture(picture); } return true; }