Commit 4f3950ab authored by Scott Wheeler's avatar Scott Wheeler
Browse files

Don't use the external TRM tool but instead use libtunepimp since it handles

these things internally.  This keeps JuK from spawning loads of TRM processes,
makes it such that it's not using the TRM tool (which wasn't ever intended for
application use), gives an appropriate place to change the string for
when the server is under heavy load (but wasn't touched because of the string
freeze) and will make it easy to only popup one dialog at a time (that will
come tomorrow).  No strings were added or changed, though some were moved
around.

CCMAIL:66721-done@bugs.kde.org
CCMAIL:65219-done@bugs.kde.org
CCMAIL:86413@bugs.kde.org
CCMAIL:79652@bugs.kde.org

svn path=/trunk/kdemultimedia/juk/; revision=335381
parent 02d3385d
...@@ -23,7 +23,6 @@ juk_SOURCES = \ ...@@ -23,7 +23,6 @@ juk_SOURCES = \
keydialog.cpp \ keydialog.cpp \
main.cpp \ main.cpp \
mediafiles.cpp \ mediafiles.cpp \
musicbrainzitem.cpp \
musicbrainzquery.cpp \ musicbrainzquery.cpp \
painteater.cpp \ painteater.cpp \
playermanager.cpp \ playermanager.cpp \
...@@ -50,6 +49,7 @@ juk_SOURCES = \ ...@@ -50,6 +49,7 @@ juk_SOURCES = \
trackpickerdialog.cpp \ trackpickerdialog.cpp \
trackpickerdialogbase.ui \ trackpickerdialogbase.ui \
treeviewitemplaylist.cpp \ treeviewitemplaylist.cpp \
ktrm.cpp \
viewmode.cpp viewmode.cpp
tagguessertest_SOURCES = tagguessertest.cpp tagguesser.cpp tagguessertest_SOURCES = tagguessertest.cpp tagguesser.cpp
...@@ -69,7 +69,7 @@ endif ...@@ -69,7 +69,7 @@ endif
# check to see if MusicBrainz is available # check to see if MusicBrainz is available
################################################## ##################################################
if link_lib_MB if link_lib_MB
mblibs = -lmusicbrainz mblibs = -lmusicbrainz -ltunepimp
endif endif
################################################## ##################################################
......
...@@ -114,7 +114,7 @@ void CollectionList::clearItems(const PlaylistItemList &items) ...@@ -114,7 +114,7 @@ void CollectionList::clearItems(const PlaylistItemList &items)
void CollectionList::setupTreeViewEntries(ViewMode *viewMode) const void CollectionList::setupTreeViewEntries(ViewMode *viewMode) const
{ {
TreeViewMode *treeViewMode = dynamic_cast<TreeViewMode*>(viewMode); TreeViewMode *treeViewMode = dynamic_cast<TreeViewMode *>(viewMode);
if(!treeViewMode) { if(!treeViewMode) {
kdWarning(65432) << "Can't setup entries on a non-tree-view mode!\n"; kdWarning(65432) << "Can't setup entries on a non-tree-view mode!\n";
return; return;
......
if test "x$have_taglib" = "xfalse"; then if test "x$have_taglib" = "xfalse"; then
echo "**************************************************" echo "**************************************************"
echo "*" echo "*"
echo "* JuK will not be built without TagLib. TagLib" echo "* JuK will not be built without TagLib."
echo "* replaces the id3lib dependancy. See the notice" echo "* See the notice below for where to find TagLib."
echo "* below for where to find TagLib."
echo "*" echo "*"
echo "**************************************************" echo "**************************************************"
fi fi
...@@ -27,11 +26,14 @@ fi ...@@ -27,11 +26,14 @@ fi
if test "x$have_musicbrainz" = "xfalse"; then if test "x$have_musicbrainz" = "xfalse"; then
echo "**************************************************" echo "**************************************************"
echo "*" echo "*"
echo "* You do not seem to have libmusicbrainz and JuK" echo "* You do not seem to have libmusicbrainz and"
echo "* will be compiled without MusicBrainz support " echo "* libtunepimp. JuK will be compiled without"
echo "* Automatic song recogntion will not be supported. " echo "* will be compiled without MusicBrainz support and"
echo "* Please download libmusicbrainz 2.0.1 from " echo "* automatic song recogntion will not be supported."
echo "* Please download libmusicbrainz 2.x and libtunepimp"
echo "* 0.3.x from:"
echo "* http://www.musicbrainz.org/products/client/download.html " echo "* http://www.musicbrainz.org/products/client/download.html "
echo "* http://www.musicbrainz.org/products/tunepimp/download.html"
echo "*" echo "*"
echo "**************************************************" echo "**************************************************"
fi fi
...@@ -39,14 +39,11 @@ AC_DEFUN([AC_NO_MUSICBRAINZ], ...@@ -39,14 +39,11 @@ AC_DEFUN([AC_NO_MUSICBRAINZ],
have_musicbrainz=false have_musicbrainz=false
]) ])
KDE_CHECK_HEADER(musicbrainz/musicbrainz.h, KDE_CHECK_HEADER(tunepimp/tp_c.h,
AC_HAVE_MUSICBRAINZ, AC_HAVE_MUSICBRAINZ,
AC_NO_MUSICBRAINZ AC_NO_MUSICBRAINZ
) )
KDE_FIND_PATH(trm,TRM,[$kde_default_bindirs],[
AC_MSG_WARN([Could not find trm utility anywhere, check http://www.musicbrainz.org/products/trmgen/download.html for TRM Generator.])
])
if test -z "$TRM" ; then if test -z "$TRM" ; then
AC_DEFINE(HAVE_TRM,0,[Is trm program present]) AC_DEFINE(HAVE_TRM,0,[Is trm program present])
else else
......
/***************************************************************************
copyright : (C) 2004 by Scott Wheeler
email : wheeler@kde.org
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
* USA *
***************************************************************************/
#include "ktrm.h"
#if HAVE_MUSICBRAINZ
#include <kapplication.h>
#include <kprotocolmanager.h>
#include <kurl.h>
#include <kdebug.h>
#include <qmutex.h>
#include <qevent.h>
#include <qobject.h>
#include <qfile.h>
#include <tunepimp/tp_c.h>
class KTRMLookup;
extern "C"
{
static void TRMNotifyCallback(tunepimp_t pimp, void *data, TPCallbackEnum type, int fileId);
}
/**
* This represents the main TunePimp instance and handles incoming requests.
*/
class KTRMRequestHandler
{
typedef QMap<int, KTRMLookup *> LookupMap;
public:
static KTRMRequestHandler *instance()
{
static QMutex mutex;
mutex.lock();
static KTRMRequestHandler handler;
mutex.unlock();
return &handler;
}
int KTRMRequestHandler::startLookup(KTRMLookup *lookup)
{
int id = tp_AddFile(m_pimp, QFile::encodeName(lookup->file()));
m_lookupMap[id] = lookup;
return id;
}
void endLookup(KTRMLookup *lookup)
{
tp_ReleaseTrack(m_pimp, tp_GetTrack(m_pimp, lookup->fileId()));
tp_Remove(m_pimp, lookup->fileId());
m_lookupMap.remove(lookup->fileId());
}
bool lookupMapContains(int fileId) const
{
m_lookupMapMutex.lock();
bool contains = m_lookupMap.contains(fileId);
m_lookupMapMutex.unlock();
return contains;
}
KTRMLookup *lookup(int fileId) const
{
m_lookupMapMutex.lock();
KTRMLookup *l = m_lookupMap[fileId];
m_lookupMapMutex.unlock();
return l;
}
void removeFromLookupMap(int fileId)
{
m_lookupMapMutex.lock();
m_lookupMap.remove(fileId);
m_lookupMapMutex.unlock();
}
const tunepimp_t &tunePimp() const
{
return m_pimp;
}
protected:
KTRMRequestHandler()
{
m_pimp = tp_New("KTRM", "0.1");
tp_SetTRMCollisionThreshold(m_pimp, 100);
tp_SetAutoSaveThreshold(m_pimp, -1);
tp_SetMoveFiles(m_pimp, false);
tp_SetRenameFiles(m_pimp, false);
tp_SetUseUTF8(m_pimp, true);
tp_SetNotifyCallback(m_pimp, TRMNotifyCallback, 0);
if(KProtocolManager::useProxy()) {
KURL proxy = KProtocolManager::proxyFor("http");
tp_SetProxy(m_pimp, proxy.host().latin1(), short(proxy.port()));
}
}
~KTRMRequestHandler()
{
tp_Delete(m_pimp);
}
private:
tunepimp_t m_pimp;
LookupMap m_lookupMap;
mutable QMutex m_lookupMapMutex;
};
/**
* A custom event type used for signalling that a TRM lookup is finished.
*/
class KTRMEvent : public QCustomEvent
{
public:
enum Status {
Recognized,
Unrecognized,
Collision,
Error
};
KTRMEvent(int fileId, Status status) :
QCustomEvent(id),
m_fileId(fileId),
m_status(status) {}
int fileId() const
{
return m_fileId;
}
Status status() const
{
return m_status;
}
static const int id = User + 1984; // random, unique, event id
private:
int m_fileId;
Status m_status;
};
/**
* A helper class to intercept KTRMQueryEvents and call recognized() (from the GUI
* thread) for the lookup.
*/
class KTRMEventHandler : public QObject
{
public:
static void send(int fileId, KTRMEvent::Status status)
{
KApplication::postEvent(instance(), new KTRMEvent(fileId, status));
}
protected:
KTRMEventHandler() : QObject() {}
static KTRMEventHandler *instance()
{
static QMutex mutex;
mutex.lock();
static KTRMEventHandler handler;
mutex.unlock();
return &handler;
}
virtual void customEvent(QCustomEvent *event)
{
if(!event->type() == KTRMEvent::id)
return;
KTRMEvent *e = static_cast<KTRMEvent *>(event);
static QMutex mutex;
mutex.lock();
if(!KTRMRequestHandler::instance()->lookupMapContains(e->fileId())) {
mutex.unlock();
return;
}
KTRMLookup *lookup = KTRMRequestHandler::instance()->lookup(e->fileId());
KTRMRequestHandler::instance()->removeFromLookupMap(e->fileId());
mutex.unlock();
switch(e->status()) {
case KTRMEvent::Recognized:
lookup->recognized();
break;
case KTRMEvent::Unrecognized:
lookup->unrecognized();
break;
case KTRMEvent::Collision:
lookup->collision();
break;
case KTRMEvent::Error:
lookup->error();
break;
}
}
};
/**
* Callback fuction for TunePimp lookup events.
*/
static void TRMNotifyCallback(tunepimp_t pimp, void *, TPCallbackEnum type, int fileId)
{
if(type != tpFileChanged)
return;
track_t track = tp_GetTrack(pimp, fileId);
TPFileStatus status = tr_GetStatus(track);
switch(status) {
case eRecognized:
KTRMEventHandler::send(fileId, KTRMEvent::Recognized);
break;
case eUnrecognized:
KTRMEventHandler::send(fileId, KTRMEvent::Unrecognized);
break;
case eTRMCollision:
KTRMEventHandler::send(fileId, KTRMEvent::Collision);
break;
case eError:
KTRMEventHandler::send(fileId, KTRMEvent::Error);
break;
default:
break;
}
}
class KTRMLookup::KTRMLookupPrivate
{
public:
KTRMLookupPrivate() :
fileId(-1) {}
QString file;
KTRMResultList results;
int fileId;
bool autoDelete;
};
////////////////////////////////////////////////////////////////////////////////
// KTRMLookup public methods
////////////////////////////////////////////////////////////////////////////////
KTRMLookup::KTRMLookup(const QString &file, bool autoDelete)
{
d = new KTRMLookupPrivate;
d->file = file;
d->autoDelete = autoDelete;
d->fileId = KTRMRequestHandler::instance()->startLookup(this);
}
KTRMLookup::~KTRMLookup()
{
KTRMRequestHandler::instance()->endLookup(this);
delete d;
}
QString KTRMLookup::file() const
{
return d->file;
}
int KTRMLookup::fileId() const
{
return d->fileId;
}
void KTRMLookup::recognized()
{
kdDebug() << k_funcinfo << d->file << endl;
d->results.clear();
metadata_t *metaData = md_New();
track_t track = tp_GetTrack(KTRMRequestHandler::instance()->tunePimp(), d->fileId);
tr_GetServerMetadata(track, metaData);
KTRMResult result;
result.title = QString::fromUtf8(metaData->track);
result.artist = QString::fromUtf8(metaData->artist);
result.album = QString::fromUtf8(metaData->album);
result.track = metaData->trackNum;
result.year = metaData->releaseYear;
d->results.append(result);
md_Delete(metaData);
finished();
}
void KTRMLookup::unrecognized()
{
kdDebug() << k_funcinfo << d->file << endl;
d->results.clear();
finished();
}
void KTRMLookup::collision()
{
kdDebug() << k_funcinfo << d->file << endl;
track_t track = tp_GetTrack(KTRMRequestHandler::instance()->tunePimp(), d->fileId);
if(track <= 0) {
kdDebug() << "invalid track number" << endl;
return;
}
tr_Lock(track);
int resultCount = tr_GetNumResults(track);
kdDebug() << k_funcinfo << "resultCount == " << resultCount << endl;
if(resultCount <= 0) {
kdDebug() << "No results found." << endl;
}
else {
TPResultType type;
result_t *results = new result_t[resultCount];
tr_GetResults(track, &type, results, &resultCount);
switch(type) {
case eNone:
kdDebug() << k_funcinfo << "eNone" << endl;
break;
case eArtistList:
kdDebug() << "eArtistList" << endl;
break;
case eAlbumList:
kdDebug() << "eAlbumList" << endl;
break;
case eTrackList:
{
kdDebug() << "eTrackList" << endl;
albumtrackresult_t **tracks = (albumtrackresult_t **) results;
d->results.clear();
for(int i = 0; i < resultCount; i++) {
KTRMResult result;
result.title = QString::fromUtf8(tracks[i]->name);
result.artist = QString::fromUtf8(tracks[i]->artist->name);
result.album = QString::fromUtf8(tracks[i]->album->name);
result.track = tracks[i]->trackNum;
result.year = tracks[i]->album->releaseYear;
result.relevance = tracks[i]->relevance;
d->results.append(result);
}
break;
}
case eMatchedTrack:
kdDebug() << k_funcinfo << "eMatchedTrack" << endl;
break;
}
delete [] results;
}
tr_Unlock(track);
finished();
}
void KTRMLookup::error()
{
kdDebug() << k_funcinfo << d->file << endl;
d->results.clear();
finished();
}
KTRMResultList KTRMLookup::results() const
{
return d->results;
}
////////////////////////////////////////////////////////////////////////////////
// KTRMLookup protected methods
////////////////////////////////////////////////////////////////////////////////
void KTRMLookup::finished()
{
if(d->autoDelete)
delete this;
}
#endif
/***************************************************************************
copyright : (C) 2004 by Scott Wheeler
email : wheeler@kde.org
***************************************************************************/
/***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
* USA *
***************************************************************************/
/*
* At some point this will likely be a library class, as such it's been written
* as such and is LGPL'ed.
*/
#ifndef KTRM_H
#define KTRM_H
#include <config.h>
#if HAVE_MUSICBRAINZ
#include <qstring.h>
#include <qvaluelist.h>
#include <qmap.h>
/**
* This struct represents the results of a TRM lookup and MusicBrainz
* identification.
*/
struct KTRMResult
{
KTRMResult() : track(0), year(0), relevance(0) {}
QString title;
QString artist;
QString album;
int track;
int year;
int relevance;
bool operator<(const KTRMResult &r) const
{
return r.relevance < relevance;
}
bool isEmpty()
{
return title.isEmpty() && artist.isEmpty() && album.isEmpty() &&
track == 0 && year == 0;
}
};
typedef QValueList<KTRMResult> KTRMResultList;
class KTRMLookup
{
public:
KTRMLookup(const QString &file, bool autoDelete = false);
virtual ~KTRMLookup();
QString file() const;
int fileId() const;
/**
* This method is called if the track was recognized by the TRM server.
* results() will return just one value. This may be reimplemented to
* provide specific behavion in the case of the track being recognized.
*/
virtual void recognized();
/**
* This method is called if the track was not recognized by the TRM server.
* results() will return an empty set. This may be reimplemented to provide
* specific behavion in the case of the track not being recognized.
*/
virtual void unrecognized();
/**
* This method is called if there are multiple potential matches for the TRM
* value. results() will return a list of the potential matches, sorted by
* liklihood. This may be reimplemented to provide
* specific behavion in the case of the track not being recognized.
*/
virtual void collision();
/**
* This method is called if the track was not recognized by the TRM server.
* results() will return an empty set. This may be reimplemented to provide
* specific behavion in the case of the track not being recognized.
*/
virtual void error();
/**
* Returns the list of matches found by the lookup. In the case that there<