Permalink
Browse files

d-pointer for Fingerprint class

  • Loading branch information...
jstamp committed May 21, 2012
1 parent f8af092 commit 6957507c376c20b6fb75f28372e62f974a325a39
Showing with 91 additions and 50 deletions.
  1. +81 −18 src/fingerprint/Fingerprint.cpp
  2. +10 −32 src/fingerprint/Fingerprint.h
@@ -24,6 +24,7 @@
#include "Sha256.h"
#include "fplib/FingerprintExtractor.h"
#include "ws.h"
+#include <QDebug>
#include <QFileInfo>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
@@ -36,21 +37,56 @@ using lastfm::Track;
static const uint k_bufferSize = 1024 * 8;
static const int k_minTrackDuration = 30;
+class lastfm::FingerprintPrivate
+{
+ public:
+ FingerprintPrivate( const Track& t )
+ : m_track( t )
+ , m_id( -1 )
+ , m_duration( 0 )
+ , m_complete( false )
+ {
+ }
+ lastfm::Track m_track;
+ QByteArray m_data;
+ int m_id;
+ int m_duration;
+ bool m_complete;
+};
+
lastfm::Fingerprint::Fingerprint( const Track& t )
- : m_track( t )
- , m_id( -1 ), m_duration( 0 )
- , m_complete( false )
+ : d( new FingerprintPrivate( t ) )
{
QString id = Collection::instance().getFingerprintId( t.url().toLocalFile() );
if (id.size()) {
bool b;
- m_id = id.toInt( &b );
- if (!b) m_id = -1;
+ d->m_id = id.toInt( &b );
+ if (!b) d->m_id = -1;
}
}
+lastfm::Fingerprint::~Fingerprint()
+{
+ delete d;
+}
+
+
+lastfm::FingerprintId
+lastfm::Fingerprint::id() const
+{
+ return d->m_id;
+}
+
+
+QByteArray
+lastfm::Fingerprint::data() const
+{
+ return d->m_data;
+}
+
+
void
lastfm::Fingerprint::generate( FingerprintableSource* ms ) throw( Error )
{
@@ -66,8 +102,8 @@ lastfm::Fingerprint::generate( FingerprintableSource* ms ) throw( Error )
try
{
- ms->init( m_track.url().toLocalFile() );
- ms->getInfo( m_duration, sampleRate, bitrate, numChannels );
+ ms->init( d->m_track.url().toLocalFile() );
+ ms->getInfo( d->m_duration, sampleRate, bitrate, numChannels );
}
catch (std::exception& e)
{
@@ -76,7 +112,7 @@ lastfm::Fingerprint::generate( FingerprintableSource* ms ) throw( Error )
}
- if (m_duration < k_minTrackDuration)
+ if (d->m_duration < k_minTrackDuration)
throw TrackTooShortError;
ms->skipSilence();
@@ -87,13 +123,13 @@ lastfm::Fingerprint::generate( FingerprintableSource* ms ) throw( Error )
{
extractor = new fingerprint::FingerprintExtractor;
- if (m_complete)
+ if (d->m_complete)
{
extractor->initForFullSubmit( sampleRate, numChannels );
}
else
{
- extractor->initForQuery( sampleRate, numChannels, m_duration );
+ extractor->initForQuery( sampleRate, numChannels, d->m_duration );
// Skippety skip for as long as the skipper sez (optimisation)
ms->skip( extractor->getToSkipMs() );
@@ -143,7 +179,7 @@ lastfm::Fingerprint::generate( FingerprintableSource* ms ) throw( Error )
throw InternalError;
// Make a deep copy before extractor gets deleted
- m_data = QByteArray( fpData.first, fpData.second );
+ d->m_data = QByteArray( fpData.first, fpData.second );
delete extractor;
}
@@ -206,15 +242,15 @@ static QByteArray number( uint n )
QNetworkReply*
lastfm::Fingerprint::submit() const
{
- if (m_data.isEmpty())
+ if (d->m_data.isEmpty())
return 0;
//Parameters understood by the server according to the MIR team:
//{ "trackid", "recordingid", "artist", "album", "track", "duration",
// "tracknum", "username", "sha256", "ip", "fpversion", "mbid",
// "filename", "genre", "year", "samplerate", "noupdate", "fulldump" }
- Track const t = m_track;
+ Track const t = d->m_track;
QString const path = t.url().toLocalFile();
QFileInfo const fi( path );
@@ -223,15 +259,15 @@ lastfm::Fingerprint::submit() const
url.addEncodedQueryItem( "artist", e(t.artist()) );
url.addEncodedQueryItem( "album", e(t.album()) );
url.addEncodedQueryItem( "track", e(t.title()) );
- url.addEncodedQueryItem( "duration", number( m_duration > 0 ? m_duration : t.duration() ) );
+ url.addEncodedQueryItem( "duration", number( d->m_duration > 0 ? d->m_duration : t.duration() ) );
url.addEncodedQueryItem( "mbid", e(t.mbid()) );
url.addEncodedQueryItem( "filename", e(fi.completeBaseName()) );
url.addEncodedQueryItem( "fileextension", e(fi.completeSuffix()) );
url.addEncodedQueryItem( "tracknum", number( t.trackNumber() ) );
url.addEncodedQueryItem( "sha256", sha256( path ).toAscii() );
url.addEncodedQueryItem( "time", number(QDateTime::currentDateTime().toTime_t()) );
url.addEncodedQueryItem( "fpversion", QByteArray::number((int)fingerprint::FingerprintExtractor::getVersion()) );
- url.addEncodedQueryItem( "fulldump", m_complete ? "true" : "false" );
+ url.addEncodedQueryItem( "fulldump", d->m_complete ? "true" : "false" );
url.addEncodedQueryItem( "noupdate", "false" );
#undef e
@@ -245,7 +281,7 @@ lastfm::Fingerprint::submit() const
bytes += "Content-Disposition: ";
bytes += "form-data; name=\"fpdata\"";
bytes += "\r\n\r\n";
- bytes += m_data;
+ bytes += d->m_data;
bytes += "\r\n";
bytes += "------------------------------8e61d618ca16--\r\n";
@@ -285,16 +321,43 @@ lastfm::Fingerprint::decode( QNetworkReply* reply, bool* complete_fingerprint_re
uint fpid_as_uint = fpid.toUInt( &b );
if (!b) goto bad_response;
- Collection::instance().setFingerprintId( m_track.url().toLocalFile(), fpid );
+ Collection::instance().setFingerprintId( d->m_track.url().toLocalFile(), fpid );
if (complete_fingerprint_requested)
*complete_fingerprint_requested = (status == "NEW");
- m_id = (int)fpid_as_uint;
+ d->m_id = (int)fpid_as_uint;
return;
}
bad_response:
qWarning() << "Response is bad:" << response;
throw BadResponseError;
}
+
+
+lastfm::CompleteFingerprint::CompleteFingerprint( const lastfm::Track& t ) : Fingerprint( t )
+{
+ d->m_complete = true;
+}
+
+
+lastfm::CompleteFingerprint::~CompleteFingerprint()
+{
+}
+
+
+QDebug operator<<( QDebug d, lastfm::Fingerprint::Error e )
+{
+ #define CASE(x) case lastfm::Fingerprint::x: return d << #x;
+ switch (e)
+ {
+ CASE(ReadError)
+ CASE(HeadersError)
+ CASE(DecodeError)
+ CASE(TrackTooShortError)
+ CASE(BadResponseError)
+ CASE(InternalError)
+ }
+ #undef CASE
+}
@@ -20,38 +20,32 @@
#ifndef LASTFM_FINGERPRINT_H
#define LASTFM_FINGERPRINT_H
-#include "global.h"
-#include "Track.h"
#include "FingerprintId.h"
-#include "FingerprintableSource.h"
-
-#include <QDebug>
namespace lastfm
{
+ class FingerprintableSource;
+ class Track;
+
class LASTFM_FINGERPRINT_DLLEXPORT Fingerprint
{
- lastfm::Track m_track;
- QByteArray m_data;
- int m_id;
- int m_duration;
-
protected:
- bool m_complete;
+ class FingerprintPrivate * const d;
public:
/** represents a partial fingerprint of 20 seconds of music, this is
* considered 99.9999...9999% unique and so we use it for most stuff as
* it is much quicker than a complete fingerprint, still though, you
* should do the generate step in a thread. */
Fingerprint( const lastfm::Track& );
+ ~Fingerprint();
/** if the id isNull(), then you'll need to do generate, submit and decode */
- FingerprintId id() const { return m_id; }
+ FingerprintId id() const;
/** The actual data that is the fingerprint, this is about 70kB or so,
* there isn't anything in it until you call generate. */
- QByteArray data() const { return m_data; }
+ QByteArray data() const;
enum Error
{
@@ -92,28 +86,12 @@ namespace lastfm
class CompleteFingerprint : public Fingerprint
{
- public:
- CompleteFingerprint( const lastfm::Track& t ) : Fingerprint( t )
- {
- m_complete = true;
- }
+ CompleteFingerprint( const lastfm::Track& t );
+ ~CompleteFingerprint();
};
}
-inline QDebug operator<<( QDebug d, lastfm::Fingerprint::Error e )
-{
- #define CASE(x) case lastfm::Fingerprint::x: return d << #x;
- switch (e)
- {
- CASE(ReadError)
- CASE(HeadersError)
- CASE(DecodeError)
- CASE(TrackTooShortError)
- CASE(BadResponseError)
- CASE(InternalError)
- }
- #undef CASE
-}
+QDebug operator<<( QDebug d, lastfm::Fingerprint::Error e );
#endif

0 comments on commit 6957507

Please sign in to comment.