bool MP3::readID3v2(const std::string& filename, Metadata& meta) { // After reading http://mail.kde.org/pipermail/taglib-devel/2008-March/000902.html // adding a big lock seems reasonable try { taglib_mutex.lock(); TagLib::MPEG::File f(filename.c_str()); if (f.isValid() && f.tag()) { TagLib::Tag* pTag = f.tag(); meta.interpret = pTag->artist().isNull() ? "" : pTag->artist().to8Bit(true); meta.album = pTag->album().isNull() ? "" : pTag->album().to8Bit(true); meta.title = pTag->title().isNull() ? "" : pTag->title().to8Bit(true); meta.genre = pTag->genre().isNull() ? "" : pTag->genre().to8Bit(true); meta.track_no = pTag->track(); meta.year = pTag->year(); taglib_mutex.unlock(); return meta.complete(); } } catch (const std::exception&) { taglib_mutex.unlock(); // ... } return false; }
void Track::readTags() { QByteArray fileName = QFile::encodeName( p->url.toLocalFile() ); const char * encodedName = fileName.constData(); TagLib::FileRef fileref = TagLib::FileRef( encodedName, true, TagLib::AudioProperties::Fast); if ( !fileref.isNull() ) { if( fileref.tag() ) { TagLib::Tag *tag = fileref.tag(); p->title = !tag->title().isNull() ? TStringToQString( tag->title() ).trimmed() : QObject::tr("Unknown"); p->artist = !tag->artist().isNull() ? TStringToQString( tag->artist() ).trimmed() : QObject::tr("Unknown"); p->album = !tag->album().isNull() ? TStringToQString( tag->album() ).trimmed() : QObject::tr("Unknown"); p->comment = TStringToQString( tag->comment() ).trimmed(); p->genre = !tag->genre().isNull() ? TStringToQString( tag->genre() ).trimmed() : QObject::tr("Unknown"); p->year = tag->year() ? QString::number( tag->year() ) : QString::null; p->tracknumber = tag->track() ? QString::number( tag->track() ) : QString::null; p->length = fileref.audioProperties()->length(); p->counter = 0; p->rate = 0; //polish up empty tags if( p->title == QObject::tr("Unknown") ) { QFileInfo fileInfo(p->url.toLocalFile()); p->title = fileInfo.fileName().replace( '_', ' ' ).replace('.' + fileInfo.suffix(),"") ; } } } }
bool MetaData(const char* filepath, cFields& fields, cRow& props) { #define ADD(x, t) do { if (t) { fields.push_back(x); props.push_back(t); } } while(0) #define ADDSTRING(x, t) do { if (!t.empty()) { fields.push_back(x); props.push_back(t); } } while(0) #define ADDINT(x, t) do { std::string c = *itoa(t); if (!c.empty()){ fields.push_back(x); props.push_back(c);} } while(0) TagLib::FileRef f(filepath); fields.clear(); props.clear(); //cTag t; //const char* tmp = NULL; std::string tmp; if (f.isNull()) { std::cerr<< "Taglib failed on " << filepath << std::endl; ADD("metadata_needs_update", "2"); // failure return false; } TagLib::Tag *tag = f.tag(); if (tag) { #if 0 tmp = toString(tag->title()).c_str(); ADD("title", tmp); tmp = toString(tag->artist()).c_str(); ADD("artist", tmp); tmp = toString(tag->album()).c_str(); ADD("album", tmp); tmp = toString(tag->comment()).c_str(); ADD("comment", tmp); tmp = toString(tag->genre()).c_str(); ADD("genre", tmp); #else tmp = toString(tag->title()); ADDSTRING("title", tmp); tmp = toString(tag->artist()); ADDSTRING("artist", tmp); tmp = toString(tag->album()); ADDSTRING("album", tmp); tmp = toString(tag->comment()); ADDSTRING("comment", tmp); tmp = toString(tag->genre()); ADDSTRING("genre", tmp); #endif //ADDINT("track", tag->track()); ADDINT("year", tag->year()); } TagLib::AudioProperties *prop = f.audioProperties(); if (prop) { ADDINT("bitrate", prop->bitrate()); ADDINT("samplerate", prop->sampleRate()); // ADDINT("channels", prop->channels()); ADDINT("length" , prop->length()); } ADD("metadata_needs_update", "0"); return true; }
Tune* tuneFromFile(const QString& file) { Tune* tune = new Tune(false); tune->file = file; TagLib::FileRef ref = fileName2TaglibRef(file); if(!ref.isNull()) { if(ref.tag()) { TagLib::Tag* tag = ref.tag(); tune->artist = safeTagLibString2QString( tag->artist() ); tune->album = safeTagLibString2QString( tag->album() ); tune->title = safeTagLibString2QString( tag->title() ); tune->trackNumber = QString::number( tag->track() ); tune->genre = safeTagLibString2QString( tag->genre() ); } Qomp::loadCover(tune, ref.file()); if(ref.audioProperties()) { TagLib::AudioProperties *prop = ref.audioProperties(); tune->duration = Qomp::durationSecondsToString( prop->length() ); tune->bitRate = QString::number( prop->bitrate() ); } tune->setMetadataResolved(true); } return tune; }
void getMp3Info(const WCHAR* fileName, MP3Info &info) { TagLib::FileRef f(fileName); if (!f.isNull() && f.tag()) { TagLib::Tag *tag = f.tag(); info.tag[0] = tag->title().toWString(); info.tag[1] = tag->artist().toWString(); info.tag[2] = tag->album().toWString(); info.tag[3] = tag->comment().toWString(); info.tag[4] = tag->genre().toWString(); info.year = tag->year(); info.track = tag->track(); TagLib::PropertyMap tags = f.file()->properties(); if (!f.isNull() && f.audioProperties()) { TagLib::AudioProperties *properties = f.audioProperties(); int seconds = properties->length() % 60; int minutes = (properties->length() - seconds) / 60; info.bitrate = properties->bitrate(); info.sample_rate = properties->sampleRate(); info.channels = properties->channels(); info.length_minutes = minutes; info.length_seconds = seconds; } } }
AlbumTrack::AlbumTrack(Album* album, QString trackPath) { this->path = trackPath; this->number = 0; this->artist = "Unknown Artist"; this->album = album; this->genre = "Unknown Genre"; TagLib::FileRef f(trackPath.toStdString().c_str()); if(!f.isNull() && f.tag()) { TagLib::Tag *tag = f.tag(); title = QString(tag->title().toCString()); number = tag->track(); artist = QString(tag->artist().toCString()); albumName = QString(tag->album().toCString()); genre = QString(tag->genre().toCString()); } if(!f.isNull() && f.audioProperties()) { TagLib::AudioProperties *properties = f.audioProperties(); duration = properties->length() * 1000; //Weil Fmod die gerne in Millisekunden hätte } }
int handle_file(const char* filepath, const char* filekey, AudioFileRecordStore& record_store) { bool record_exists = record_store.find_record(filekey) != NULL; // Scanning a file for tags is expensive, so only do it if required. if(record_exists && !record_store.record_update_required(filekey)) { // no update reqquired so has been handled. return 1; } TagLib::FileRef f(filepath); if (!f.isNull() && f.tag()) { AudioFileRecord &record = record_store.get_record(filekey); record.update_start(); if (verbose) { TagLib::Tag *tag = f.tag(); std::cout << filepath << endl; std::cout << filekey << endl; std::cout << "-- TAG (basic) --" << endl; std::cout << "title - \"" << tag->title() << "\"" << endl; std::cout << "artist - \"" << tag->artist() << "\"" << endl; std::cout << "album - \"" << tag->album() << "\"" << endl; std::cout << "year - \"" << tag->year() << "\"" << endl; std::cout << "comment - \"" << tag->comment() << "\"" << endl; std::cout << "track - \"" << tag->track() << "\"" << endl; std::cout << "genre - \"" << tag->genre() << "\"" << endl; } TagLib::PropertyMap tags = f.file()->properties(); for(TagLib::PropertyMap::ConstIterator i = tags.begin(); i != tags.end(); ++i) { for(TagLib::StringList::ConstIterator j = i->second.begin(); j != i->second.end(); ++j) { record.update(i->first.toCString(true), j->toCString(true)); } } if (f.audioProperties()) { TagLib::AudioProperties *properties = f.audioProperties(); record.update(audio_tags::BITRATE, properties->bitrate()); record.update(audio_tags::LENGTH, properties->length()); record.update(audio_tags::SAMPLERATE, properties->sampleRate()); record.update(audio_tags::CHANNELS, properties->channels()); } record.update_complete(); return 1; } return 0; }
TagLibTokenizer::TagLibTokenizer(const Document *pDocument) : Tokenizer(NULL), m_pTagDocument(NULL) { if (pDocument != NULL) { Url urlObj(pDocument->getLocation()); string pseudoContent; if ((urlObj.isLocal() == true) && (urlObj.getFile().empty() == false)) { string location(urlObj.getLocation()); string trackTitle; location += "/"; location += urlObj.getFile(); TagLib::FileRef fileRef(location.c_str(), false); if (fileRef.isNull() == false) { TagLib::Tag *pTag = fileRef.tag(); if ((pTag != NULL) && (pTag->isEmpty() == false)) { char yearStr[64]; trackTitle = pTag->title().to8Bit(); trackTitle += " "; trackTitle += pTag->artist().to8Bit(); pseudoContent = trackTitle; pseudoContent += " "; pseudoContent += pTag->album().to8Bit(); pseudoContent += " "; pseudoContent += pTag->comment().to8Bit(); pseudoContent += " "; pseudoContent += pTag->genre().to8Bit(); snprintf(yearStr, 64, " %u", pTag->year()); pseudoContent += yearStr; } } else { trackTitle = pseudoContent = pDocument->getTitle(); } m_pTagDocument = new Document(trackTitle, pDocument->getLocation(), pDocument->getType(), pDocument->getLanguage()); m_pTagDocument->setData(pseudoContent.c_str(), pseudoContent.length()); m_pTagDocument->setTimestamp(pDocument->getTimestamp()); m_pTagDocument->setSize(pDocument->getSize()); // Give the result to the parent class setDocument(m_pTagDocument); } } }
bool ReadTag(const musik::Core::String& fn, musik::Core::SongInfo& target) { bool ret = true; musik::Core::Filename mfn(fn); target.SetFilename(fn); target.SetFormat("Ogg Vorbis"); try { #if defined (WIN32) TagLib::FileRef tag_file(fn.c_str()); #else TagLib::FileRef tag_file(utf16to8(fn, true).c_str()); #endif if (!tag_file.isNull()) { if (tag_file.tag()) { TagLib::Tag *tag = tag_file.tag(); target.SetArtist(musik::Core::utf8to16(tag->artist().to8Bit(true))); target.SetAlbum(musik::Core::utf8to16(tag->album().to8Bit(true))); target.SetTitle(musik::Core::utf8to16(tag->title().to8Bit(true))); target.SetGenre(musik::Core::utf8to16(tag->genre().to8Bit(true))); target.SetNotes(musik::Core::utf8to16(tag->comment().to8Bit(true))); target.SetYear(musik::Core::IntToString(tag->year())); target.SetTrackNum(musik::Core::IntToString(tag->track())); } if (tag_file.audioProperties()) { TagLib::AudioProperties *properties = tag_file.audioProperties(); int duration = properties->length() * 1000; target.SetBitrate(musik::Core::IntToString(properties->bitrate())); target.SetDuration(musik::Core::IntToString(duration)); } } // if the title is empty, then use the // filename... if (target.GetTitle().IsEmpty()) { musik::Core::Filename MFN(fn); target.SetTitle(MFN.GetJustFilename()); } } catch (...) { ret = false; cout << "taglib crashed reading: " << fn.c_str() << endl; } return ret; }
int main(int argc, char *argv[]) { for(int i = 1; i < argc; i++) { cout << "******************** \"" << argv[i] << "\" ********************" << endl; TagLib::FileRef f(argv[i]); if(!f.isNull() && f.tag()) { TagLib::Tag *tag = f.tag(); cout << "-- TAG (basic) --" << endl; cout << "title - \"" << tag->title() << "\"" << endl; cout << "artist - \"" << tag->artist() << "\"" << endl; cout << "album - \"" << tag->album() << "\"" << endl; cout << "year - \"" << tag->year() << "\"" << endl; cout << "comment - \"" << tag->comment() << "\"" << endl; cout << "track - \"" << tag->track() << "\"" << endl; cout << "genre - \"" << tag->genre() << "\"" << endl; TagLib::PropertyMap tags = f.file()->properties(); unsigned int longest = 0; for(TagLib::PropertyMap::ConstIterator i = tags.begin(); i != tags.end(); ++i) { if (i->first.size() > longest) { longest = i->first.size(); } } cout << "-- TAG (properties) --" << endl; for(TagLib::PropertyMap::ConstIterator i = tags.begin(); i != tags.end(); ++i) { for(TagLib::StringList::ConstIterator j = i->second.begin(); j != i->second.end(); ++j) { cout << left << std::setw(longest) << i->first << " - " << '"' << *j << '"' << endl; } } } if(!f.isNull() && f.audioProperties()) { TagLib::AudioProperties *properties = f.audioProperties(); int seconds = properties->length() % 60; int minutes = (properties->length() - seconds) / 60; cout << "-- AUDIO --" << endl; cout << "bitrate - " << properties->bitrate() << endl; cout << "sample rate - " << properties->sampleRate() << endl; cout << "channels - " << properties->channels() << endl; cout << "length - " << minutes << ":" << setfill('0') << setw(2) << seconds << endl; } } return 0; }
void DataStore::addSongToLibrary(const Phonon::MediaSource& song, QSqlQuery &addQuery){ QString fileName = song.fileName(); QString songName; QString artistName; QString albumName; QString genre; int track; int duration; TagLib::FileRef f(fileName.toStdString().c_str()); if(!f.isNull() && f.tag() && f.audioProperties()){ TagLib::Tag *tag = f.tag(); songName = TStringToQString(tag->title()); artistName = TStringToQString(tag->artist()); albumName = TStringToQString(tag->album()); genre = TStringToQString(tag->genre()); duration = f.audioProperties()->length(); track = tag->track(); } else{ //TODO throw error return; } if(songName == ""){ songName = unknownSongTitle(); } if(artistName == ""){ artistName = unknownSongArtist(); } if(albumName == ""){ albumName = unknownSongAlbum(); } if(genre == ""){ genre = unknownGenre(); } Logger::instance()->log("adding song with title: " + songName + " to database"); library_song_id_t hostId =-1; addQuery.bindValue(":song", songName); addQuery.bindValue(":artist", artistName); addQuery.bindValue(":album", albumName); addQuery.bindValue(":genre", genre); addQuery.bindValue(":track", track); addQuery.bindValue(":file", fileName); addQuery.bindValue(":duration", duration); EXEC_INSERT( "Failed to add song library" << songName.toStdString(), addQuery, hostId, library_song_id_t) }
void MetaBundle::readTags( TagLib::AudioProperties::ReadStyle readStyle ) { if( m_url.protocol() != "file" ) return; const QString path = m_url.path(); TagLib::FileRef fileref; TagLib::Tag *tag = 0; if( AmarokConfig::recodeID3v1Tags() && path.endsWith( ".mp3", false ) ) { TagLib::MPEG::File *mpeg = new TagLib::MPEG::File( QFile::encodeName( path ), true, readStyle ); fileref = TagLib::FileRef( mpeg ); if( mpeg->isValid() ) // we prefer ID3v1 over ID3v2 if recoding tags because // apparently this is what people who ignore ID3 standards want tag = mpeg->ID3v1Tag() ? (TagLib::Tag*)mpeg->ID3v1Tag() : (TagLib::Tag*)mpeg->ID3v2Tag(); } else { fileref = TagLib::FileRef( QFile::encodeName( path ), true, readStyle ); if( !fileref.isNull() ) tag = fileref.tag(); } if( !fileref.isNull() ) { if ( tag ) { #define strip( x ) TStringToQString( x ).stripWhiteSpace() m_title = strip( tag->title() ); m_artist = strip( tag->artist() ); m_album = strip( tag->album() ); m_comment = strip( tag->comment() ); m_genre = strip( tag->genre() ); m_year = tag->year() ? QString::number( tag->year() ) : QString(); m_track = tag->track() ? QString::number( tag->track() ) : QString(); #undef strip m_isValidMedia = true; } init( fileref.audioProperties() ); } //FIXME disabled for beta4 as it's simpler to not got 100 bug reports //else if( KMimeType::findByUrl( m_url )->is( "audio" ) ) // init( KFileMetaInfo( m_url, QString::null, KFileMetaInfo::Everything ) ); }
int main(int argc, char *argv[]) { for(int i = 1; i < argc; i++) { cout << "******************** \"" << argv[i] << "\" ********************" << endl; TagLib::FileRef f(argv[i]); if(!f.isNull() && f.tag()) { TagLib::Tag *tag = f.tag(); cout << "-- TAG --" << endl; cout << "title - \"" << tag->title() << "\"" << endl; cout << "artist - \"" << tag->artist() << "\"" << endl; cout << "album - \"" << tag->album() << "\"" << endl; cout << "year - \"" << tag->year() << "\"" << endl; cout << "comment - \"" << tag->comment() << "\"" << endl; cout << "track - \"" << tag->track() << "\"" << endl; cout << "genre - \"" << tag->genre() << "\"" << endl; } if(!f.isNull() && f.audioProperties()) { TagLib::AudioProperties *properties = f.audioProperties(); int seconds = properties->length() % 60; int minutes = (properties->length() - seconds) / 60; cout << "-- AUDIO --" << endl; cout << "bitrate - " << properties->bitrate() << endl; cout << "sample rate - " << properties->sampleRate() << endl; cout << "channels - " << properties->channels() << endl; cout << "length - " << minutes << ":" << formatSeconds(seconds) << endl; } } return 0; }
bool mediaTag(Artwork *art, TagLib::File *f) { Q_ASSERT(f != NULL); Q_ASSERT(f->tag()); TagLib::Tag *tag = f->tag(); art->filetype = FILETYPE_UNKNOWN; // The basic stuff!!! art->artist = TStringToQString(tag->artist()).trimmed(); art->album = TStringToQString(tag->album()).trimmed(); art->track = TStringToQString(tag->title()).trimmed(); art->genre = TStringToQString(tag->genre()).trimmed(); art->year = tag->year(); art->trackNo = tag->track(); // we need something to search on! if (art->artist == "" && art->album == "" && art->track == "") { return false; } // Any audio properties??? if (f->audioProperties()) { TagLib::AudioProperties *properties = f->audioProperties(); int seconds = properties->length() % 60; int minutes = (properties->length() - seconds) / 60; art->duration = minutes * 60 + seconds; art->bitRate = properties->bitrate(); art->sampleRate = properties->sampleRate(); art->channels = properties->channels(); } art->makeSearchable(); return true; }
void FileStore::scan(const string & a_path) { if (!fs::exists(a_path)) return; if (fs::is_directory(a_path)) { fs::directory_iterator end; // default construction yields past-the-end for (fs::directory_iterator curr(a_path); curr != end; ++curr) { fs::path p = curr->path(); string s = p.string(); scan(s); } } else if (fs::is_regular_file(a_path)) { if (pathExists(a_path)) return; TagLib::FileRef file_ref(a_path.c_str(), false); if (!file_ref.isNull() && file_ref.tag()) { cerr << "indexing " << a_path << endl; TagLib::Tag *t = file_ref.tag(); string artist = t->artist().to8Bit(true); string album = t->album().to8Bit(true); string title = t->title().to8Bit(true); string genre = t->genre().to8Bit(true); string year = t->year() > 0 ? lexical_cast<string>(t->year()) : ""; string track = t->track() > 0 ? lexical_cast<string>(t->track()) : ""; string uri = "file://" + a_path; shared_ptr<UUID> fileID(generateID()); addField(*fileID, ARTIST, artist); addField(*fileID, ARTIST, artist); addField(*fileID, ALBUM, album); addField(*fileID, YEAR, year); addField(*fileID, TITLE, title); addField(*fileID, GENRE, genre); addField(*fileID, TRACK, track); addField(*fileID, URI, uri); } } }
bool SoundSource::processTaglibFile(TagLib::File& f) { if (s_bDebugMetadata) qDebug() << "Parsing" << getFilename(); if (f.isValid()) { TagLib::Tag *tag = f.tag(); if (tag) { QString title = TStringToQString(tag->title()); setTitle(title); QString artist = TStringToQString(tag->artist()); setArtist(artist); QString album = TStringToQString(tag->album()); setAlbum(album); QString comment = TStringToQString(tag->comment()); setComment(comment); QString genre = TStringToQString(tag->genre()); setGenre(genre); int iYear = tag->year(); QString year = ""; if (iYear > 0) { year = QString("%1").arg(iYear); setYear(year); } int iTrack = tag->track(); QString trackNumber = ""; if (iTrack > 0) { trackNumber = QString("%1").arg(iTrack); setTrackNumber(trackNumber); } if (s_bDebugMetadata) qDebug() << "TagLib" << "title" << title << "artist" << artist << "album" << album << "comment" << comment << "genre" << genre << "year" << year << "trackNumber" << trackNumber; } TagLib::AudioProperties *properties = f.audioProperties(); if (properties) { int lengthSeconds = properties->length(); int bitrate = properties->bitrate(); int sampleRate = properties->sampleRate(); int channels = properties->channels(); if (s_bDebugMetadata) qDebug() << "TagLib" << "length" << lengthSeconds << "bitrate" << bitrate << "sampleRate" << sampleRate << "channels" << channels; setDuration(lengthSeconds); setBitrate(bitrate); setSampleRate(sampleRate); setChannels(channels); } // If we didn't get any audio properties, this was a failure. return (properties!=NULL); } return false; }
void RecurseWorker::updateTrackInfo( const TrackInfo &trackInfo ) { bool tagsChanged = false; TrackInfo ti = trackInfo; TrackInfo oldTags; QString oldpath( trackInfo.mDirectory + "/" + trackInfo.mFileName ); mTagMap.clear(); { TagLib::FileRef f( oldpath.toLocal8Bit().data() ); if( f.file() ) { oldTags = trackInfo; TagLib::AudioProperties *audioProperties = f.audioProperties(); TagLib::Tag *tag = f.tag(); if( audioProperties ) { oldTags.mPlayTime = audioProperties->length(); } if( tag ) { oldTags.mArtist = QString::fromUtf8( tag->artist().toCString( true ) ); oldTags.mTitle = QString::fromUtf8( tag->title().toCString( true ) ); oldTags.mAlbum = QString::fromUtf8( tag->album().toCString( true ) ); oldTags.mTrackNr = tag->track(); oldTags.mYear = tag->year(); oldTags.mGenre = QString::fromUtf8( tag->genre().toCString( true ) ); } else { emit error( tr("Could not read tags"), oldpath ); } ti = oldTags; } else { emit error( tr("Could not read file"), oldpath ); } } switch( mMode ) { case ModeSetTags: if( mSetArtist ) { ti.mArtist = mTrackInfo.mArtist; } if( mSetTitle ) { ti.mTitle.append( " " ); ti.mTitle.append( mTrackInfo.mTitle ); } if( mSetAlbum ) { ti.mAlbum = mTrackInfo.mAlbum; } if( mSetYear ) { ti.mYear = mTrackInfo.mYear; } if( mSetGenre ) { ti.mGenre = mTrackInfo.mGenre; } tagsChanged = (ti != oldTags); if( mSetFlags ) { if( mTrackInfo.isFlagged( TrackInfo::Favorite ) ) { ti.setFlag( TrackInfo::Favorite, true ); } if( mTrackInfo.isFlagged( TrackInfo::Unwanted ) ) { ti.setFlag( TrackInfo::Unwanted, true ); } } if( mUnsetFlags ) { if( mTrackInfo.isFlagged( TrackInfo::Favorite ) ) { ti.setFlag( TrackInfo::Favorite, false ); } if( mTrackInfo.isFlagged( TrackInfo::Unwanted ) ) { ti.setFlag( TrackInfo::Unwanted, false ); } if( mTrackInfo.isFlagged( TrackInfo::ScannedWithPower ) || mTrackInfo.isFlagged( TrackInfo::ScannedWithPeak ) ) { ti.setFlag( TrackInfo::ScannedWithPeak, false ); ti.mLastScanned = 0; } } if( mSetGroups || mUnsetGroups ) { QStringList groups( mTrackInfo.getGroups() ); foreach( const QString &group, groups ) { ti.setGroup( group, mSetGroups ); } }
Tags *TagUtils::load(const QString &filename) { #ifdef Q_OS_WIN const wchar_t * encodedName = reinterpret_cast<const wchar_t*>(filename.utf16()); TagLib::FileStream readOnlyStream(encodedName, true); #else TagLib::FileStream readOnlyStream((TagLib::FileName)filename.toUtf8(), true); #endif TagLib::FileRef fileref(&readOnlyStream); if (fileref.isNull()) { qDebug() << "Taglib cannot parse" << filename; return nullptr; } Tags *tags = new Tags(); tags->setFilename(filename); TagLib::Tag *tag = fileref.tag(); if (tag) { tags->setTitle(TagUtils::qString(tag->title())); tags->setArtistString(TagUtils::qString(tag->artist())); tags->setAlbumString(TagUtils::qString(tag->album())); tags->setGenre(TagUtils::qString(tag->genre())); tags->setTrackNumber(tag->track()); tags->setYear(tag->year()); tags->setComment(TagUtils::qString(tag->comment())); TagLib::AudioProperties *audioProperties = fileref.audioProperties(); if (audioProperties) tags->setDuration(audioProperties->length()); } /* TagLib::PropertyMap map = tag->properties(); for (TagLib::PropertyMap::ConstIterator i = map.begin(); i != map.end(); ++i) { for (TagLib::StringList::ConstIterator j = i->second.begin(); j != i->second.end(); ++j) { const QString tagName = TagLibUtils::toQString(i->first); qDebug() << "PropertyMap" << tagName << TagLibUtils::toQString(*j); if (tagName == QLatin1String("ALBUMARTIST")) tags->setAlbumArtist(TagLibUtils::toQString(*j)); else if (tagName == QLatin1String("DISCNUMBER")) tags->setDiskNumber(TagLibUtils::toQString(*j).toInt()); // else if (tagName == QLatin1String("COMPOSER")) // tags->setComposer(toQString(*j)); else if (tagName == QLatin1String("LYRICS")) tags->setLyrics(TagLibUtils::toQString(*j)); //else if (tagName == QLatin1String("BPM")) // tags->bpm = toQString(*j).toInt(); // else qDebug() << "Unused tag" << tagName << toQString(*j); } } */ // Handle file types where TagLibf:::File::tag() returns a "TagUnion" TagLib::File *file = fileref.file(); if (TagLib::MPEG::File *f = dynamic_cast<TagLib::MPEG::File*>(file)) { if (TagLib::ID3v2::Tag *t = f->ID3v2Tag()) Id3Utils::load(t, tags); } else if (TagLib::TrueAudio::File *f = dynamic_cast<TagLib::TrueAudio::File*>(file)) { if (TagLib::ID3v2::Tag *t = f->ID3v2Tag()) Id3Utils::load(t, tags); } else if (TagLib::FLAC::File *f = dynamic_cast<TagLib::FLAC::File*>(file)) { if (TagLib::Ogg::XiphComment *t = f->xiphComment()) VorbisUtils::load(t, tags); else if (TagLib::ID3v2::Tag *t = f->ID3v2Tag()) Id3Utils::load(t, tags); } else if (TagLib::APE::File *f = dynamic_cast<TagLib::APE::File*>(file)) { if (TagLib::APE::Tag *t = f->APETag()) ApeUtils::load(t, tags); } else if (TagLib::MPC::File *f = dynamic_cast<TagLib::MPC::File*>(file)) { if (TagLib::APE::Tag *t = f->APETag()) ApeUtils::load(t, tags); } else if (TagLib::WavPack::File *f = dynamic_cast<TagLib::WavPack::File*>(file)) { if (TagLib::APE::Tag *t = f->APETag()) ApeUtils::load(t, tags); } else { // Fallback to casting tag() for any other file type TagLib::Tag *tag = file->tag(); if (TagLib::ID3v2::Tag *t = dynamic_cast<TagLib::ID3v2::Tag*>(tag)) Id3Utils::load(t, tags); else if (TagLib::Ogg::XiphComment *t = dynamic_cast<TagLib::Ogg::XiphComment*>(tag)) VorbisUtils::load(t, tags); else if (TagLib::APE::Tag *t = dynamic_cast<TagLib::APE::Tag*>(tag)) ApeUtils::load(t, tags); else if (TagLib::MP4::Tag *t = dynamic_cast<TagLib::MP4::Tag*>(tag)) Mp4Utils::load(t, tags); else if (TagLib::ASF::Tag *t = dynamic_cast<TagLib::ASF::Tag*>(tag)) AsfUtils::load(t, tags); } return tags; }
int main (int argc, char *argv[]) { try { static struct option long_options[] = { { "source-encoding", required_argument, NULL, 's' }, { "id3v1-encoding", required_argument, NULL, '1' }, { "id3v2-encoding", required_argument, NULL, '2' }, { "preserve-unicode", no_argument, NULL, 'p' }, { "preview", no_argument, NULL, 'w' }, { "version", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { "quiet", no_argument, NULL, 'q' }, { NULL, 0, NULL, 0 } }; int long_options_ret; std::string source_encoding; std::string id3v1_encoding = "none"; std::string id3v2_encoding = "none"; bool preserve_unicode = false; bool preview = false; bool usage_ok = true; bool verbose = true; if(argc == 1) { printf("%s", msg::usage); exit(1); } while ( (long_options_ret = getopt_long (argc, argv, "s:1:2:pwdvhq", long_options, NULL)) != -1 ) { switch (long_options_ret) { case 's': source_encoding = optarg; tolower(source_encoding); break; case '1': id3v1_encoding = optarg; tolower(id3v1_encoding); break; case '2': id3v2_encoding = optarg; tolower(id3v2_encoding); break; case 'p': preserve_unicode = true; break; case 'w': preview = true; break; case 'v': printf("%s %s\n", PACKAGE, PACKAGE_VERSION); printf("%s", msg::copyright); exit (1); break; case 'h': printf("%s", msg::usage); exit(1); case 'q': verbose = false; break; default: usage_ok = false; break; } } if (usage_ok && source_encoding.empty ()) { printf("%s", msg::nosenc); usage_ok = false; } if(optind == argc) { printf("%s", msg::nofiles); usage_ok = false; } if (!usage_ok) { printf("%s", msg::seehelp); exit (1); } TagLib::ID3v2::FrameFactory::instance()->setDefaultTextEncoding (TagLib::String::UTF8); for (int i=optind;i<argc;i++) { TagLib::MPEG::File mp3file(argv[i]); if (!mp3file.isOpen ()) { throw msg::nofile(argv[i]); } TagLib::Tag *tag = mp3file.tag(); if(tag->isEmpty()) { printf("%s", msg::emptyfile(argv[i]).c_str()); } else { Converter converter ( source_encoding, id3v1_encoding, id3v2_encoding, mp3file.ID3v1Tag (true), mp3file.ID3v2Tag (true), preserve_unicode ); converter.Convert (tag->title (), &TagLib::Tag::setTitle); converter.Convert (tag->artist (), &TagLib::Tag::setArtist); converter.Convert (tag->album (), &TagLib::Tag::setAlbum); converter.Convert (tag->comment (), &TagLib::Tag::setComment); converter.Convert (tag->genre (), &TagLib::Tag::setGenre); if (preview) { converter.printTags(argv[i]); } else { mp3file.strip(~converter.Tags()); if (!mp3file.save (converter.Tags ())) { printf("%s", msg::writefail(argv[i]).c_str()); } else if(verbose) { printf("%s", msg::filedone(argv[i]).c_str()); } } } } exit (0); } catch (const std::string &e) { printf ("%s", msg::error(e).c_str()); exit (1); } catch (const char *e) { printf ("%s", msg::error(e).c_str()); exit (1); } return 1; }
std::vector<std::string> GetFileInfo(std::string path) { std::vector<std::string> fileInfo; std::string title, artist, album, genre, comment; TagLib::FileRef f( path.c_str() ); if(!f.isNull() && f.tag()) { TagLib::Tag *tag = f.tag(); // unicode = false title = tag->title().stripWhiteSpace().toCString(false) ; if(title.size()) { std::stringstream temp; temp << tr("Title") << ":\t"; temp << title; fileInfo.push_back(temp.str()); } artist = tag->artist().stripWhiteSpace().toCString(false) ; if(artist.size()) { std::stringstream temp; temp << tr("Artist") << ":\t"; temp << artist; fileInfo.push_back(temp.str()); } album = tag->album().stripWhiteSpace().toCString(false) ; if(album.size()) { std::stringstream temp; temp << tr("Album") << ":\t"; temp << album; fileInfo.push_back(temp.str()); } genre = tag->genre().stripWhiteSpace().toCString(false) ; if(genre.size()) { std::stringstream temp; temp << tr("Genre") << ":\t"; temp << genre; fileInfo.push_back(temp.str()); } comment = tag->comment().stripWhiteSpace().toCString(false) ; if(comment.size()) { std::stringstream temp; temp << tr("Comment") << ":\t"; temp << comment; fileInfo.push_back(temp.str()); } if(tag->year()) { std::stringstream temp; temp << tr("Year") << ":\t"; temp << tag->year(); fileInfo.push_back(temp.str()); } if(tag->track()) { std::stringstream temp; temp << tr("Track") << ":\t"; temp << tag->track(); fileInfo.push_back(temp.str()); } } if(!f.isNull() && f.audioProperties()) { TagLib::AudioProperties *props = f.audioProperties(); if(props->length()) { int min = props->length()/60; int sec = props->length()%60; std::stringstream temp; temp << tr("Length") << ":\t"; temp << min << ":"; if(sec<=9) temp << "0"; temp << sec << " " << tr("min"); fileInfo.push_back(temp.str()); } if(props->bitrate()) { std::stringstream temp; temp << tr("Bitrate") << ":\t"; temp << props->bitrate() << " kb/s"; fileInfo.push_back(temp.str()); } if(props->sampleRate()) { std::stringstream temp; temp << tr("Samplerate") << ":\t"; temp << props->sampleRate() << " Hz"; fileInfo.push_back(temp.str()); } if(props->channels()) { std::stringstream temp; temp << tr("ID3$Channels") << ":\t"; temp << props->channels(); fileInfo.push_back(temp.str()); } if(TagLib::MPEG::Properties* mpegProp = dynamic_cast<TagLib::MPEG::Properties*>(props)) { #if 0 std::stringstream temp; temp << tr("Original") << ":\t"; temp << mpegProp->isOriginal(); fileInfo.push_back(temp.str()); #endif std::stringstream temp2; temp2 << tr("MPEG-Layer") << ":\t"; temp2 << mpegProp->layer(); fileInfo.push_back(temp2.str()); #if 0 std::stringstream temp3; temp3 << tr("Copyrighted") << ":\t"; temp3 << mpegProp->isCopyrighted(); fileInfo.push_back(temp3.str()); std::stringstream temp4; temp4 << tr("Protected") << ":\t"; temp4 << mpegProp->protectionEnabled(); fileInfo.push_back(temp4.str()); #endif } } struct stat stats; if(stat(path.c_str(), &stats) == 0) { std::stringstream temp; char buf[32]; temp << tr("File size") << ":\t"; if(stats.st_size < 1024) { temp << stats.st_size << " B"; } else if (stats.st_size < 1024*1024) { sprintf(buf, "%0.1f", ((float)stats.st_size)/1024); temp << buf << " KB"; } else { sprintf(buf, "%0.1f", ((float)stats.st_size)/(1024*1024)); temp << buf << " MB"; } fileInfo.push_back(temp.str()); std::stringstream temp2; temp2 << tr("Last Modified") << ":\t"; temp2 << ctime(&stats.st_mtime); // remove '\n' std::string time_str = temp2.str(); if (time_str.length()>0 && time_str.at(time_str.length()-1) == '\n') time_str = time_str.substr(0,time_str.length()-1); fileInfo.push_back(time_str); } return fileInfo; }
/* ** Called during each update of the main measure. ** */ void PlayerWinamp::UpdateData() { if (m_Initialized || CheckWindow()) { const auto playing = SendMessage(m_Window, WM_WA_IPC, 0, IPC_ISPLAYING); if (playing == 0) { // Make sure Winamp is still active if (!IsWindow(m_Window)) { m_Initialized = false; ClearData(); if (m_WinampHandle) CloseHandle(m_WinampHandle); } else if (m_State != STATE_STOPPED) { ClearData(false); } // Don't continue if Winamp has quit or is stopped return; } else { m_State = (playing == 1) ? STATE_PLAYING : STATE_PAUSED; m_Position = (UINT)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETOUTPUTTIME) / 1000; // ms to secs m_Volume = ((UINT)SendMessage(m_Window, WM_WA_IPC, -666, IPC_SETVOLUME) * 100) / 255; // 0 - 255 to 0 - 100 } WCHAR wBuffer[MAX_PATH]; char cBuffer[MAX_PATH]; if (m_UseUnicodeAPI) { if (!ReadProcessMemory(m_WinampHandle, m_WinampAddress, &wBuffer, sizeof(wBuffer), nullptr)) { // Failed to read memory return; } } else { // MediaMonkey doesn't support wide IPC messages const auto pos = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETLISTPOS); LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, pos, IPC_GETPLAYLISTFILE); if (!ReadProcessMemory(m_WinampHandle, address, &cBuffer, sizeof(cBuffer), nullptr)) { // Failed to read memory return; } mbstowcs(wBuffer, cBuffer, MAX_PATH); } if (wcscmp(wBuffer, m_FilePath.c_str()) != 0) { ++m_TrackCount; m_FilePath = wBuffer; m_PlayingStream = (m_FilePath.find(L"://") != std::wstring::npos); if (!m_PlayingStream) { const int duration = (int)SendMessage(m_Window, WM_WA_IPC, 1, IPC_GETOUTPUTTIME); m_Duration = (duration != -1) ? duration : 0; m_Rating = (UINT)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETRATING); m_Shuffle = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_SHUFFLE) != 0; m_Repeat = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_REPEAT) != 0; TagLib::FileRef fr(wBuffer, false); TagLib::Tag* tag = fr.tag(); if (tag) { m_Artist = tag->artist().toWString(); m_Album = tag->album().toWString(); m_Title = tag->title().toWString(); m_Genre = tag->genre().toWString(); m_Number = tag->track(); m_Year = tag->year(); if (m_Measures & MEASURE_LYRICS) { FindLyrics(); } } else if (m_Measures & MEASURE_LYRICS) { m_Lyrics.clear(); } // Find cover if needed if (m_Measures & MEASURE_COVER) { if (tag && CCover::GetEmbedded(fr, m_TempCoverPath)) { // Got everything, return m_CoverPath = m_TempCoverPath; return; } std::wstring trackFolder = CCover::GetFileFolder(m_FilePath); if (tag && !m_Album.empty()) { // Winamp stores covers usually as %album%.jpg std::wstring file = m_Album; std::wstring::size_type end = file.length(); for (std::wstring::size_type pos = 0; pos < end; ++pos) { // Replace reserved chars according to Winamp specs switch (file[pos]) { case L'?': case L'*': case L'|': file[pos] = L'_'; break; case L'/': case L'\\': case L':': file[pos] = L'-'; break; case L'\"': file[pos] = L'\''; break; case L'<': file[pos] = L'('; break; case L'>': file[pos] = L')'; break; } } if (CCover::GetLocal(file, trackFolder, m_CoverPath)) { // %album% art file found return; } } if (!CCover::GetLocal(L"cover", trackFolder, m_CoverPath) && !CCover::GetLocal(L"folder", trackFolder, m_CoverPath)) { // Nothing found m_CoverPath.clear(); } } if (tag) { return; } } else { m_Rating = 0; m_Duration = 0; m_CoverPath.clear(); } } else if (!m_PlayingStream) { if (m_Duration == 0) { const int duration = (int)SendMessage(m_Window, WM_WA_IPC, 1, IPC_GETOUTPUTTIME); m_Duration = (duration != -1) ? duration : 0; } return; } // TagLib couldn't parse the file or Winamp is playing a stream, try to get title if (m_UseUnicodeAPI) { LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, 0, IPC_GET_PLAYING_TITLE); ReadProcessMemory(m_WinampHandle, address, &wBuffer, sizeof(wBuffer), nullptr); } else { const auto pos = SendMessage(m_Window, WM_WA_IPC, 0, IPC_GETLISTPOS); LPCVOID address = (LPCVOID)SendMessage(m_Window, WM_WA_IPC, pos, IPC_GETPLAYLISTTITLE); ReadProcessMemory(m_WinampHandle, address, &cBuffer, sizeof(cBuffer), nullptr); mbstowcs(wBuffer, cBuffer, MAX_PATH); } std::wstring title = wBuffer; std::wstring::size_type pos = title.find(L" - "); if (pos != std::wstring::npos) { m_Artist.assign(title, 0, pos); pos += 3; // Skip " - " m_Title.assign(title, pos, title.length() - pos); m_Album.clear(); if (m_PlayingStream) { // Remove crap from title if playing radio pos = m_Title.find(L" ("); if (pos != std::wstring::npos) { m_Title.resize(pos); } } } else { m_Title = title; m_Artist.clear(); m_Album.clear(); } } }
void TagLibExtractor::extract(ExtractionResult* result) { const QString fileUrl = result->inputUrl(); const QString mimeType = result->inputMimetype(); TagLib::FileRef file(fileUrl.toUtf8().constData(), true); if (file.isNull()) { return; } TagLib::Tag* tags = file.tag(); result->addType(Type::Audio); TagLib::String artists; TagLib::String albumArtists; TagLib::String composers; TagLib::String lyricists; TagLib::StringList genres; // Handling multiple tags in mpeg files. if ((mimeType == QLatin1String("audio/mpeg")) || (mimeType == QLatin1String("audio/mpeg3")) || (mimeType == QLatin1String("audio/x-mpeg"))) { TagLib::MPEG::File mpegFile(fileUrl.toUtf8().constData(), true); if (mpegFile.ID3v2Tag() && !mpegFile.ID3v2Tag()->isEmpty()) { TagLib::ID3v2::FrameList lstID3v2; // Artist. lstID3v2 = mpegFile.ID3v2Tag()->frameListMap()["TPE1"]; if (!lstID3v2.isEmpty()) { for (TagLib::ID3v2::FrameList::ConstIterator it = lstID3v2.begin(); it != lstID3v2.end(); ++it) { if (!artists.isEmpty()) { artists += ", "; } artists += (*it)->toString(); } } // Album Artist. lstID3v2 = mpegFile.ID3v2Tag()->frameListMap()["TPE2"]; if (!lstID3v2.isEmpty()) { for (TagLib::ID3v2::FrameList::ConstIterator it = lstID3v2.begin(); it != lstID3v2.end(); ++it) { if (!albumArtists.isEmpty()) { albumArtists += ", "; } albumArtists += (*it)->toString(); } } // Composer. lstID3v2 = mpegFile.ID3v2Tag()->frameListMap()["TCOM"]; if (!lstID3v2.isEmpty()) { for (TagLib::ID3v2::FrameList::ConstIterator it = lstID3v2.begin(); it != lstID3v2.end(); ++it) { if (!composers.isEmpty()) { composers += ", "; } composers += (*it)->toString(); } } // Lyricist. lstID3v2 = mpegFile.ID3v2Tag()->frameListMap()["TEXT"]; if (!lstID3v2.isEmpty()) { for (TagLib::ID3v2::FrameList::ConstIterator it = lstID3v2.begin(); it != lstID3v2.end(); ++it) { if (!lyricists.isEmpty()) { lyricists += ", "; } lyricists += (*it)->toString(); } } // Genre. lstID3v2 = mpegFile.ID3v2Tag()->frameListMap()["TCON"]; if (!lstID3v2.isEmpty()) { for (TagLib::ID3v2::FrameList::ConstIterator it = lstID3v2.begin(); it != lstID3v2.end(); ++it) { genres.append((*it)->toString()); } } } } // Handling multiple tags in Ogg containers. { TagLib::Ogg::FieldListMap lstOgg; // FLAC files. if (mimeType == QLatin1String("audio/flac")) { TagLib::FLAC::File flacFile(fileUrl.toUtf8().constData(), true); if (flacFile.xiphComment() && !flacFile.xiphComment()->isEmpty()) { lstOgg = flacFile.xiphComment()->fieldListMap(); } } // Vorbis files. if (mimeType == QLatin1String("audio/ogg") || mimeType == QLatin1String("audio/x-vorbis+ogg")) { TagLib::Ogg::Vorbis::File oggFile(fileUrl.toUtf8().constData(), true); if (oggFile.tag() && !oggFile.tag()->isEmpty()) { lstOgg = oggFile.tag()->fieldListMap(); } } // Opus files. if (mimeType == QLatin1String("audio/opus") || mimeType == QLatin1String("audio/x-opus+ogg")) { TagLib::Ogg::Opus::File opusFile(fileUrl.toUtf8().constData(), true); if (opusFile.tag() && !opusFile.tag()->isEmpty()) { lstOgg = opusFile.tag()->fieldListMap(); } } // Handling OGG container tags. if (!lstOgg.isEmpty()) { TagLib::Ogg::FieldListMap::ConstIterator itOgg; // Artist. itOgg = lstOgg.find("ARTIST"); if (itOgg != lstOgg.end()) { if (!artists.isEmpty()) { artists += ", "; } artists += (*itOgg).second.toString(", "); } // Album Artist. itOgg = lstOgg.find("ALBUMARTIST"); if (itOgg != lstOgg.end()) { if (!albumArtists.isEmpty()) { albumArtists += ", "; } albumArtists += (*itOgg).second.toString(", "); } // Composer. itOgg = lstOgg.find("COMPOSER"); if (itOgg != lstOgg.end()) { if (!composers.isEmpty()) { composers += ", "; } composers += (*itOgg).second.toString(", "); } // Lyricist. itOgg = lstOgg.find("LYRICIST"); if (itOgg != lstOgg.end()) { if (!lyricists.isEmpty()) { lyricists += ", "; } lyricists += (*itOgg).second.toString(", "); } // Genre. itOgg = lstOgg.find("GENRE"); if (itOgg != lstOgg.end()) { genres.append((*itOgg).second); } } } // Handling multiple tags in Musepack files. if (mimeType == QLatin1String("audio/x-musepack")) { TagLib::MPC::File mpcFile(fileUrl.toUtf8().constData(), true); if (mpcFile.tag() && !mpcFile.tag()->isEmpty()) { TagLib::APE::ItemListMap lstMusepack = mpcFile.APETag()->itemListMap(); TagLib::APE::ItemListMap::ConstIterator itMPC; // Artist. itMPC = lstMusepack.find("ARTIST"); if (itMPC != lstMusepack.end()) { if (!artists.isEmpty()) { artists += ", "; } artists += (*itMPC).second.toString(); } // Album Artist. itMPC = lstMusepack.find("ALBUMARTIST"); if (itMPC != lstMusepack.end()) { if(!albumArtists.isEmpty()) { albumArtists += ", "; } albumArtists += (*itMPC).second.toString(); } // Composer. itMPC = lstMusepack.find("COMPOSER"); if (itMPC != lstMusepack.end()) { if (!composers.isEmpty()) { composers += ", "; } composers += (*itMPC).second.toString(); } // Lyricist. itMPC = lstMusepack.find("LYRICIST"); if (itMPC != lstMusepack.end()) { if (!lyricists.isEmpty()) { lyricists += ", "; } lyricists += (*itMPC).second.toString(); } // Genre. itMPC = lstMusepack.find("GENRE"); if (itMPC != lstMusepack.end()) { genres.append((*itMPC).second.toString()); } } } if (!tags->isEmpty()) { QString title = t2q(tags->title()); if (!title.isEmpty()) { result->add(Property::Title, title); } QString comment = t2q(tags->comment()); if (!comment.isEmpty()) { result->add(Property::Comment, comment); } if (genres.isEmpty()) { genres.append(tags->genre()); } for (uint i = 0; i < genres.size(); i++) { QString genre = t2q(genres[i]).trimmed(); // Convert from int bool ok = false; int genreNum = genre.toInt(&ok); if (ok) { genre = t2q(TagLib::ID3v1::genre(genreNum)); } result->add(Property::Genre, genre); } QString artistString; if (artists.isEmpty()) { artistString = t2q(tags->artist()); } else { artistString = t2q(artists).trimmed(); } QStringList artists = contactsFromString(artistString); foreach(const QString& artist, artists) { result->add(Property::Artist, artist); }
QString NTagReaderTaglib::parse(const QString &format, bool *success, bool stopOnFail) { if (format.isEmpty()) return ""; *success = true; if (!isValid()) return "NTagReaderTaglib::InvalidFile"; TagLib::Tag *tag = NTaglib::_tagRef->tag(); TagLib::AudioProperties *ap = NTaglib::_tagRef->audioProperties(); int seconds_total = ap->length(); QString res; for (int i = 0; i < format.size(); ++i) { if (format.at(i) == '%') { ++i; QChar ch = format.at(i); if (ch == 'a') { QString str = TStringToQString(tag->artist()); if (!(*success = !str.isEmpty())) str = "<Unknown artist>"; res += str; } else if (ch == 't') { QString str = TStringToQString(tag->title()); if (!(*success = !str.isEmpty())) str = "<Unknown title>"; res += str; } else if (ch == 'A') { QString str = TStringToQString(tag->album()); if (!(*success = !str.isEmpty())) str = "<Unknown album>"; res += str; } else if (ch == 'c') { QString str = TStringToQString(tag->comment()); if (!(*success = !str.isEmpty())) str = "<Empty comment>"; res += str; } else if (ch == 'g') { QString str = TStringToQString(tag->genre()); if (!(*success = !str.isEmpty())) str = "<Unknown genre>"; res += str; } else if (ch == 'y') { QString str = QString::number(tag->year()); if (str == "0") { str = "<Unknown year>"; *success = false; } res += str; } else if (ch == 'n') { QString str = QString::number(tag->track()); if (str == "0") { str = "<Unknown track number>"; *success = false; } res += str; } else if (ch == 'b') { if (auto *prop = dynamic_cast<TagLib::APE::Properties *>(ap)) { res += QString::number(prop->bitsPerSample()); } else if (auto *prop = dynamic_cast<TagLib::FLAC::Properties *>(ap)) { res += QString::number(prop->sampleWidth()); } else if (auto *prop = dynamic_cast<TagLib::MP4::Properties *>(ap)) { res += QString::number(prop->bitsPerSample()); } else if (auto *prop = dynamic_cast<TagLib::RIFF::AIFF::Properties *>(ap)) { res += QString::number(prop->sampleWidth()); } else if (auto *prop = dynamic_cast<TagLib::RIFF::WAV::Properties *>(ap)) { res += QString::number(prop->sampleWidth()); } else if (auto *prop = dynamic_cast<TagLib::TrueAudio::Properties *>(ap)) { res += QString::number(prop->bitsPerSample()); } else if (auto *prop = dynamic_cast<TagLib::WavPack::Properties *>(ap)) { res += QString::number(prop->bitsPerSample()); } else { res += "<Unknown bit depth>"; *success = false; } } else if (ch == 'd') { QString duration; if (seconds_total > 0) { int seconds = seconds_total % 60; int minutes = (seconds_total - seconds) / 60; int hours = minutes / 60; minutes = minutes % 60; if (hours > 0) duration.sprintf("%d:%02d:%02d", hours, minutes, seconds); else duration.sprintf("%d:%02d", minutes, seconds); } else { duration = "<Unknown duration>"; *success = false; } res += duration; } else if (ch == 'D') { QString duration; if (seconds_total == 0) { duration = "<Unknown duration>"; *success = false; } else { duration = QString::number(seconds_total); } res += duration; } else if (ch == 'B') { QString str = QString::number(ap->bitrate()); if (str == "0") { str = "<Unknown bitrate>"; *success = false; } res += str; } else if (ch == 's') { QString str = QString::number(ap->sampleRate() / (float)1000); if (str == "0") { str = "<Unknown sample rate>"; *success = false; } res += str; } else if (ch == 'C') { QString str = QString::number(ap->channels()); if (str == "0") { str = "<Unknown channels number>"; *success = false; } res += str; } else if (ch == 'f') { res += QFileInfo(NTaglib::_filePath).baseName(); } else if (ch == 'F') { res += QFileInfo(NTaglib::_filePath).fileName(); } else if (ch == 'p') { res += QFileInfo(NTaglib::_filePath).absoluteFilePath(); } else if (ch == 'e') { res += QFileInfo(NTaglib::_filePath).suffix(); } else if (ch == 'E') { res += QFileInfo(NTaglib::_filePath).suffix().toUpper(); } else if (ch == 'v') { res += QCoreApplication::applicationVersion(); } else { res += ch; } } else if (format.at(i) == '{') { ++i; int matchedAt = format.indexOf('}', i); if (matchedAt == -1) { res += "<condition error: unmatched '{'>"; return res; } QString condition = format.mid(i, matchedAt - i); if (condition.indexOf('{') != -1) { res += "<condition error: extra '{'>"; return res; } QStringList values = condition.split('|'); if (values.count() < 2) { res += "<condition error: missing '|'>"; return res; } else if (values.count() > 2) { res += "<condition error: extra '|'>"; return res; } bool cond_res; QString cond_true = parse(values.at(0), &cond_res, true); if (cond_res) { res += cond_true; } else { res += parse(values.at(1), &cond_res); } i = matchedAt; } else { res += format.at(i); } if (!*success && stopOnFail) return ""; } return res; }
//Adds dir & its contents to the library void libraryDialog::addDir2Lib(QDir dir) { dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot); QDirIterator di(dir, QDirIterator::Subdirectories); while(di.hasNext()) { di.next(); QString fpath = di.filePath(); QFileInfo f = di.fileInfo(); if(isAudioFile(f))//Add this song to the database { wchar_t wname[250]; //TODO: Dynamic. Need to figure out wchar length from QStr length wname[fpath.toWCharArray(wname)] = 0; TagLib::FileName fname(wname); //We'll store tag information in these: QMap<QString, QString> stmap; QMap<QString, int> itmap; TagLib::File* file = NULL; //MP3 Means we can check for additional info in ID3v2 tags if(f.suffix() == "mp3") { TagLib::MPEG::File* fr = new TagLib::MPEG::File(fname, true, TagLib::AudioProperties::ReadStyle::Fast); if(fr->ID3v2Tag()) { //Somehow this means album artist / band. http://www.id3.org/id3v2.4.0-frames TagLib::ID3v2::FrameList l = fr->ID3v2Tag()->frameList("TPE2"); if(!l.isEmpty()) stmap["albumartist"] = l.front()->toString().toCString(); } file = dynamic_cast<TagLib::File*>(fr); } if(file == NULL) { qDebug() << "ERR: " + fpath; continue; //TODO: Error out here } //Try to get audio properties TagLib::AudioProperties* ap = file->audioProperties(); TagLib::Tag* genTag = file->tag(); stmap["name"] = genTag->title().toCString(); stmap["genre"] = genTag->genre().toCString(); itmap["year"] = genTag->year(); itmap["tracknum"] = genTag->track(); stmap["album"] = genTag->album().toCString(); stmap["artist"] = genTag->artist().toCString(); if(ap != NULL) itmap["length"] = ap->length(); stmap["path"] = fpath; //Add collected info to db DBItem s; s.strVals = stmap; s.intVals = itmap; myparent->dbi->addSong(s); delete file; } else if(f.isDir()) ui.curDirLbl->setText(fpath); //if(top) //If we're the top level of recursion update prog bar // ui.progressBar->setValue(di./siz * 100); qApp->processEvents(); } }
int main(int argc, char *argv[]) { for(int i = 1; i < argc; i++) { cout << "******************** \"" << argv[i] << "\" ********************" << endl; TagLib::FileRef f(argv[i]); if(!f.isNull() && f.tag()) { TagLib::Tag *tag = f.tag(); cout << "-- TAG --" << endl; cout << "title - \"" << tag->title() << "\"" << endl; cout << "artist - \"" << tag->artist() << "\"" << endl; cout << "album artist - \"" << tag->albumArtist() << "\"" << endl; cout << "album - \"" << tag->album() << "\"" << endl; cout << "year - \"" << tag->year() << "\"" << endl; cout << "comment - \"" << tag->comment() << "\"" << endl; cout << "track - \"" << tag->track() << "\"" << endl; cout << "genre - \"" << tag->genre() << "\"" << endl; cout << "grouping - \"" << tag->grouping() << "\"" << endl; TagLib::Ogg::XiphComment *comment = NULL; TagLib::FLAC::File *flac = dynamic_cast<TagLib::FLAC::File *>(f.file()); if (flac) { cout << "flac:" << endl; cout << "id3v1 - \"" << flac->ID3v1Tag() << "\"" << endl; cout << "id3v2 - \"" << flac->ID3v2Tag() << "\"" << endl; cout << "xiph - \"" << flac->xiphComment() << "\"" << endl; comment = flac->xiphComment(); } if (!comment) { comment = dynamic_cast<TagLib::Ogg::XiphComment *>(tag); } if (comment) { TagLib::Ogg::FieldListMap fields = comment->fieldListMap(); for(TagLib::Ogg::FieldListMap::ConstIterator it = fields.begin(), end = fields.end(); it != end; it++) { if (!it->second.isEmpty()) cout << "xiph:" << it->first << " \"" << it->second[0].substr(0,3) << "\"" << endl; } } cout << "pictures- \"" << f.file()->pictures().size() << "\"" << endl; TagLib::File::PictureList l = f.file()->pictures(); for (TagLib::File::_PictureList::ConstIterator i = l.begin(), end = l.end(); i != end; i++) { cout << "\t" << (*i)->typeName() << ' ' << (*i)->mimeType() << ' ' << (*i)->base64data().size() << endl; } cout << "pictures- \"" << tag->pictures().size() << "\"" << endl; } if(!f.isNull() && f.audioProperties()) { TagLib::AudioProperties *properties = f.audioProperties(); int seconds = properties->length() % 60; int minutes = (properties->length() - seconds) / 60; cout << "-- AUDIO --" << endl; cout << "bitrate - " << properties->bitrate() << endl; cout << "sample rate - " << properties->sampleRate() << endl; cout << "channels - " << properties->channels() << endl; cout << "length - " << minutes << ":" << formatSeconds(seconds) << endl; } } return 0; }
void TagReader::ReadFile(const QString& filename, pb::tagreader::SongMetadata* song) const { const QByteArray url(QUrl::fromLocalFile(filename).toEncoded()); const QFileInfo info(filename); qLog(Debug) << "Reading tags from" << filename; song->set_basefilename(DataCommaSizeFromQString(info.fileName())); song->set_url(url.constData(), url.size()); song->set_filesize(info.size()); song->set_mtime(info.lastModified().toTime_t()); song->set_ctime(info.created().toTime_t()); std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename)); if (fileref->isNull()) { qLog(Info) << "TagLib hasn't been able to read " << filename << " file"; return; } TagLib::Tag* tag = fileref->tag(); if (tag) { Decode(tag->title(), nullptr, song->mutable_title()); Decode(tag->artist(), nullptr, song->mutable_artist()); // TPE1 Decode(tag->album(), nullptr, song->mutable_album()); Decode(tag->genre(), nullptr, song->mutable_genre()); song->set_year(tag->year()); song->set_track(tag->track()); song->set_valid(true); } QString disc; QString compilation; // Handle all the files which have VorbisComments (Ogg, OPUS, ...) in the same // way; // apart, so we keep specific behavior for some formats by adding another // "else if" block below. if (TagLib::Ogg::XiphComment* tag = dynamic_cast<TagLib::Ogg::XiphComment*>(fileref->file()->tag())) { ParseOggTag(tag->fieldListMap(), nullptr, &disc, &compilation, song); } if (TagLib::MPEG::File* file = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) { if (file->ID3v2Tag()) { const TagLib::ID3v2::FrameListMap& map = file->ID3v2Tag()->frameListMap(); if (!map["TPOS"].isEmpty()) disc = TStringToQString(map["TPOS"].front()->toString()).trimmed(); if (!map["TBPM"].isEmpty()) song->set_bpm(TStringToQString(map["TBPM"].front()->toString()) .trimmed() .toFloat()); if (!map["TCOM"].isEmpty()) Decode(map["TCOM"].front()->toString(), nullptr, song->mutable_composer()); if (!map["TIT1"].isEmpty()) // content group Decode(map["TIT1"].front()->toString(), nullptr, song->mutable_grouping()); // Skip TPE1 (which is the artist) here because we already fetched it if (!map["TPE2"].isEmpty()) // non-standard: Apple, Microsoft Decode(map["TPE2"].front()->toString(), nullptr, song->mutable_albumartist()); if (!map["TCMP"].isEmpty()) compilation = TStringToQString(map["TCMP"].front()->toString()).trimmed(); if (!map["APIC"].isEmpty()) song->set_art_automatic(kEmbeddedCover); // Find a suitable comment tag. For now we ignore iTunNORM comments. for (int i = 0; i < map["COMM"].size(); ++i) { const TagLib::ID3v2::CommentsFrame* frame = dynamic_cast<const TagLib::ID3v2::CommentsFrame*>(map["COMM"][i]); if (frame && TStringToQString(frame->description()) != "iTunNORM") { Decode(frame->text(), nullptr, song->mutable_comment()); break; } } // Parse FMPS frames for (int i = 0; i < map["TXXX"].size(); ++i) { const TagLib::ID3v2::UserTextIdentificationFrame* frame = dynamic_cast<const TagLib::ID3v2::UserTextIdentificationFrame*>( map["TXXX"][i]); if (frame && frame->description().startsWith("FMPS_")) { ParseFMPSFrame(TStringToQString(frame->description()), TStringToQString(frame->fieldList()[1]), song); } } // Check POPM tags // We do this after checking FMPS frames, so FMPS have precedence, as we // will consider POPM tags iff song has no rating/playcount already set. if (!map["POPM"].isEmpty()) { const TagLib::ID3v2::PopularimeterFrame* frame = dynamic_cast<const TagLib::ID3v2::PopularimeterFrame*>( map["POPM"].front()); if (frame) { // Take a user rating only if there's no rating already set if (song->rating() <= 0 && frame->rating() > 0) { song->set_rating(ConvertPOPMRating(frame->rating())); } if (song->playcount() <= 0 && frame->counter() > 0) { song->set_playcount(frame->counter()); } } } } } else if (TagLib::FLAC::File* file = dynamic_cast<TagLib::FLAC::File*>(fileref->file())) { if (file->xiphComment()) { ParseOggTag(file->xiphComment()->fieldListMap(), nullptr, &disc, &compilation, song); #ifdef TAGLIB_HAS_FLAC_PICTURELIST if (!file->pictureList().isEmpty()) { song->set_art_automatic(kEmbeddedCover); } #endif } Decode(tag->comment(), nullptr, song->mutable_comment()); } else if (TagLib::MP4::File* file = dynamic_cast<TagLib::MP4::File*>(fileref->file())) { if (file->tag()) { TagLib::MP4::Tag* mp4_tag = file->tag(); const TagLib::MP4::ItemListMap& items = mp4_tag->itemListMap(); // Find album artists TagLib::MP4::ItemListMap::ConstIterator it = items.find("aART"); if (it != items.end()) { TagLib::StringList album_artists = it->second.toStringList(); if (!album_artists.isEmpty()) { Decode(album_artists.front(), nullptr, song->mutable_albumartist()); } } // Find album cover art if (items.find("covr") != items.end()) { song->set_art_automatic(kEmbeddedCover); } if (items.contains("disk")) { disc = TStringToQString( TagLib::String::number(items["disk"].toIntPair().first)); } if (items.contains(kMP4_FMPS_Rating_ID)) { float rating = TStringToQString(items[kMP4_FMPS_Rating_ID].toStringList().toString( '\n')).toFloat(); if (song->rating() <= 0 && rating > 0) { song->set_rating(rating); } } if (items.contains(kMP4_FMPS_Playcount_ID)) { int playcount = TStringToQString( items[kMP4_FMPS_Playcount_ID].toStringList().toString('\n')) .toFloat(); if (song->playcount() <= 0 && playcount > 0) { song->set_playcount(playcount); } } if (items.contains(kMP4_FMPS_Playcount_ID)) { int score = TStringToQString( items[kMP4_FMPS_Score_ID].toStringList().toString('\n')) .toFloat() * 100; if (song->score() <= 0 && score > 0) { song->set_score(score); } } if (items.contains("\251wrt")) { Decode(items["\251wrt"].toStringList().toString(", "), nullptr, song->mutable_composer()); } if (items.contains("\251grp")) { Decode(items["\251grp"].toStringList().toString(" "), nullptr, song->mutable_grouping()); } Decode(mp4_tag->comment(), nullptr, song->mutable_comment()); } } #ifdef TAGLIB_WITH_ASF else if (TagLib::ASF::File* file = dynamic_cast<TagLib::ASF::File*>(fileref->file())) { const TagLib::ASF::AttributeListMap& attributes_map = file->tag()->attributeListMap(); if (attributes_map.contains("FMPS/Rating")) { const TagLib::ASF::AttributeList& attributes = attributes_map["FMPS/Rating"]; if (!attributes.isEmpty()) { float rating = TStringToQString(attributes.front().toString()).toFloat(); if (song->rating() <= 0 && rating > 0) { song->set_rating(rating); } } } if (attributes_map.contains("FMPS/Playcount")) { const TagLib::ASF::AttributeList& attributes = attributes_map["FMPS/Playcount"]; if (!attributes.isEmpty()) { int playcount = TStringToQString(attributes.front().toString()).toInt(); if (song->playcount() <= 0 && playcount > 0) { song->set_playcount(playcount); } } } if (attributes_map.contains("FMPS/Rating_Amarok_Score")) { const TagLib::ASF::AttributeList& attributes = attributes_map["FMPS/Rating_Amarok_Score"]; if (!attributes.isEmpty()) { int score = TStringToQString(attributes.front().toString()).toFloat() * 100; if (song->score() <= 0 && score > 0) { song->set_score(score); } } } } #endif else if (tag) { Decode(tag->comment(), nullptr, song->mutable_comment()); } if (!disc.isEmpty()) { const int i = disc.indexOf('/'); if (i != -1) { // disc.right( i ).toInt() is total number of discs, we don't use this at // the moment song->set_disc(disc.left(i).toInt()); } else { song->set_disc(disc.toInt()); } } if (compilation.isEmpty()) { // well, it wasn't set, but if the artist is VA assume it's a compilation if (QStringFromStdString(song->artist()).toLower() == "various artists") { song->set_compilation(true); } } else { song->set_compilation(compilation.toInt() == 1); } if (fileref->audioProperties()) { song->set_bitrate(fileref->audioProperties()->bitrate()); song->set_samplerate(fileref->audioProperties()->sampleRate()); song->set_length_nanosec(fileref->audioProperties()->length() * kNsecPerSec); } // Get the filetype if we can song->set_type(GuessFileType(fileref.get())); // Set integer fields to -1 if they're not valid #define SetDefault(field) \ if (song->field() <= 0) { \ song->set_##field(-1); \ } SetDefault(track); SetDefault(disc); SetDefault(bpm); SetDefault(year); SetDefault(bitrate); SetDefault(samplerate); SetDefault(lastplayed); #undef SetDefault }
bool SqlHelper::INSERT(const char* filepath, const char* url) const // TODO: NULL allowed? { #if 0 if(mPlayerConnection == NULL) return; mPlayerConnection->pass_remote_command((QString("loadfile \"%1\"\n").arg(filepath).toAscii().data())); QString filename = filepath; // filename as SQL wants it filename.replace('\'', "''"); QString metaTitle = corr( mPlayerConnection->fetchValue("get_meta_title\n", "ANS_META_TITLE=") ); printf("metaTitle: %s\n",metaTitle.toAscii().data()); if(metaTitle == "''") { metaTitle = strrchr(filepath, QDir::separator().toAscii()) + 1; metaTitle.resize(metaTitle.lastIndexOf('.')); // get rid of ending /* handle spaces */ metaTitle.replace('_', ' '); bool lastWasSpace = true; for(int i = 0; i<metaTitle.size(); i++) { if( lastWasSpace ) metaTitle[i] = metaTitle[i].toUpper(); lastWasSpace = (metaTitle[i] == ' '); } metaTitle.prepend('\''); metaTitle.append('\''); metaTitle = corr(metaTitle); printf("metaTitle now: %s\n",metaTitle.toAscii().data()); } QByteArray md5sum; calculate_md5sum(filepath, &md5sum); QDateTime last_changed = QFileInfo(filepath).lastModified(); printf("str: %s\n",QString("INSERT INTO 'main' ('id' ,'titel' ,'kuenstler' ,'album' ,'tag' ,'genre' ,'jahr' ,'others' ,'yours' ,'dateityp' ,'qualitaet' ,'bew_yours' ,'bew_others' ,'pfad', 'last_changed', 'md5sum', 'url') " "VALUES ( NULL, %1, %2, %3, '', %4, %5, '0', '0', %6, %7, '0', '0', '%8', '%9', '%10', '%11');") .arg( metaTitle, corr( mPlayerConnection->fetchValue("get_meta_artist\n", "ANS_META_ARTIST=") ), corr( mPlayerConnection->fetchValue("get_meta_album\n", "ANS_META_ALBUM=") ), corr( mPlayerConnection->fetchValue("get_meta_genre\n", "ANS_META_GENRE=") ), mPlayerConnection->fetchValue("get_meta_year\n", "ANS_META_YEAR="), // TODO: interest mPlayerConnection->fetchValue("get_audio_codec\n", "ANS_AUDIO_CODEC="), mPlayerConnection->fetchValue("get_audio_bitrate\n", "ANS_AUDIO_BITRATE="), filename, md5sum.toHex().data() ).arg( last_changed.toTime_t() ).arg( url ).toAscii().data()); const QSqlQuery query = db.exec( /*QString str =*/ QString("INSERT INTO 'main' ('id' ,'titel' ,'kuenstler' ,'album' ,'tag' ,'genre' ,'jahr' ,'others' ,'yours' ,'dateityp' ,'qualitaet' ,'bew_yours' ,'bew_others' ,'pfad', 'last_changed', 'md5sum', 'url') " "VALUES ( NULL, %1, %2, %3, '', %4, %5, '0', '0', %6, %7, '0', '0', '%8', '%9', '%10', '%11');") .arg( metaTitle, corr( mPlayerConnection->fetchValue("get_meta_artist\n", "ANS_META_ARTIST=") ), corr( mPlayerConnection->fetchValue("get_meta_album\n", "ANS_META_ALBUM=") ), corr( mPlayerConnection->fetchValue("get_meta_genre\n", "ANS_META_GENRE=") ), mPlayerConnection->fetchValue("get_meta_year\n", "ANS_META_YEAR="), // TODO: interest mPlayerConnection->fetchValue("get_audio_codec\n", "ANS_AUDIO_CODEC="), mPlayerConnection->fetchValue("get_audio_bitrate\n", "ANS_AUDIO_BITRATE="), filename ) .arg( last_changed.toTime_t() ) .arg ( md5sum.toHex().data() ) .arg ( corr(url) ) ); if(!query.isValid()) { fputs(query.lastError().text().toAscii().data(),stderr); } #else TagLib::FileRef fp(filepath); if(fp.isNull()) { printf("Warning: File not found."); return false; } TagLib::Tag* tag = fp.tag(); TagLib::AudioProperties* audio_props = fp.audioProperties(); QString filename = filepath; // filename as SQL wants it filename.replace('\'', "''"); QString metaTitle = corr( TStringToQString(tag->title()) ); printf("metaTitle: %s\n",metaTitle.toAscii().data()); if(metaTitle.isEmpty()) { metaTitle = strrchr(filepath, QDir::separator().toAscii()) + 1; metaTitle.resize(metaTitle.lastIndexOf('.')); // get rid of ending /* handle spaces */ metaTitle.replace('_', ' '); bool lastWasSpace = true; for(int i = 0; i<metaTitle.size(); i++) { if( lastWasSpace ) metaTitle[i] = metaTitle[i].toUpper(); lastWasSpace = (metaTitle[i] == ' '); } // metaTitle.prepend('\''); // metaTitle.append('\''); metaTitle = corr(metaTitle); printf("metaTitle now: %s\n",metaTitle.toAscii().data()); } QByteArray md5sum; calculate_md5sum(filepath, &md5sum); QDateTime last_changed = QFileInfo(filepath).lastModified(); QString audio_codec = filename; audio_codec.remove(0, audio_codec.lastIndexOf('.')+1); printf("str: %s\n",QString("INSERT INTO 'main' ('id' ,'titel' ,'kuenstler' ,'album' ,'tag' ,'genre' ,'jahr' ,'others' ,'yours' ,'dateityp' ,'qualitaet' ,'bew_yours' ,'bew_others' ,'pfad', 'last_changed', 'md5sum', 'url') " "VALUES ( NULL, '%1', '%2', '%3', '', '%4', '%5', '0', '0', '%6', '%7', '0', '0', '%8', '%9', '%10', '%11');") .arg( metaTitle, corr( TStringToQString(tag->artist()) ), corr( TStringToQString(tag->album()) ), corr( TStringToQString(tag->genre()) ), get_year(tag), // TODO: interest audio_codec, QString::number(audio_props->bitrate()), filename, md5sum.toHex().data() ).arg( last_changed.toTime_t() ).arg( url ).toAscii().data()); const QSqlQuery query = db.exec( /*QString str =*/ QString("INSERT INTO 'main' ('id' ,'titel' ,'kuenstler' ,'album' ,'tag' ,'genre' ,'jahr' ,'others' ,'yours' ,'dateityp' ,'qualitaet' ,'bew_yours' ,'bew_others' ,'pfad', 'last_changed', 'md5sum', 'url') " "VALUES ( NULL, '%1', '%2', '%3', '', '%4', '%5', '0', '0', '%6', '%7', '0', '0', '%8', '%9', '%10', '%11');") .arg( metaTitle, corr( TStringToQString(tag->artist()) ), corr( TStringToQString(tag->album()) ), corr( TStringToQString(tag->genre()) ), get_year(tag), // TODO: interest audio_codec, QString::number(audio_props->bitrate()), filename) .arg( last_changed.toTime_t() ) .arg ( md5sum.toHex().data() ) .arg ( corr(url) ) ); if(!query.isValid()) { fputs(query.lastError().text().toAscii().data(),stderr); } return true; #endif }