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; }
// Inserts the default entries into mDefaultEntries. Also registers the the // standard IFD dir (IFD pointer) tags void ExifImageFile::setupDefaults( void ) { if ( mDefaultEntries.size() != 0 ) return ; // Bits per Sample std::vector<uint16> bitsPerSample(3, 8) ; ExifTagEntry *tagEntry = new ExifTagEntryT<std::vector<uint16> > ( EXIFTAG_BITSPERSAMPLE, EXIF_SHORT, 3, bitsPerSample ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type ( tagEntry->getTagNum(), tagEntry ) ); // Orientation - CONDITIONALLY MANDATORY, REQUIRED IF SUPPORTED BY HARDWARE tagEntry = new ExifTagEntryT<uint16> ( EXIFTAG_ORIENTATION, EXIF_SHORT, 1, 1 ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); // Samples per Pixel - MANDATORY FOR UNCOMPRESSED -- NOT RECORDED for // COMPRESSED tagEntry = new ExifTagEntryT<uint16> ( EXIFTAG_SAMPLESPERPIXEL, EXIF_SHORT, 1, 3 ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); // Rows per Strip - MANDATORY FOR UNCOMPRESSED -- NOT RECORDED for // COMPRESSED tagEntry = new ExifTagEntryT<exif_uint32> ( EXIFTAG_ROWSPERSTRIP, EXIF_LONG, 1, UINT_MAX ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); // X Resolution - MANDATORY FOR UNCOMPRESSED and COMPRESSED tagEntry = new ExifTagEntryT<float> ( EXIFTAG_XRESOLUTION, EXIF_RATIONAL, 1, 72 ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); // Y Resolution - MANDATORY FOR UNCOMPRESSED and COMPRESSED tagEntry = new ExifTagEntryT<float> ( EXIFTAG_YRESOLUTION, EXIF_RATIONAL, 1, 72 ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); // Planar Configuration - MANDATORY FOR UNCOMPRESSED tagEntry = new ExifTagEntryT<uint16> ( EXIFTAG_PLANARCONFIG, EXIF_SHORT, 1, 1 ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); // Resolution Unit - MANDATORY FOR UNCOMPRESSED and COMPRESSED tagEntry = new ExifTagEntryT<uint16> ( EXIFTAG_RESOLUTIONUNIT, EXIF_SHORT, 1, 2 ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); // YCbCr Positioning - MANDATORY for UNCOMPRESSES YCC and COMPRESSED tagEntry = new ExifTagEntryT<uint16> ( EXIFTAG_YCBCRPOSITIONING, EXIF_SHORT, 1, 1 ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); // Exif Version - Exif IFD MANDATORY for UNCOMPRESSES and COMPRESSED std::vector<int8> byteVec ; byteVec.push_back( '0' ) ; byteVec.push_back( '2' ) ; byteVec.push_back( '1' ) ; byteVec.push_back( '0' ) ; tagEntry = new ExifTagEntryT<std::vector<int8> > ( EXIFTAG_EXIFVERSION, EXIF_UNDEFINED, byteVec.size(), byteVec ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); // FlashPix Version - Exif IFD MANDATORY for UNCOMPRESSES and COMPRESSED byteVec.erase( byteVec.begin(), byteVec.end() ) ; byteVec.push_back( '0' ) ; byteVec.push_back( '1' ) ; byteVec.push_back( '0' ) ; byteVec.push_back( '0' ) ; tagEntry = new ExifTagEntryT<std::vector<int8> > ( EXIFTAG_FLASHPIXVERSION, EXIF_UNDEFINED, byteVec.size(), byteVec ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); // Components Configuration - Exif IFD MANDATORY for UNCOMPRESSES and // COMPRESSED byteVec.erase( byteVec.begin(), byteVec.end() ) ; byteVec.push_back( 1 ) ; byteVec.push_back( 2 ) ; byteVec.push_back( 3 ) ; byteVec.push_back( 0 ) ; tagEntry = new ExifTagEntryT<std::vector<int8> > ( EXIFTAG_COMPONENTSCONFIGURATION, EXIF_UNDEFINED, byteVec.size(), byteVec ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); // Color Space - Exif IFD MANDATORY for UNCOMPRESSES and COMPRESSED tagEntry = new ExifTagEntryT<uint16> ( EXIFTAG_COLORSPACE, EXIF_SHORT, 1, 1 ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); // Pixel X Dimension - Exif IFD MANDATORY for COMPRESSED tagEntry = new ExifTagEntryT<exif_uint32> ( EXIFTAG_PIXELXDIMENSION, EXIF_LONG, 1, 0 ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); // Pixel Y Dimension - Exif IFD MANDATORY for COMPRESSED tagEntry = new ExifTagEntryT<exif_uint32> ( EXIFTAG_PIXELYDIMENSION, EXIF_LONG, 1, 0 ); mDefaultEntries.insert( ExifIFD::EntryMap::value_type (tagEntry->getTagNum(), tagEntry ) ); return ; }
qint32 cMediaInfo::writeFilename() { QSqlQuery query; query.prepare("SELECT id FROM file WHERE fileName=:fileName AND fileSize=:fileSize AND fileDate=:fileDate;"); query.bindValue(":fileName", fileName()); query.bindValue(":fileSize", fileSize()); query.bindValue(":fileDate", fileDate()); if(!query.exec()) { myDebug << query.lastError().text(); return(-1); } if(query.next()) query.prepare("UPDATE file SET fileType=:fileType, length=:length, bitrate=:bitrate, sampleRate=:sampleRate, channels=:channels, bitsPerSample=:bitsPerSample, layer=:layer, version=:version, sampleWidth=:sampleWidth, sampleFrames=:sampleFrames, isEncrypted=:isEncrypted, trackGain=:trackGain, albumGain=:albumGain, trackPeak=:trackPeak, albumPeak=:albumPeak, protectionEnabled=:protectionEnabled, channelMode=:channelMode, isCopyrighted=:isCopyrighted, isOriginal=:isOriginal, album=:album, title=:title, copyright=:copyright, trackNumber=:trackNumber, contentGroupDescription=:contentGroupDescription, subTitle=:subTitle, originalAlbum=:originalAlbum, partOfSet=:partOfSet, subTitleOfSet=:subTitleOfSet, internationalStandardRecordingCode=:internationalStandardRecordingCode, leadArtist=:leadArtist, band=:band, conductor=:conductor, interpret=:interpret, originalArtist=:originalArtist, textWriter=:textWriter, originalTextWriter=:originalTextWriter, composer=:composer, encodedBy=:encodedBy, beatsPerMinute=:beatsPerMinute, language=:language, contentType=:contentType, mediaType=:mediaType, mood=:mood, producedNotice=:producedNotice, publisher=:publisher, fileOwner=:fileOwner, internetRadioStationName=:internetRadioStationName, internetRadioStationOwner=:internetRadioStationOwner, originalFilename=:originalFilename, playlistDelay=:playlistDelay, encodingTime=:encodingTime, originalReleaseTime=:originalReleaseTime, recordingTime=:recordingTime, releaseTime=:releaseTime, taggingTime=:taggingTime, swhwSettings=:swhwSettings, albumSortOrder=:albumSortOrder, performerSortOrder=:performerSortOrder, titleSortOrder=:titleSortOrder, synchronizedLyrics=:synchronizedLyrics, unsynchronizedLyrics=:unsynchronizedLyrics WHERE filename=:filename AND filesize=:filesize AND filedate=:filedate;"); else query.prepare("INSERT INTO file (fileName, fileSize, fileDate, fileType, length, bitrate, sampleRate, channels, bitsPerSample, layer, version, sampleWidth, sampleFrames, isEncrypted, trackGain, albumGain, trackPeak, albumPeak, protectionEnabled, channelMode, isCopyrighted, isOriginal, album, title, copyright, trackNumber, contentGroupDescription, subTitle, originalAlbum, partOfSet, subTitleOfSet, internationalStandardRecordingCode, leadArtist, band, conductor, interpret, originalArtist, textWriter, originalTextWriter, composer, encodedBy, beatsPerMinute, language, contentType, mediaType, mood, producedNotice, publisher, fileOwner, internetRadioStationName, internetRadioStationOwner, originalFilename, playlistDelay, encodingTime, originalReleaseTime, recordingTime, releaseTime, taggingTime, swhwSettings, albumSortOrder, performerSortOrder, titleSortOrder, synchronizedLyrics, unsynchronizedLyrics) VALUES (:fileName, :fileSize, :fileDate, :fileType, :length, :bitrate, :sampleRate, :channels, :bitsPerSample, :layer, :version, :sampleWidth, :sampleFrames, :isEncrypted, :trackGain, :albumGain, :trackPeak, :albumPeak, :protectionEnabled, :channelMode, :isCopyrighted, :isOriginal, :album, :title, :copyright, :trackNumber, :contentGroupDescription, :subTitle, :originalAlbum, :partOfSet, :subTitleOfSet, :internationalStandardRecordingCode, :leadArtist, :band, :conductor, :interpret, :originalArtist, :textWriter, :originalTextWriter, :composer, :encodedBy, :beatsPerMinute, :language, :contentType, :mediaType, :mood, :producedNotice, :publisher, :fileOwner, :internetRadioStationName, :internetRadioStationOwner, :originalFilename, :playlistDelay, :encodingTime, :originalReleaseTime, :recordingTime, :releaseTime, :taggingTime, :swhwSettings, :albumSortOrder, :performerSortOrder, :titleSortOrder, :synchronizedLyrics, :unsynchronizedLyrics);"); query.bindValue(":fileName", fileName()); query.bindValue(":fileSize", fileSize()); query.bindValue(":fileDate", fileDate()); query.bindValue(":fileType", fileType()); query.bindValue(":length", length()); query.bindValue(":bitrate", bitrate()); query.bindValue(":sampleRate", sampleRate()); query.bindValue(":channels", channels()); query.bindValue(":bitsPerSample", bitsPerSample()); query.bindValue(":layer", layer()); query.bindValue(":version", version()); query.bindValue(":sampleWidth", sampleWidth()); query.bindValue(":sampleFrames", sampleFrames()); query.bindValue(":isEncrypted", isEncrypted()); query.bindValue(":trackGain", trackGain()); query.bindValue(":albumGain", albumGain()); query.bindValue(":trackPeak", trackPeak()); query.bindValue(":albumPeak", albumPeak()); query.bindValue(":protectionEnabled", protectionEnabled()); query.bindValue(":channelMode", channelMode()); query.bindValue(":isCopyrighted", isCopyrighted()); query.bindValue(":isOriginal", isOriginal()); query.bindValue(":album", album()); query.bindValue(":title", title()); query.bindValue(":copyright", copyright()); query.bindValue(":trackNumber", trackNumber()); query.bindValue(":contentGroupDescription", contentGroupDescription()); query.bindValue(":subTitle", subTitle()); query.bindValue(":originalAlbum", originalAlbum()); query.bindValue(":partOfSet", partOfSet()); query.bindValue(":subTitleOfSet", subTitleOfSet()); query.bindValue(":internationalStandardRecordingCode", internationalStandardRecordingCode()); query.bindValue(":leadArtist", leadArtist()); query.bindValue(":band", band()); query.bindValue(":conductor", conductor()); query.bindValue(":interpret", interpret().join(", ")); query.bindValue(":originalArtist", originalArtist()); query.bindValue(":textWriter", textWriter()); query.bindValue(":originalTextWriter", originalTextWriter()); query.bindValue(":composer", composer()); query.bindValue(":encodedBy", encodedBy()); query.bindValue(":beatsPerMinute", beatsPerMinute()); query.bindValue(":language", language().join(", ")); query.bindValue(":contentType", contentType().join(", ")); query.bindValue(":mediaType", mediaType().join(", ")); query.bindValue(":mood", mood()); query.bindValue(":producedNotice", producedNotice()); query.bindValue(":publisher", publisher()); query.bindValue(":fileOwner", fileOwner()); query.bindValue(":internetRadioStationName", internetRadioStationName()); query.bindValue(":internetRadioStationOwner", internetRadioStationOwner()); query.bindValue(":originalFilename", originalFilename()); query.bindValue(":playlistDelay", playlistDelay()); query.bindValue(":encodingTime", encodingTime()); query.bindValue(":originalReleaseTime", originalReleaseTime()); query.bindValue(":recordingTime", recordingTime()); query.bindValue(":releaseTime", releaseTime()); query.bindValue(":taggingTime", taggingTime()); query.bindValue(":swhwSettings", swhwSettings().join(", ")); query.bindValue(":albumSortOrder", albumSortOrder()); query.bindValue(":performerSortOrder", performerSortOrder()); query.bindValue(":titleSortOrder", titleSortOrder()); query.bindValue(":synchronizedLyrics", synchronizedLyrics().join()); query.bindValue(":unsynchronizedLyrics", unsynchronizedLyrics().join("||")); if(!query.exec()) { myDebug << query.lastError().text(); return(-1); } query.prepare("SELECT id FROM file WHERE fileName=:fileName AND fileSize=:fileSize AND fileDate=:fileDate;"); query.bindValue(":fileName", fileName()); query.bindValue(":fileSize", fileSize()); query.bindValue(":fileDate", fileDate()); if(!query.exec()) { myDebug << query.lastError().text(); return(-1); } if(query.next()) return(query.value("id").toInt()); return(-1); }