Start auto tagging support (using MusicBrainz)

This commit is contained in:
Arnaud Bienner 2011-01-15 20:00:39 +00:00
parent ddd3f119d3
commit d53e74a91f
53 changed files with 663 additions and 4 deletions

View File

@ -69,6 +69,9 @@ endif (WIN32)
find_library(LASTFM_LIBRARIES lastfm)
find_path(LASTFM_INCLUDE_DIRS lastfm/ws.h)
find_library(TUNEPIMP_LIBRARIES tunepimp)
find_path(TUNEPIMP_INCLUDE_DIRS tunepimp-0.5/tunepimp.h)
if (APPLE)
find_library(GROWL Growl)
option(ENABLE_SPARKLE "Sparkle updating" ON)
@ -141,6 +144,7 @@ option(ENABLE_VISUALISATIONS "Use libprojectm visualisations" ON)
option(BUNDLE_PROJECTM_PRESETS "Install Clementine's own copies of libprojectm presets - disable this if you want to use a system package instead" ON)
option(ENABLE_SOUNDMENU "Add Clementine to the Gnome sound menu" ON)
option(ENABLE_LIBLASTFM "Use liblastfm for fetching song info, scrobbling and radio streams" ON)
option(ENABLE_LIBTUNEPIMP "Use libtunepimp for generating fingerprinting for musicbrainz, for auto tagging" ON)
option(ENABLE_SCRIPTING_PYTHON "Enable python scripting" ON)
option(ENABLE_REMOTE "Enable support for using remote controls with Clementine" ON)
@ -168,6 +172,10 @@ if(ENABLE_LIBLASTFM AND LASTFM_LIBRARIES AND LASTFM_INCLUDE_DIRS)
set(HAVE_LIBLASTFM ON)
endif(ENABLE_LIBLASTFM AND LASTFM_LIBRARIES AND LASTFM_INCLUDE_DIRS)
if(ENABLE_LIBTUNEPIMP AND TUNEPIMP_LIBRARIES AND TUNEPIMP_INCLUDE_DIRS)
set(HAVE_LIBTUNEPIMP ON)
endif(ENABLE_LIBTUNEPIMP AND TUNEPIMP_LIBRARIES AND TUNEPIMP_INCLUDE_DIRS)
if(ENABLE_SCRIPTING_PYTHON AND PYTHONLIBS_FOUND AND PYQT_SIP_DIR)
set(HAVE_SCRIPTING_PYTHON ON)
endif(ENABLE_SCRIPTING_PYTHON AND PYTHONLIBS_FOUND AND PYQT_SIP_DIR)
@ -293,5 +301,6 @@ summary_add("Visualisations" ENABLE_VISUALISATIONS)
summary_add("Last.fm support" HAVE_LIBLASTFM)
summary_add("Scripting support: Python" HAVE_SCRIPTING_PYTHON)
summary_add("(Mac OS X) Sparkle integration" HAVE_SPARKLE)
summary_add("MusicBrainz support" HAVE_LIBTUNEPIMP)
summary_add("Remote control support" HAVE_REMOTE)
summary_show()

View File

@ -26,6 +26,10 @@ if(HAVE_LIBLASTFM)
include_directories(${LASTFM_INCLUDE_DIRS})
endif(HAVE_LIBLASTFM)
if(HAVE_LIBTUNEPIMP)
include_directories(${TUNEPIMP_INCLUDE_DIRS})
endif(HAVE_LIBTUNEPIMP)
if(HAVE_SCRIPTING_PYTHON)
include_directories(${PYTHON_INCLUDE_DIRS})
endif(HAVE_SCRIPTING_PYTHON)
@ -73,6 +77,7 @@ set(SOURCES
core/stylesheetloader.cpp
core/taskmanager.cpp
core/utilities.cpp
core/tagfetcher.cpp
devices/connecteddevice.cpp
devices/devicedatabasebackend.cpp
@ -257,6 +262,7 @@ set(HEADERS
core/player.h
core/songloader.h
core/taskmanager.h
core/tagfetcher.h
devices/connecteddevice.h
devices/devicedatabasebackend.h
@ -874,6 +880,10 @@ if(HAVE_LIBLASTFM)
target_link_libraries(clementine_lib ${LASTFM_LIBRARIES})
endif(HAVE_LIBLASTFM)
if(HAVE_LIBTUNEPIMP)
target_link_libraries(clementine_lib ${TUNEPIMP_LIBRARIES})
endif(HAVE_LIBTUNEPIMP)
if(HAVE_LIBGPOD)
target_link_libraries(clementine_lib ${LIBGPOD_LIBRARIES})
endif(HAVE_LIBGPOD)

View File

@ -38,6 +38,7 @@
#cmakedefine HAVE_LIBGPOD
#cmakedefine HAVE_LIBINDICATE
#cmakedefine HAVE_LIBLASTFM
#cmakedefine HAVE_LIBTUNEPIMP
#cmakedefine HAVE_LIBMTP
#cmakedefine HAVE_SCRIPTING_PYTHON

210
src/core/tagfetcher.cpp Normal file
View File

@ -0,0 +1,210 @@
/* This file is part of Clementine.
Copyright 2010, David Sansome <me@davidsansome.com>
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tagfetcher.h"
#include <QtDebug>
#include <QFile>
#include <QStringList>
#include <QNetworkReply>
#ifdef HAVE_LIBTUNEPIMP
static void NotifyCallback(tunepimp_t /*pimp*/, void */*data*/, TPCallbackEnum type, int fileId, TPFileStatus status);
const char* kMusicBrainzLookupUrl = "http://musicbrainz.org/ws/1/track/?type=xml&puid=%1";
TagFetcher::TagFetcher(QObject *parent)
: QObject(parent),
network_(new NetworkAccessManager(this)),
pimp_(NULL)
{
//active_fetchers_ = new QMap<int, TagFetcherItem*>;
pimp_ = tp_New("FETCHTAG", "0.1");
tp_SetDebug(pimp_, true);
tp_SetAutoSaveThreshold(pimp_, -1);
tp_SetMoveFiles(pimp_, false);
tp_SetRenameFiles(pimp_, false);
tp_SetFileNameEncoding(pimp_, "UTF-8");
tp_SetNotifyCallback(pimp_, NotifyCallback, this);
tp_SetMusicDNSClientId(pimp_, "0c6019606b1d8a54d0985e448f3603ca");
}
TagFetcher::~TagFetcher() {
delete network_;
tp_Delete(pimp_);
}
void TagFetcher::FetchFromFile(const QString& path) {
int id = tp_AddFile(pimp_, QFile::encodeName(path), 0);
TagFetcherItem* tagFetcherItem = new TagFetcherItem(path, id, pimp_, network_);
connect(tagFetcherItem, SIGNAL(PuidGeneratedSignal()), tagFetcherItem, SLOT(PuidGeneratedSlot()), Qt::QueuedConnection);
active_fetchers_.insert(id, tagFetcherItem);
connect(tagFetcherItem, SIGNAL(FetchFinishedSignal(int)), SLOT(FetchFinishedSlot(int)));
}
static void NotifyCallback(tunepimp_t pimp, void *data, TPCallbackEnum type, int fileId, TPFileStatus status)
{
TagFetcher *tagFetcher = (TagFetcher*)data;
tagFetcher->CallReturned(fileId, status);
if(type != tpFileChanged)
return;
}
void TagFetcher::CallReturned(int fileId, TPFileStatus status)
{
/*for(QMap<int, TagFetcherItem*>::Iterator it = active_fetchers_.begin();
it != active_fetchers_.end(); ++it) {
qDebug() << it.key();
active_fetchers_.insert(it.key(), it.value());
}*/
TagFetcherItem *tagFetcherItem = active_fetchers_.value(fileId);
switch(status) {
case eRecognized:
// TODO
break;
case eUnrecognized:
tagFetcherItem->Unrecognized();
break;
case ePUIDLookup:
case ePUIDCollision:
case eFileLookup:
//TODO
tagFetcherItem->PuidGenerated();
break;
case eUserSelection:
// TODO
break;
case eError:
//TODO
break;
default:
break;
}
}
void TagFetcher::FetchFinishedSlot(int id) {
TagFetcherItem *tagFetcherItem = active_fetchers_.value(id);
tp_Remove(pimp_, id);
active_fetchers_.erase(active_fetchers_.find(id));
emit FetchFinished(tagFetcherItem->getFilename(), tagFetcherItem->getSongsFetched());
delete tagFetcherItem;
}
TagFetcherItem::TagFetcherItem() { }
TagFetcherItem::TagFetcherItem(const QString& _filename, int _fileId, tunepimp_t _pimp, NetworkAccessManager *_network)
: filename_(_filename),
fileId_(_fileId),
pimp_(_pimp),
network_(_network)
{ }
TagFetcherItem::~TagFetcherItem()
{ }
void TagFetcherItem::Unrecognized() {
char trm[255];
bool finish = false;
trm[0] = 0;
track_t track = tp_GetTrack(pimp_, fileId_);
tr_Lock(track);
tr_GetPUID(track, trm, 255);
if ( !trm[0] ) {
tr_SetStatus(track, ePending);
tp_Wake(pimp_, track);
}
else {
finish = true;
}
tr_Unlock(track);
tp_ReleaseTrack(pimp_, track);
if ( !finish )
return;
//TODO clear
}
void TagFetcherItem::PuidGenerated() {
// Get PUID
track_t track = tp_GetTrack(pimp_, fileId_);
tr_Lock(track);
tr_GetPUID(track, puid_, 255);
tr_Unlock(track);
tp_ReleaseTrack(pimp_, track);
// Now we have PUID, let's download song's info from musicbrainz's Web Service
emit PuidGeneratedSignal();
}
void TagFetcherItem::PuidGeneratedSlot() {
QString reqString(QString(kMusicBrainzLookupUrl).arg(QString(puid_)));
QNetworkRequest req = QNetworkRequest(QUrl(reqString));
req.setAttribute(QNetworkRequest::CacheLoadControlAttribute,
QNetworkRequest::AlwaysNetwork);
QNetworkReply* reply = network_->get(req);
connect(reply, SIGNAL(finished()), SLOT(DownloadInfoFinished()));
}
void TagFetcherItem::DownloadInfoFinished() {
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
Q_ASSERT(reply);
QXmlStreamReader reader(reply);
while(!reader.atEnd()) {
reader.readNext();
if(reader.tokenType() == QXmlStreamReader::StartElement &&
reader.name() == "track") {
songs_fetched_ << ReadTrack(&reader);
}
}
emit FetchFinishedSignal(fileId_);
}
SongList TagFetcherItem::ReadTrack(QXmlStreamReader *reader) {
QString currentArtist;
QString currentTitle;
SongList songs;
while(!reader->atEnd()) {
reader->readNext();
if(reader->tokenType() == QXmlStreamReader::StartElement) {
if(reader->name() == "title") { // track's title
currentTitle = reader->readElementText();
} else if(reader->name() == "artist") {
reader->readNext();
if(reader->name() == "name") {
currentArtist = reader->readElementText();
}
} else if(reader->name() == "release-list") {
while(!reader->atEnd()) {
reader->readNext();
if(reader->name() == "title") { // album (release) title
QString albumTitle = reader->readElementText();
Song newSongMatch;
newSongMatch.Init(currentTitle, currentArtist, albumTitle, 0); // Using 0 as length. We could have used <duration> field but it is not usefull, so don't wasting our time and keeping 0
songs << newSongMatch;
} else if(reader->tokenType() == QXmlStreamReader::EndElement &&
reader->name() == "release-list") {
break;
}
}
}
}
}
return songs;
}
#endif // HAVE_LIBTUNEPIMP

95
src/core/tagfetcher.h Normal file
View File

@ -0,0 +1,95 @@
/* This file is part of Clementine.
Copyright 2010, David Sansome <me@davidsansome.com>
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TAGFETCHER_H
#define TAGFETCHER_H
#include "config.h"
#include "core/network.h"
#include "core/song.h"
#include <QtDebug>
#include <QMap>
#include <QXmlStreamReader>
#include <tunepimp-0.5/tp_c.h>
class TagFetcherItem;
class TagFetcher : public QObject {
Q_OBJECT
#ifdef HAVE_LIBTUNEPIMP
public:
TagFetcher(QObject *parent = 0);
~TagFetcher();
void FetchFromFile(const QString& path);
void CallReturned(int fileId, TPFileStatus status);
signals:
void FetchFinished(QString filename, SongList songs_guessed);
private slots:
void FetchFinishedSlot(int id);
private:
NetworkAccessManager *network_;
tunepimp_t pimp_;
QMap<int, TagFetcherItem*> active_fetchers_;
#endif // HAVE_LIBTUNEPIMP
};
class TagFetcherItem : public QObject {
Q_OBJECT
#ifdef HAVE_LIBTUNEPIMP
public:
TagFetcherItem();
TagFetcherItem(const QString& filename, int filedId, tunepimp_t pimp, NetworkAccessManager *network);
~TagFetcherItem();
void setFileId(int _fileId) { fileId_ = _fileId; };
int getFileId() { return fileId_; };
void setFilename(const QString& _filename) { filename_ = _filename; };
QString getFilename() { return filename_; }
SongList getSongsFetched() { return songs_fetched_; }
void Unrecognized();
void PuidGenerated();
signals:
void PuidGeneratedSignal();
void FetchFinishedSignal(int id);
private slots:
void PuidGeneratedSlot();
void DownloadInfoFinished();
private:
SongList ReadTrack(QXmlStreamReader *reader);
private:
QString filename_;
int fileId_; // tunepimp generated id
tunepimp_t pimp_;
NetworkAccessManager *network_;
char puid_[255];
SongList songs_fetched_;
#endif // HAVE_LIBTUNEPIMP
};
#endif // TAGFETCHER_H

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr ""
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "الملحّن"
@ -1034,6 +1037,9 @@ msgstr ""
msgid "General settings"
msgstr ""
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "النوع"

View File

@ -535,6 +535,9 @@ msgstr "Колер"
msgid "Comment"
msgstr "Каментар"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Кампазітар"
@ -1048,6 +1051,9 @@ msgstr ""
msgid "General settings"
msgstr ""
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr ""

View File

@ -527,6 +527,9 @@ msgstr "Цвят"
msgid "Comment"
msgstr "Коментар"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr ""
@ -1036,6 +1039,9 @@ msgstr ""
msgid "General settings"
msgstr "Общи настройки"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Жанр"

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr ""
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr ""
@ -1034,6 +1037,9 @@ msgstr ""
msgid "General settings"
msgstr ""
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr ""

View File

@ -548,6 +548,9 @@ msgstr "Color"
msgid "Comment"
msgstr "Comentari"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Compositor"
@ -1065,6 +1068,9 @@ msgstr "Motor d'audio GStreamer"
msgid "General settings"
msgstr "Arranjaments generals"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Gènere"

View File

@ -543,6 +543,9 @@ msgstr "Barva"
msgid "Comment"
msgstr "Poznámka"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Skladatel"
@ -1061,6 +1064,9 @@ msgstr "Zvukový stroj GStreamer"
msgid "General settings"
msgstr "Obecná nastavení"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Žánr"

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr ""
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr ""
@ -1034,6 +1037,9 @@ msgstr ""
msgid "General settings"
msgstr ""
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr ""

View File

@ -528,6 +528,9 @@ msgstr ""
msgid "Comment"
msgstr "Kommentar"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Komponist"
@ -1037,6 +1040,9 @@ msgstr "GStreamer lydmotor"
msgid "General settings"
msgstr "Generelle indstillinger"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Genre"

View File

@ -547,6 +547,9 @@ msgstr "Farbe"
msgid "Comment"
msgstr "Kommentar"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Komponist"
@ -1064,6 +1067,9 @@ msgstr "GStreamer Audio Engine"
msgid "General settings"
msgstr "Allgemeine Einstellungen"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Genre"

View File

@ -550,6 +550,9 @@ msgstr "Χρώμα"
msgid "Comment"
msgstr "Σχόλια"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Συνθέτης"
@ -1071,6 +1074,9 @@ msgstr "GStreamer, μηχανή ήχου"
msgid "General settings"
msgstr "Γενικές ρυθμίσεις"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Είδος"

View File

@ -516,6 +516,9 @@ msgstr ""
msgid "Comment"
msgstr ""
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr ""
@ -1023,6 +1026,9 @@ msgstr ""
msgid "General settings"
msgstr ""
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr ""

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr "Comment"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Composer"
@ -1037,6 +1040,9 @@ msgstr "GStreamer audio engine"
msgid "General settings"
msgstr "General settings"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Genre"

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr "Comment"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Composer"
@ -1035,6 +1038,9 @@ msgstr "GStreamer audio engine"
msgid "General settings"
msgstr "General settings"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Genre"

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr ""
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr ""
@ -1034,6 +1037,9 @@ msgstr ""
msgid "General settings"
msgstr ""
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr ""

View File

@ -549,6 +549,9 @@ msgstr "Color"
msgid "Comment"
msgstr "Comentario"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Compositor"
@ -1069,6 +1072,9 @@ msgstr "Motor de audio GStreamer"
msgid "General settings"
msgstr "Preferencias generales"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Género"

View File

@ -527,6 +527,9 @@ msgstr "Värv"
msgid "Comment"
msgstr "Märkus"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Helilooja"
@ -1035,6 +1038,9 @@ msgstr ""
msgid "General settings"
msgstr "Üldised seadistused"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Žanr"

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr ""
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr ""
@ -1034,6 +1037,9 @@ msgstr ""
msgid "General settings"
msgstr ""
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr ""

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr "Kommentti"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Säveltäjä"
@ -1034,6 +1037,9 @@ msgstr ""
msgid "General settings"
msgstr "Yleiset asetukset"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Tyylilaji"

View File

@ -551,6 +551,9 @@ msgstr "Couleur"
msgid "Comment"
msgstr "Commentaire"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Compositeur"
@ -1073,6 +1076,9 @@ msgstr "Moteur audio GStreamer"
msgid "General settings"
msgstr "Configuration générale"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Genre"

View File

@ -531,6 +531,9 @@ msgstr ""
msgid "Comment"
msgstr ""
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Compositor"
@ -1038,6 +1041,9 @@ msgstr ""
msgid "General settings"
msgstr ""
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Xénero"

View File

@ -529,6 +529,9 @@ msgstr "צבע"
msgid "Comment"
msgstr "הערה"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "מלחין"
@ -1038,6 +1041,9 @@ msgstr "מנוע האודיו של GStreamer"
msgid "General settings"
msgstr "הגדרות כלליות"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "סגנון"

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr ""
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr ""
@ -1034,6 +1037,9 @@ msgstr ""
msgid "General settings"
msgstr ""
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr ""

View File

@ -533,6 +533,9 @@ msgstr ""
msgid "Comment"
msgstr ""
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr ""
@ -1040,6 +1043,9 @@ msgstr ""
msgid "General settings"
msgstr ""
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr ""

View File

@ -542,6 +542,9 @@ msgstr "Szín"
msgid "Comment"
msgstr "Megjegyzés"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Zeneszerző"
@ -1062,6 +1065,9 @@ msgstr "GStreamer audio meghajtó"
msgid "General settings"
msgstr "Általános beállítások"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Műfaj"

View File

@ -547,6 +547,9 @@ msgstr "Colore"
msgid "Comment"
msgstr "Commento"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Compositore"
@ -1066,6 +1069,9 @@ msgstr "Motore audio GStreamer"
msgid "General settings"
msgstr "Impostazioni generali"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Genere"

View File

@ -537,6 +537,9 @@ msgstr "色"
msgid "Comment"
msgstr "コメント"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "作曲者"
@ -1055,6 +1058,9 @@ msgstr "GStreamer オーディオ エンジン"
msgid "General settings"
msgstr "全般設定"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "ジャンル"

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr ""
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr ""
@ -1034,6 +1037,9 @@ msgstr ""
msgid "General settings"
msgstr ""
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Жанры"

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr ""
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr ""
@ -1034,6 +1037,9 @@ msgstr ""
msgid "General settings"
msgstr ""
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr ""

View File

@ -534,6 +534,9 @@ msgstr "Farge"
msgid "Comment"
msgstr "Kommentar"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Komponist"
@ -1046,6 +1049,9 @@ msgstr "GStreamer lydmotor"
msgid "General settings"
msgstr "Generelle innstillinger"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Sjanger"

View File

@ -539,6 +539,9 @@ msgstr "Kleur"
msgid "Comment"
msgstr "Opmerking"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Componist"
@ -1057,6 +1060,9 @@ msgstr "GStreamer audio engine"
msgid "General settings"
msgstr "Algemene instellingen"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Genre"

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr "Comentari"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Compositor"
@ -1034,6 +1037,9 @@ msgstr "Motor àudio GStreamer"
msgid "General settings"
msgstr "Paramètres generals"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Genre"

View File

@ -545,6 +545,9 @@ msgstr "Kolor"
msgid "Comment"
msgstr "Komentarz"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Kompozytor"
@ -1062,6 +1065,9 @@ msgstr "Silnik dźwiękowy GStreamer"
msgid "General settings"
msgstr "Podstawowe ustawienia"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Gatunek"

View File

@ -547,6 +547,9 @@ msgstr "Cor"
msgid "Comment"
msgstr "Comentário"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Compositor"
@ -1066,6 +1069,9 @@ msgstr "Sistema de áudio GSTreamer"
msgid "General settings"
msgstr "Definições gerais"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Género"

View File

@ -540,6 +540,9 @@ msgstr "Cor"
msgid "Comment"
msgstr "Comentário"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Composto por"
@ -1059,6 +1062,9 @@ msgstr "Mecanismo de áudio GStreamer"
msgid "General settings"
msgstr "Configurações gerais"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Gênero"

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr "Comentariu"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Compozitor"
@ -1034,6 +1037,9 @@ msgstr ""
msgid "General settings"
msgstr "Setări generale"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Gen"

View File

@ -540,6 +540,9 @@ msgstr "Цвет"
msgid "Comment"
msgstr "Комментарий"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Композитор"
@ -1057,6 +1060,9 @@ msgstr "Движок аудио GStreamer"
msgid "General settings"
msgstr "Общие настройки"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Жанр"

View File

@ -539,6 +539,9 @@ msgstr "Farba"
msgid "Comment"
msgstr "Komentár"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Skladateľ"
@ -1056,6 +1059,9 @@ msgstr "GStreamer audio engine"
msgid "General settings"
msgstr "Všeobecné nastavenia"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Žáner"

View File

@ -541,6 +541,9 @@ msgstr "Barva"
msgid "Comment"
msgstr "Opomba"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Skladatelj"
@ -1058,6 +1061,9 @@ msgstr "GStreamerjev zvočni pogon"
msgid "General settings"
msgstr "Splošne nastavitve"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Zvrst"

View File

@ -527,6 +527,9 @@ msgstr ""
msgid "Comment"
msgstr "Коментар"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Композитор"
@ -1037,6 +1040,9 @@ msgstr "Гстример звучни мотор"
msgid "General settings"
msgstr "Опште поставке"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Жанр"

View File

@ -545,6 +545,9 @@ msgstr "Färg"
msgid "Comment"
msgstr "Kommentar"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Kompositör"
@ -1062,6 +1065,9 @@ msgstr "GStreamer-ljudmotor"
msgid "General settings"
msgstr "Allmänna inställningar"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Genre"

View File

@ -538,6 +538,9 @@ msgstr "Renk"
msgid "Comment"
msgstr "Yorum"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Besteci"
@ -1055,6 +1058,9 @@ msgstr "GStreamer ses motoru"
msgid "General settings"
msgstr "Genel ayarlar"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Tür"

View File

@ -517,6 +517,9 @@ msgstr ""
msgid "Comment"
msgstr ""
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr ""
@ -1024,6 +1027,9 @@ msgstr ""
msgid "General settings"
msgstr ""
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr ""

View File

@ -542,6 +542,9 @@ msgstr "Колір"
msgid "Comment"
msgstr "Коментар"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "Композитор"
@ -1058,6 +1061,9 @@ msgstr "Аудіо-рушій GStreamer"
msgid "General settings"
msgstr "Загальні налаштування"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "Жанр"

View File

@ -529,6 +529,9 @@ msgstr ""
msgid "Comment"
msgstr "备注"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "作曲家"
@ -1036,6 +1039,9 @@ msgstr ""
msgid "General settings"
msgstr "常规设置"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "流派"

View File

@ -531,6 +531,9 @@ msgstr ""
msgid "Comment"
msgstr "評論"
msgid "Complete automatically"
msgstr ""
msgid "Composer"
msgstr "作曲家"
@ -1038,6 +1041,9 @@ msgstr "GStreamer的音頻引擎"
msgid "General settings"
msgstr "一般設定"
msgid "Generating audio fingerprint and fetching results..."
msgstr ""
msgid "Genre"
msgstr "風格"

View File

@ -42,6 +42,8 @@
#include <QtDebug>
const char* EditTagDialog::kHintText = QT_TR_NOOP("(different across multiple songs)");
const char* EditTagDialog::kTagFetchText = QT_TR_NOOP("Complete automatically");
const char* EditTagDialog::kTagFetchOnLoadText = QT_TR_NOOP("Generating audio fingerprint and fetching results...");
EditTagDialog::EditTagDialog(QWidget* parent)
: QDialog(parent),
@ -49,6 +51,9 @@ EditTagDialog::EditTagDialog(QWidget* parent)
backend_(NULL),
loading_(false),
ignore_edits_(false),
#ifdef HAVE_LIBTUNEPIMP
tag_fetcher_(new TagFetcher()),
#endif
#ifdef HAVE_LIBLASTFM
cover_searcher_(new AlbumCoverSearcher(QIcon(":/nocover.png"), this)),
cover_fetcher_(new AlbumCoverFetcher(this)),
@ -61,6 +66,9 @@ EditTagDialog::EditTagDialog(QWidget* parent)
cover_loader_->Worker()->SetDefaultOutputImage(QImage(":nocover.png"));
connect(cover_loader_->Worker().get(), SIGNAL(ImageLoaded(quint64,QImage)),
SLOT(ArtLoaded(quint64,QImage)));
#ifdef HAVE_LIBTUNEPIMP
connect(tag_fetcher_, SIGNAL(FetchFinished(QString, SongList)), SLOT(FetchTagFinished(QString, SongList)));
#endif
#ifdef HAVE_LIBLASTFM
cover_searcher_->Init(cover_fetcher_);
@ -69,6 +77,11 @@ EditTagDialog::EditTagDialog(QWidget* parent)
ui_->setupUi(this);
ui_->splitter->setSizes(QList<int>() << 200 << width() - 200);
ui_->loading_container->hide();
#ifdef HAVE_LIBTUNEPIMP
ui_->fetch_tag->setText(kTagFetchText);
#else
ui_->fetch_tag->setVisible(false);
#endif
// An editable field is one that has a label as a buddy. The label is
// important because it gets turned bold when the field is changed.
@ -118,6 +131,10 @@ EditTagDialog::EditTagDialog(QWidget* parent)
connect(ui_->rating, SIGNAL(RatingChanged(float)),
SLOT(SongRated(float)));
connect(ui_->playcount_reset, SIGNAL(clicked()), SLOT(ResetPlayCounts()));
#ifdef HAVE_LIBTUNEPIMP
connect(ui_->fetch_tag, SIGNAL(clicked()), SLOT(FetchTag()));
ui_->fetch_tag->setText(kTagFetchText);
#endif
// Set up the album cover menu
cover_menu_ = new QMenu(this);
@ -167,6 +184,7 @@ bool EditTagDialog::SetLoading(const QString& message) {
ui_->button_box->setEnabled(!loading);
ui_->tab_widget->setEnabled(!loading);
ui_->song_list->setEnabled(!loading);
ui_->fetch_tag->setEnabled(!loading);
ui_->loading_label->setText(message);
return true;
}
@ -231,6 +249,9 @@ void EditTagDialog::SetSongsFinished() {
previous_button_->setEnabled(multiple);
next_button_->setEnabled(multiple);
// Display tag fetcher if there's only one song
ui_->fetch_tag->setVisible(!multiple);
ui_->tab_widget->setCurrentWidget(multiple ? ui_->tags_tab : ui_->summary_tab);
}
@ -670,3 +691,31 @@ void EditTagDialog::ResetPlayCounts() {
backend_->ResetStatisticsAsync(song->id());
UpdateStatisticsTab(*song);
}
void EditTagDialog::FetchTag() {
#ifdef HAVE_LIBTUNEPIMP
const QModelIndexList sel = ui_->song_list->selectionModel()->selectedIndexes();
if (sel.isEmpty())
return;
Song* song = &data_[sel.first().row()].original_;
if (!song->is_valid() || song->id() == -1)
return;
tag_fetcher_->FetchFromFile(song->filename());
ui_->fetch_tag->setDisabled(true); // disable button, will be re-enabled later
ui_->fetch_tag->setText(kTagFetchOnLoadText);
#endif
}
void EditTagDialog::FetchTagFinished(QString filename, SongList songs_guessed) {
#ifdef HAVE_LIBTUNEPIMP
ui_->fetch_tag->setDisabled(false);
ui_->fetch_tag->setText(kTagFetchText);
// TODO: pop-up a window with suggestions (songs_guessed) and complete tags
foreach(const Song& song, songs_guessed) {
qDebug() << "Song guessed:";
qDebug() << "Artist: " + song.artist();
qDebug() << "Album: " + song.album();
qDebug() << "Title: " + song.title();
}
#endif
}

View File

@ -24,6 +24,9 @@
#include "config.h"
#include "core/backgroundthread.h"
#include "core/song.h"
#ifdef HAVE_LIBTUNEPIMP
# include "core/tagfetcher.h"
#endif
#include "playlist/playlistitem.h"
#include "widgets/lineedit.h"
@ -49,6 +52,8 @@ public:
~EditTagDialog();
static const char* kHintText;
static const char* kTagFetchText;
static const char* kTagFetchOnLoadText;
void SetSongs(const SongList& songs, const PlaylistItemList& items = PlaylistItemList());
void SetTagCompleter(LibraryBackend* backend);
@ -74,6 +79,8 @@ private slots:
void ButtonClicked(QAbstractButton* button);
void SongRated(float rating);
void ResetPlayCounts();
void FetchTag();
void FetchTagFinished(QString filename, SongList songs_guessed);
void ArtLoaded(quint64 id, const QImage& image);
@ -139,6 +146,10 @@ private:
bool ignore_edits_;
#ifdef HAVE_LIBTUNEPIMP
TagFetcher* tag_fetcher_;
#endif
#ifdef HAVE_LIBLASTFM
AlbumCoverSearcher* cover_searcher_;
AlbumCoverFetcher* cover_fetcher_;

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>863</width>
<height>571</height>
<height>586</height>
</rect>
</property>
<property name="windowTitle">
@ -30,7 +30,7 @@
</widget>
<widget class="QTabWidget" name="tab_widget">
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<widget class="QWidget" name="summary_tab">
<attribute name="title">
@ -711,7 +711,7 @@
</property>
</widget>
</item>
<item row="6" column="0">
<item row="7" column="0">
<widget class="QLabel" name="comment_label">
<property name="text">
<string>Comment</string>
@ -721,7 +721,7 @@
</property>
</widget>
</item>
<item row="6" column="1" colspan="3">
<item row="7" column="1" colspan="3">
<widget class="TextEdit" name="comment">
<property name="has_reset_button" stdset="0">
<bool>true</bool>
@ -731,6 +731,10 @@
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QPushButton" name="fetch_tag">
</widget>
</item>
</layout>
</widget>
</widget>