#include "tagengine.h" #include // #include #include #include //used to load genre list #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "wavpack/wvfile.h" #include "trueaudio/ttafile.h" #include #ifdef HAVE_MP4V2 #include "mp4/mp4file.h" #include "mp4/mp4tag.h" #else #include "m4a/mp4file.h" #include "m4a/mp4itunestag.h" #endif #define TStringToTQString(s) TQString::fromUtf8((s).toCString(true)) // TODO COMPILATION tag // FIXME BPM tag TagData::TagData( const TQString& _artist, const TQString& _composer, const TQString& _album, const TQString& _title, const TQString& _genre, const TQString& _comment, int _track, int _disc, int _year, int _length, int _fileSize, int _bitrate, int _samplingRate ) { artist = _artist; composer = _composer; album = _album; title = _title; genre = _genre; comment = _comment; track = _track; disc = _disc; year = _year; length = _length; fileSize = _fileSize; bitrate = _bitrate; samplingRate = _samplingRate; } TagData::~TagData() {} TagEngine::TagEngine() { TagLib::StringList genres = TagLib::ID3v1::genreList(); for( TagLib::StringList::ConstIterator it = genres.begin(), end = genres.end(); it != end; ++it ) genreList += TStringToTQString( (*it) ); genreList.sort(); } TagEngine::~TagEngine() {} TagData* TagEngine::readTags( const TQString& file ) { TagLib::FileRef fileref( TQFile::encodeName(file) ); TagData* tagData = new TagData(); if( !fileref.isNull() ) { TagLib::Tag *tag = fileref.tag(); tagData->track = 0; tagData->year = 0; tagData->disc = 0; tagData->track_gain = 210588; // 0 is a valid value tagData->album_gain = 210588; if( tag ) { tagData->title = TStringToTQString( tag->title() ).stripWhiteSpace(); tagData->artist = TStringToTQString( tag->artist() ).stripWhiteSpace(); tagData->album = TStringToTQString( tag->album() ).stripWhiteSpace(); tagData->genre = TStringToTQString( tag->genre() ).stripWhiteSpace(); tagData->comment = TStringToTQString( tag->comment() ).stripWhiteSpace(); tagData->track = tag->track(); tagData->year = tag->year(); } TagLib::AudioProperties *audioProperties = fileref.audioProperties(); if( audioProperties ) { tagData->length = audioProperties->lengthInSeconds(); // TODO read all information //tagData->fileSize = ; // = audioProperties->channels(); //tagData->bitrate = audioProperties->bitrate(); tagData->samplingRate = audioProperties->sampleRate(); } TQString disc; TQString track_gain; TQString album_gain; if ( TagLib::MPEG::File *file = dynamic_cast( fileref.file() ) ) { if ( file->ID3v2Tag() ) { if ( !file->ID3v2Tag()->frameListMap()[ "TPOS" ].isEmpty() ) disc = TStringToTQString( file->ID3v2Tag()->frameListMap()["TPOS"].front()->toString() ).stripWhiteSpace(); if ( !file->ID3v2Tag()->frameListMap()[ "TCOM" ].isEmpty() ) tagData->composer = TStringToTQString( file->ID3v2Tag()->frameListMap()["TCOM"].front()->toString() ).stripWhiteSpace(); } if ( file->APETag() ) { if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) track_gain = TStringToTQString( file->APETag()->itemListMap()["REPLAYGAIN_TRACK_GAIN"].toString() ).stripWhiteSpace(); if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) album_gain = TStringToTQString( file->APETag()->itemListMap()["REPLAYGAIN_ALBUM_GAIN"].toString() ).stripWhiteSpace(); } } else if ( TagLib::Ogg::Vorbis::File *file = dynamic_cast( fileref.file() ) ) { if ( file->tag() ) { if ( !file->tag()->fieldListMap()[ "COMPOSER" ].isEmpty() ) tagData->composer = TStringToTQString( file->tag()->fieldListMap()["COMPOSER"].front() ).stripWhiteSpace(); if ( !file->tag()->fieldListMap()[ "DISCNUMBER" ].isEmpty() ) disc = TStringToTQString( file->tag()->fieldListMap()["DISCNUMBER"].front() ).stripWhiteSpace(); if ( !file->tag()->fieldListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) track_gain = TStringToTQString( file->tag()->fieldListMap()["REPLAYGAIN_TRACK_GAIN"].front() ).stripWhiteSpace(); if ( !file->tag()->fieldListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) album_gain = TStringToTQString( file->tag()->fieldListMap()["REPLAYGAIN_ALBUM_GAIN"].front() ).stripWhiteSpace(); } } else if ( TagLib::FLAC::File *file = dynamic_cast( fileref.file() ) ) { if ( file->xiphComment() ) { if ( !file->xiphComment()->fieldListMap()[ "COMPOSER" ].isEmpty() ) tagData->composer = TStringToTQString( file->xiphComment()->fieldListMap()["COMPOSER"].front() ).stripWhiteSpace(); if ( !file->xiphComment()->fieldListMap()[ "DISCNUMBER" ].isEmpty() ) disc = TStringToTQString( file->xiphComment()->fieldListMap()["DISCNUMBER"].front() ).stripWhiteSpace(); if ( !file->xiphComment()->fieldListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) track_gain = TStringToTQString( file->xiphComment()->fieldListMap()["REPLAYGAIN_TRACK_GAIN"].front() ).stripWhiteSpace(); if ( !file->xiphComment()->fieldListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) album_gain = TStringToTQString( file->xiphComment()->fieldListMap()["REPLAYGAIN_ALBUM_GAIN"].front() ).stripWhiteSpace(); } /*if ( file->tag() ) { if ( !file->tag()->fieldListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) track_gain = TStringToTQString( file->tag()->fieldListMap()["REPLAYGAIN_TRACK_GAIN"].front() ).stripWhiteSpace(); if ( !file->tag()->fieldListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) album_gain = TStringToTQString( file->tag()->fieldListMap()["REPLAYGAIN_ALBUM_GAIN"].front() ).stripWhiteSpace(); }*/ } else if ( TagLib::MP4::File *file = dynamic_cast( fileref.file() ) ) { TagLib::MP4::Tag *mp4tag = dynamic_cast( file->tag() ); if( mp4tag ) { tagData->composer = TStringToTQString( mp4tag->composer() ); disc = TQString::number( mp4tag->disk() ); } } /* else if ( TagLib::MPC::File *file = dynamic_cast( fileref.file() ) ) { if ( file->APETag() ) { if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) track_gain = TStringToTQString( file->APETag()->itemListMap()["REPLAYGAIN_TRACK_GAIN"].toString() ).stripWhiteSpace(); if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) album_gain = TStringToTQString( file->APETag()->itemListMap()["REPLAYGAIN_ALBUM_GAIN"].toString() ).stripWhiteSpace(); } }*/ else if ( TagLib::WavPack::File *file = dynamic_cast( fileref.file() ) ) { if ( file->APETag() ) { if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) track_gain = TStringToTQString( file->APETag()->itemListMap()["REPLAYGAIN_TRACK_GAIN"].toString() ).stripWhiteSpace(); if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) album_gain = TStringToTQString( file->APETag()->itemListMap()["REPLAYGAIN_ALBUM_GAIN"].toString() ).stripWhiteSpace(); } } else if ( TagLib::TTA::File *file = dynamic_cast( fileref.file() ) ) { if ( file->ID3v2Tag() ) { if ( !file->ID3v2Tag()->frameListMap()[ "TPOS" ].isEmpty() ) disc = TStringToTQString( file->ID3v2Tag()->frameListMap()["TPOS"].front()->toString() ).stripWhiteSpace(); if ( !file->ID3v2Tag()->frameListMap()[ "TCOM" ].isEmpty() ) tagData->composer = TStringToTQString( file->ID3v2Tag()->frameListMap()["TCOM"].front()->toString() ).stripWhiteSpace(); } } if( !disc.isEmpty() ) { int i = disc.find('/'); if( i != -1 ) // disc.right( i ).toInt() is total number of discs, we don't use this at the moment tagData->disc = disc.left( i ).toInt(); else tagData->disc = disc.toInt(); } if( !track_gain.isEmpty() ) { int i = track_gain.find(' '); if( i != -1 ) tagData->track_gain = track_gain.left( i ).toFloat(); else tagData->track_gain = track_gain.toFloat(); } if( !album_gain.isEmpty() ) { int i = album_gain.find(' '); if( i != -1 ) tagData->album_gain = album_gain.left( i ).toFloat(); else tagData->album_gain = album_gain.toFloat(); } return tagData; } return 0; } bool TagEngine::writeTags( const TQString& file, TagData* tagData ) { if( !tagData ) tagData = new TagData(); //Set default codec to UTF-8 (see bugs 111246 and 111232) TagLib::ID3v2::FrameFactory::instance()->setDefaultTextEncoding( TagLib::String::UTF8 ); TagLib::FileRef fileref( TQFile::encodeName(file), false ); if ( !fileref.isNull() ) { TagLib::Tag* tag = fileref.tag(); if ( tag ) { tag->setTitle( QStringToTString(tagData->title) ); tag->setArtist( QStringToTString(tagData->artist) ); tag->setAlbum( QStringToTString(tagData->album) ); tag->setTrack( tagData->track ); tag->setYear( tagData->year ); tag->setComment( QStringToTString(tagData->comment) ); tag->setGenre( QStringToTString(tagData->genre) ); } else { return false; } if ( TagLib::MPEG::File *file = dynamic_cast( fileref.file() ) ) { if ( file->ID3v2Tag() ) { if ( !file->ID3v2Tag()->frameListMap()[ "TPOS" ].isEmpty() ) { file->ID3v2Tag()->frameListMap()[ "TPOS" ].front()->setText( QStringToTString( TQString::number(tagData->disc) ) ); } else { TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TPOS", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); frame->setText( QStringToTString( TQString::number(tagData->disc) ) ); file->ID3v2Tag()->addFrame( frame ); } if ( !file->ID3v2Tag()->frameListMap()[ "TCOM" ].isEmpty() ) { file->ID3v2Tag()->frameListMap()[ "TCOM" ].front()->setText( QStringToTString( tagData->composer ) ); } else { TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TCOM", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); frame->setText( QStringToTString( tagData->composer ) ); file->ID3v2Tag()->addFrame( frame ); } // HACK sets the id3v2 genre tag as string if ( !file->ID3v2Tag()->frameListMap()[ "TCON" ].isEmpty() ) { file->ID3v2Tag()->frameListMap()[ "TCON" ].front()->setText( QStringToTString( tagData->genre ) ); } else { TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TCON", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); frame->setText( QStringToTString( tagData->genre ) ); file->ID3v2Tag()->addFrame( frame ); } // HACK sets the id3v2 year tag if ( !file->ID3v2Tag()->frameListMap()[ "TYER" ].isEmpty() ) { file->ID3v2Tag()->frameListMap()[ "TYER" ].front()->setText( QStringToTString( TQString::number(tagData->year) ) ); } else { TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TYER", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); frame->setText( QStringToTString( TQString::number(tagData->year) ) ); file->ID3v2Tag()->addFrame( frame ); } } } else if ( TagLib::Ogg::Vorbis::File *file = dynamic_cast( fileref.file() ) ) { if ( file->tag() ) { file->tag()->addField( "COMPOSER", QStringToTString( tagData->composer ), true ); file->tag()->addField( "DISCNUMBER", QStringToTString( TQString::number(tagData->disc) ), true ); } } else if ( TagLib::FLAC::File *file = dynamic_cast( fileref.file() ) ) { if ( file->xiphComment() ) { file->xiphComment()->addField( "COMPOSER", QStringToTString( tagData->composer ), true ); file->xiphComment()->addField( "DISCNUMBER", QStringToTString( TQString::number(tagData->disc) ), true ); } } else if ( TagLib::MP4::File *file = dynamic_cast( fileref.file() ) ) { TagLib::MP4::Tag *mp4tag = dynamic_cast( file->tag() ); if( mp4tag ) { mp4tag->setComposer( QStringToTString( tagData->composer ) ); mp4tag->setDisk( tagData->disc ); } } if ( TagLib::TTA::File *file = dynamic_cast( fileref.file() ) ) { if ( file->ID3v2Tag() ) { if ( !file->ID3v2Tag()->frameListMap()[ "TPOS" ].isEmpty() ) { file->ID3v2Tag()->frameListMap()[ "TPOS" ].front()->setText( QStringToTString( TQString::number(tagData->disc) ) ); } else { TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TPOS", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); frame->setText( QStringToTString( TQString::number(tagData->disc) ) ); file->ID3v2Tag()->addFrame( frame ); } if ( !file->ID3v2Tag()->frameListMap()[ "TCOM" ].isEmpty() ) { file->ID3v2Tag()->frameListMap()[ "TCOM" ].front()->setText( QStringToTString( tagData->composer ) ); } else { TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TCOM", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); frame->setText( QStringToTString( tagData->composer ) ); file->ID3v2Tag()->addFrame( frame ); } } } return fileref.save(); } return false; } // bool TagEngine::canWrite( TQString format ) // { // format = format.lower(); // // if( format == "ogg" || // format == "flac" || format == "fla" || // format == "mp3" || // TODO mp2 ? // format == "mpc" || // format == "aac" || // format == "ape" || format == "mac" || // format == "aa" || // format == "m4a" || format == "m4b" || format == "m4p" || format == "mp4" || format == "m4v" || format == "mp4v" || // format == "ra" || format == "rv" || format == "rm" || format == "rmj" || format == "rmvb" || // format == "wma" || format == "asf" ) // { // return true; // } // else { // return false; // } // }