123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- #include <QtCore>
- #include <taglib/mpegfile.h>
- #include <taglib/fileref.h>
- #include <taglib/id3v2tag.h>
- #include <taglib/id3v2frame.h>
- #include "tmetadataloader.h"
- #include "urlutils.h"
- using namespace TagLib;
- /** Given a filename, fetches metadata.
- A functor for using TagLib in a with functional algorithm.
- Unfortunately, it is not thread-safe so we don't use it with QtConcurrent. */
- class MetaDataFunctor : public std::unary_function<QUrl, MetaDataValue> {
- public:
- MetaDataValue operator()(QUrl url);
- };
- QString toQString(const TagLib::String &s) {
- #ifdef Q_OS_WIN
- return QString::fromAscii(s.toCString());
- #else
- return QString::fromStdWString(s.toWString());
- #endif
- }
- const QString FMPSPREFIX="[FMPS_Rating] FMPS_Rating ";
- QRegExp fmpsRx("FMPS_Rating ([\\d\\.]+)");
- //start id="functor"
- MetaDataValue MetaDataFunctor::operator ()(QUrl url) {
- using namespace TagLib;
- MetaDataValue retval;
- retval.setUrl(url);
- QString path = UrlUtils::toLocalFile(url);
- FileRef f(path.toLocal8Bit().constData());
- const Tag* t = f.tag();
- if (t == NULL) {
- qDebug() << "error: no tag available: " << path << "\n from URL: " << url.toEncoded();
- return retval;
- }
- retval.setTrackTitle(toQString(t->title()));
- retval.setArtist(toQString(t->artist()));
- retval.setAlbumTitle(toQString(t->album()));
- //end
- QString trackNumber = QString("%1").arg(t->track());
- retval.setTrackNumber(trackNumber);
- retval.setGenre(toQString(t->genre()));
- retval.setComment(toQString(t->comment()));
- /*
- #ifdef FMPS_RATING
- // http://www.freedesktop.org/wiki/Specifications/free-media-player-specs
- MPEG::File mpegFile(path.toLocal8Bit());
- const ID3v2::Tag *id3v2 = mpegFile.ID3v2Tag();
- if (id3v2 != 0) {
- ID3v2::FrameListMap map = id3v2->frameListMap();
- ID3v2::FrameList fl = map["TXXX"];
- if (!fl.isEmpty()) {
- QString v = toQString(fl.front()->toString());
- if (v.contains(fmpsRx)) {
- QString ratingStr = fmpsRx.cap(1);
- double dr = ratingStr.toDouble() * 10.0;
- int rating = (int)dr;
- Preference p(rating);
- retval.setPreference(p);
- }
- }
- //ID3v2::FrameList::ConstIterator litr = fl.begin();
- // while (litr != fl.end()) {
- // ++litr;
- // }
- }
- #else
- // musicmatch style preference
- retval.setPreference(retval.comment());
- #endif
- */
- //start id="functor"
- QTime time(0,0,0,0);
- const AudioProperties* ap = f.audioProperties();
- time = time.addSecs(ap->length());
- retval.setTrackTime(time);
- return retval;
- }
- //end
- const QStringList & TagLib::MetaDataLoader::supportedExtensions() {
- static QStringList sl;
- if (sl.isEmpty()) // there might be more but this is all I care about for now...
- sl << "*.mp3" << "*.mp4" << "*.asf" << "*.wma" << "*.flac" << "*.ogg" << "*.aiff";
- return sl;
- }
- TagLib::MetaDataLoader* TagLib::MetaDataLoader::instance() {
- static TagLib::MetaDataLoader* inst = 0;
- if (inst == 0) {
- inst = new TagLib::MetaDataLoader(qApp);
- }
- return inst;
- }
- //start id="metadataloader"
- TagLib::MetaDataLoader::MetaDataLoader(QObject *parent) :
- SUPER(parent) {
- m_processingMax = 0;
- m_running = false;
- qDebug() << "TagLib::MetaDataLoader created.";
- connect (this, SIGNAL(finished()), this, SLOT(checkForWork()),
- Qt::QueuedConnection);
- }
- void TagLib::MetaDataLoader::get(QUrl path) {
- m_queue << path;
- m_timer.singleShot(2000, this, SLOT(checkForWork()));
- }
- MetaDataLoader* MetaDataLoader::clone(QObject *parent) {
- return new MetaDataLoader(parent);
- }
- void TagLib::MetaDataLoader::checkForWork() {
- MetaDataFunctor functor;
- if (m_queue.isEmpty() && !m_running) {
- m_processingMax = 0;
- return;
- }
- if (m_running ) return;
- m_running = true;
- m_canceled = false;
- QList<QUrl> sl = m_queue;
- m_queue = QList<QUrl>();
- m_processingMax = sl.length();
- emit progressRangeChanged(0, m_processingMax);
- for (int i=0; i<m_processingMax;++i) {
- if (m_canceled) break;
- emit fetched(functor(sl[i]));
- emit progressValueChanged(i);
- qApp->processEvents(); /* Allow the GUI to process events
- (and our signals to be delivered) */
- }
- m_running = false;
- emit finished();
- }
- //end
- void TagLib::MetaDataLoader::cancel() {
- m_canceled = true;
- }
- void TagLib::MetaDataLoader::get(QList<QUrl> paths) {
- m_queue.append(paths);
- checkForWork();
- }
|