summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/depends.py1
-rw-r--r--plugins/soundsourcem4a/SConscript3
-rw-r--r--plugins/soundsourcem4a/m4a/mp4-mixxx.cpp4
-rw-r--r--plugins/soundsourcem4a/soundsourcem4a.cpp57
-rw-r--r--plugins/soundsourcemediafoundation/SConscript2
-rw-r--r--plugins/soundsourcemediafoundation/soundsourcemediafoundation.cpp53
-rw-r--r--plugins/soundsourcemediafoundation/soundsourcemediafoundation.h1
-rw-r--r--plugins/soundsourcewv/SConscript3
-rw-r--r--plugins/soundsourcewv/soundsourcewv.cpp70
-rw-r--r--plugins/soundsourcewv/soundsourcewv.h2
-rw-r--r--src/soundsource.cpp630
-rw-r--r--src/soundsource.h218
-rw-r--r--src/soundsourcecoreaudio.cpp104
-rw-r--r--src/soundsourceffmpeg.cpp62
-rw-r--r--src/soundsourceffmpeg.h7
-rw-r--r--src/soundsourceflac.cpp83
-rw-r--r--src/soundsourceflac.h2
-rw-r--r--src/soundsourcemodplug.cpp10
-rw-r--r--src/soundsourcemp3.cpp85
-rw-r--r--src/soundsourcemp3.h8
-rw-r--r--src/soundsourceoggvorbis.cpp48
-rw-r--r--src/soundsourceopus.cpp77
-rw-r--r--src/soundsourceopus.h3
-rw-r--r--src/soundsourcesndfile.cpp93
-rw-r--r--src/soundsourcetaglib.cpp408
-rw-r--r--src/soundsourcetaglib.h45
26 files changed, 1091 insertions, 988 deletions
diff --git a/build/depends.py b/build/depends.py
index c5129e6ea2..d038d26b92 100644
--- a/build/depends.py
+++ b/build/depends.py
@@ -659,6 +659,7 @@ class MixxxCore(Feature):
"upgrade.cpp",
"soundsource.cpp",
+ "soundsourcetaglib.cpp",
"sharedglcontext.cpp",
"widget/controlwidgetconnection.cpp",
diff --git a/plugins/soundsourcem4a/SConscript b/plugins/soundsourcem4a/SConscript
index 1f3672142e..96df047098 100644
--- a/plugins/soundsourcem4a/SConscript
+++ b/plugins/soundsourcem4a/SConscript
@@ -11,8 +11,9 @@ Import('build')
# On Posix default SCons.LIBPREFIX = 'lib', on Windows default SCons.LIBPREFIX = ''
m4a_sources = [
- "soundsource.cpp", # required to subclass soundsource
"soundsourcem4a.cpp", # MP4/M4A Support through FAAD/libmp4v2
+ "soundsourcetaglib.cpp", # TagLib dependencies
+ "soundsource.cpp", # required to subclass SoundSource
"sampleutil.cpp", # utility functions
]
diff --git a/plugins/soundsourcem4a/m4a/mp4-mixxx.cpp b/plugins/soundsourcem4a/m4a/mp4-mixxx.cpp
index 4d226947ca..d6503f7239 100644
--- a/plugins/soundsourcem4a/m4a/mp4-mixxx.cpp
+++ b/plugins/soundsourcem4a/m4a/mp4-mixxx.cpp
@@ -124,6 +124,10 @@ static MP4TrackId mp4_get_track(MP4FileHandle *handle)
return MP4_INVALID_TRACK_ID;
}
+static void mp4_init(struct input_plugin_data *ip_data) {
+ memset(ip_data, 0, sizeof(*ip_data));
+}
+
static int mp4_open(struct input_plugin_data *ip_data)
{
struct mp4_private *priv;
diff --git a/plugins/soundsourcem4a/soundsourcem4a.cpp b/plugins/soundsourcem4a/soundsourcem4a.cpp
index 963a4156c9..c8399d7555 100644
--- a/plugins/soundsourcem4a/soundsourcem4a.cpp
+++ b/plugins/soundsourcem4a/soundsourcem4a.cpp
@@ -15,6 +15,7 @@
***************************************************************************/
#include "soundsourcem4a.h"
+#include "soundsourcetaglib.h"
#include "sampleutil.h"
#include <taglib/mp4file.h>
@@ -41,7 +42,8 @@ SoundSourceM4A::SoundSourceM4A(QString qFileName)
// Initialize variables to invalid values in case loading fails.
mp4file = MP4_INVALID_FILE_HANDLE;
filelength = 0;
- memset(&ipd, 0, sizeof(ipd));
+ setType("m4a");
+ mp4_init(&ipd);
}
SoundSourceM4A::~SoundSourceM4A() {
@@ -61,7 +63,7 @@ Result SoundSourceM4A::open()
//Initialize the FAAD2 decoder...
initializeDecoder();
- //qDebug() << "SSM4A: channels:" << m_iChannels
+ //qDebug() << "SSM4A: channels:" << getChannels()
// << "filelength:" << filelength
// << "Sample Rate:" << m_iSampleRate;
return OK;
@@ -70,8 +72,7 @@ Result SoundSourceM4A::open()
int SoundSourceM4A::initializeDecoder()
{
// Copy QString to char[] buffer for mp4_open to read from later
- QByteArray qbaFileName;
- qbaFileName = m_qFilename.toLocal8Bit();
+ const QByteArray qbaFileName(getFilename().toLocal8Bit());
int bytes = qbaFileName.length() + 1;
ipd.filename = new char[bytes];
strncpy(ipd.filename, qbaFileName.constData(), bytes);
@@ -84,7 +85,7 @@ int SoundSourceM4A::initializeDecoder()
int mp4_open_status = mp4_open(&ipd);
if (mp4_open_status != 0) {
qWarning() << "SSM4A::initializeDecoder failed"
- << m_qFilename << " with status:" << mp4_open_status;
+ << getFilename() << " with status:" << mp4_open_status;
return ERR;
}
@@ -93,8 +94,8 @@ int SoundSourceM4A::initializeDecoder()
Q_ASSERT(mp);
mp4file = mp->mp4.handle;
filelength = mp4_total_samples(&ipd);
- m_iSampleRate = mp->sample_rate;
- m_iChannels = mp->channels;
+ setSampleRate(mp->sample_rate);
+ setChannels(mp->channels);
return OK;
}
@@ -106,10 +107,10 @@ long SoundSourceM4A::seek(long filepos){
//qDebug() << "SSM4A::seek()" << filepos;
- // qDebug() << "MP4SEEK: seek time:" << filepos / (m_iChannels * m_iSampleRate) ;
+ // qDebug() << "MP4SEEK: seek time:" << filepos / (getChannels() * m_iSampleRate) ;
int position = mp4_seek_sample(&ipd, filepos);
- //int position = mp4_seek(&ipd, filepos / (m_iChannels * m_iSampleRate));
+ //int position = mp4_seek(&ipd, filepos / (getChannels() * m_iSampleRate));
return position;
}
@@ -125,7 +126,7 @@ unsigned SoundSourceM4A::read(volatile unsigned long size, const SAMPLE* destina
// sample is 16-bits = 2 bytes here, so we multiply size by channels to
// get the number of bytes we want to decode.
- int total_bytes_to_decode = size * m_iChannels;
+ int total_bytes_to_decode = size * getChannels();
int total_bytes_decoded = 0;
int num_bytes_req = 4096;
char* buffer = (char*)destination;
@@ -148,7 +149,7 @@ unsigned SoundSourceM4A::read(volatile unsigned long size, const SAMPLE* destina
// At this point *destination should be filled. If mono : double all samples
// (L => R)
- if (m_iChannels == 1) {
+ if (getChannels() == 1) {
SampleUtil::doubleMonoToDualMono(as_buffer, total_bytes_decoded / 2);
}
@@ -168,30 +169,40 @@ unsigned SoundSourceM4A::read(volatile unsigned long size, const SAMPLE* destina
inline long unsigned SoundSourceM4A::length(){
return filelength;
- //return m_iChannels * mp4_duration(&ipd) * m_iSampleRate;
+ //return getChannels() * mp4_duration(&ipd) * m_iSampleRate;
}
Result SoundSourceM4A::parseHeader(){
- setType("m4a");
-
TagLib::MP4::File f(getFilename().toLocal8Bit().constData());
- bool result = processTaglibFile(f);
- TagLib::MP4::Tag* tag = f.tag();
+ if (!readFileHeader(this, f)) {
+ return ERR;
+ }
- if (tag) {
- processMP4Tag(tag);
+ TagLib::MP4::Tag *mp4(f.tag());
+ if (mp4) {
+ readMP4Tag(this, *mp4);
+ } else {
+ // fallback
+ const TagLib::Tag *tag(f.tag());
+ if (tag) {
+ readTag(this, *tag);
+ } else {
+ return ERR;
+ }
}
- if (result)
- return OK;
- return ERR;
+ return OK;
}
QImage SoundSourceM4A::parseCoverArt() {
- setType("m4a");
TagLib::MP4::File f(getFilename().toLocal8Bit().constData());
- return getCoverInMP4Tag(f.tag());
+ TagLib::MP4::Tag *mp4(f.tag());
+ if (mp4) {
+ return getCoverInMP4Tag(*mp4);
+ } else {
+ return QImage();
+ }
}
QList<QString> SoundSourceM4A::supportedFileExtensions()
diff --git a/plugins/soundsourcemediafoundation/SConscript b/plugins/soundsourcemediafoundation/SConscript
index a0284db8cd..0fc749c542 100644
--- a/plugins/soundsourcemediafoundation/SConscript
+++ b/plugins/soundsourcemediafoundation/SConscript
@@ -18,7 +18,7 @@ if int(build.flags['mediafoundation']):
else:
env["LINKFLAGS"].remove("/subsystem:windows,5.01")
ssmediafoundation_bin = env.SharedLibrary('soundsourcemediafoundation',
- ['soundsource.cpp', 'soundsourcemediafoundation.cpp'],
+ ['soundsource.cpp', 'soundsourcetaglib.cpp', 'soundsourcemediafoundation.cpp'],
LINKCOM = [env['LINKCOM'],
'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;1'])
Return("ssmediafoundation_bin")
diff --git a/plugins/soundsourcemediafoundation/soundsourcemediafoundation.cpp b/plugins/soundsourcemediafoundation/soundsourcemediafoundation.cpp
index e3c4aac68e..2016ca406e 100644
--- a/plugins/soundsourcemediafoundation/soundsourcemediafoundation.cpp
+++ b/plugins/soundsourcemediafoundation/soundsourcemediafoundation.cpp
@@ -30,6 +30,7 @@
#include <propvarutil.h>
#include "soundsourcemediafoundation.h"
+#include "soundsourcetaglib.h"
const int kBitsPerSample = 16;
const int kNumChannels = 2;
@@ -50,7 +51,6 @@ template<class T> static void safeRelease(T **ppT)
SoundSourceMediaFoundation::SoundSourceMediaFoundation(QString filename)
: SoundSource(filename)
- , m_file(filename)
, m_pReader(NULL)
, m_pAudioType(NULL)
, m_wcFilename(NULL)
@@ -66,8 +66,9 @@ SoundSourceMediaFoundation::SoundSourceMediaFoundation(QString filename)
{
// these are always the same, might as well just stick them here
// -bkgood
- m_iChannels = kNumChannels;
- m_iSampleRate = kSampleRate;
+ setType("m4a");
+ setChannels(kNumChannels);
+ setSampleRate(kSampleRate);
// http://social.msdn.microsoft.com/Forums/en/netfxbcl/thread/35c6a451-3507-40c8-9d1c-8d4edde7c0cc
// gives maximum path + file length as 248 + 260, using that -bkgood
@@ -88,11 +89,11 @@ SoundSourceMediaFoundation::~SoundSourceMediaFoundation()
Result SoundSourceMediaFoundation::open()
{
if (sDebug) {
- qDebug() << "open()" << m_qFilename;
+ qDebug() << "open()" << getFilename();
}
- QString qurlStr(m_qFilename);
- int wcFilenameLength(m_qFilename.toWCharArray(m_wcFilename));
+ QString qurlStr(getFilename());
+ int wcFilenameLength(getFilename().toWCharArray(m_wcFilename));
// toWCharArray does not append a null terminator to the string!
m_wcFilename[wcFilenameLength] = '\0';
@@ -114,7 +115,7 @@ Result SoundSourceMediaFoundation::open()
// Create the source reader to read the input file.
hr = MFCreateSourceReaderFromURL(m_wcFilename, NULL, &m_pReader);
if (FAILED(hr)) {
- qWarning() << "SSMF: Error opening input file:" << m_qFilename;
+ qWarning() << "SSMF: Error opening input file:" << getFilename();
return ERR;
}
@@ -375,26 +376,38 @@ inline unsigned long SoundSourceMediaFoundation::length()
Result SoundSourceMediaFoundation::parseHeader()
{
- setType("m4a");
-
// Must be toLocal8Bit since Windows fopen does not do UTF-8
TagLib::MP4::File f(getFilename().toLocal8Bit().constData());
- bool result = processTaglibFile(f);
- TagLib::MP4::Tag* tag = f.tag();
- if (tag) {
- processMP4Tag(tag);
+ if (!readFileHeader(this, f)) {
+ return ERR;
}
- if (result)
- return OK;
- return ERR;
+ TagLib::MP4::Tag *mp4(f.tag());
+ if (mp4) {
+ readMP4Tag(this, *mp4);
+ } else {
+ // fallback
+ const TagLib::Tag *tag(f.tag());
+ if (tag) {
+ readTag(this, *tag);
+ } else {
+ return ERR;
+ }
+ }
+
+ return OK;
}
QImage SoundSourceMediaFoundation::parseCoverArt() {
setType("m4a");
TagLib::MP4::File f(getFilename().toLocal8Bit().constData());
- return getCoverInMP4Tag(f.tag());
+ TagLib::MP4::Tag *mp4(f.tag());
+ if (mp4) {
+ return Mixxx::getCoverInMP4Tag(*mp4);
+ } else {
+ return QImage();
+ }
}
// static
@@ -567,15 +580,15 @@ bool SoundSourceMediaFoundation::readProperties()
// QuadPart isn't available on compilers that don't support _int64. Visual
// Studio 6.0 introduced the type in 1998, so I think we're safe here
// -bkgood
- m_iDuration = secondsFromMF(prop.hVal.QuadPart);
+ setDuration(secondsFromMF(prop.hVal.QuadPart));
m_mfDuration = prop.hVal.QuadPart;
- qDebug() << "SSMF: Duration:" << m_iDuration;
+ qDebug() << "SSMF: Duration:" << getDuration();
PropVariantClear(&prop);
// presentation attribute MF_PD_AUDIO_ENCODING_BITRATE only exists for
// presentation descriptors, one of which MFSourceReader is not.
// Therefore, we calculate it ourselves.
- m_iBitrate = kBitsPerSample * kSampleRate * kNumChannels;
+ setBitrate(kBitsPerSample * kSampleRate * kNumChannels);
return true;
}
diff --git a/plugins/soundsourcemediafoundation/soundsourcemediafoundation.h b/plugins/soundsourcemediafoundation/soundsourcemediafoundation.h
index 9599d1e1c1..96794568f7 100644
--- a/plugins/soundsourcemediafoundation/soundsourcemediafoundation.h
+++ b/plugins/soundsourcemediafoundation/soundsourcemediafoundation.h
@@ -58,7 +58,6 @@ class SoundSourceMediaFoundation : public Mixxx::SoundSource {
static inline qint64 mfFromSeconds(qreal sec);
static inline qint64 frameFromMF(qint64 mf);
static inline qint64 mfFromFrame(qint64 frame);
- QFile m_file;
IMFSourceReader *m_pReader;
IMFMediaType *m_pAudioType;
wchar_t *m_wcFilename;
diff --git a/plugins/soundsourcewv/SConscript b/plugins/soundsourcewv/SConscript
index 33843b80fc..984e3bddc5 100644
--- a/plugins/soundsourcewv/SConscript
+++ b/plugins/soundsourcewv/SConscript
@@ -11,8 +11,9 @@ Import('build')
# On Posix default SCons.LIBPREFIX = 'lib', on Windows default SCons.LIBPREFIX = ''
wv_sources = [
- "soundsource.cpp", # required to subclass soundsource
"soundsourcewv.cpp", # Wavpack support
+ "soundsourcetaglib.cpp", # TagLib dependencies
+ "soundsource.cpp", # required to subclass SoundSource
"sampleutil.cpp", # utility functions
]
diff --git a/plugins/soundsourcewv/soundsourcewv.cpp b/plugins/soundsourcewv/soundsourcewv.cpp
index 87ba22b64b..301e8ee088 100644
--- a/plugins/soundsourcewv/soundsourcewv.cpp
+++ b/plugins/soundsourcewv/soundsourcewv.cpp
@@ -5,17 +5,19 @@
#include <QtDebug>
-#include <taglib/wavpackfile.h>
-
#include "soundsourcewv.h"
+#include "soundsourcetaglib.h"
#include "sampleutil.h"
+#include <taglib/wavpackfile.h>
namespace Mixxx {
-SoundSourceWV::SoundSourceWV(QString qFilename) : SoundSource(qFilename)
-{
- // Initialize variables to invalid values in case loading fails.
- filewvc=NULL;
+SoundSourceWV::SoundSourceWV(QString qFilename)
+ : SoundSource(qFilename),
+ filewvc(NULL),
+ Bps(0),
+ filelength(0) {
+ setType("wv");
}
@@ -36,12 +38,12 @@ QList<QString> SoundSourceWV::supportedFileExtensions()
Result SoundSourceWV::open()
{
- QByteArray qBAFilename = m_qFilename.toLocal8Bit();
- char msg[80]; //hold posible error message
+ QByteArray qBAFilename(getFilename().toLocal8Bit());
+ char msg[80]; //hold possible error message
- filewvc = WavpackOpenFileInput(qBAFilename.constData(), msg,OPEN_2CH_MAX | OPEN_WVC,0);
+ filewvc = WavpackOpenFileInput(qBAFilename.constData(), msg, OPEN_2CH_MAX | OPEN_WVC,0);
if (!filewvc) {
- qDebug() << "SSWV::open: failed to open file : "<<msg;
+ qDebug() << "SSWV::open: failed to open file : "<< msg;
return ERR;
}
if (WavpackGetMode(filewvc) & MODE_FLOAT) {
@@ -52,11 +54,11 @@ Result SoundSourceWV::open()
}
// wavpack_open succeeded -> populate variables
filelength = WavpackGetNumSamples(filewvc);
- m_iSampleRate=WavpackGetSampleRate(filewvc);
- m_iChannels=WavpackGetReducedChannels(filewvc);
+ setSampleRate(WavpackGetSampleRate(filewvc));
+ setChannels(WavpackGetReducedChannels(filewvc));
Bps=WavpackGetBytesPerSample(filewvc);
- qDebug () << "SSWV::open: opened filewvc with filelength: "<<filelength<<" SampleRate: " << m_iSampleRate
- << " channels: " << m_iChannels << " bytes per samp: "<<Bps;
+ qDebug () << "SSWV::open: opened filewvc with filelength: "<<filelength<<" SampleRate: " << getSampleRate()
+ << " channels: " << getChannels() << " bytes per samp: "<<Bps;
if (Bps>2) {
qDebug() << "SSWV::open: warning: input file has > 2 bytes per sample, will be truncated to 16bits";
}
@@ -82,15 +84,15 @@ unsigned SoundSourceWV::read(volatile unsigned long size, const SAMPLE* destinat
//tempbuffer is fixed size : WV_BUF_LENGTH of uint32
while (sampsread != size) {
timesamps=(size-sampsread)>>1; //timesamps still remaining
- if (timesamps > (WV_BUF_LENGTH/m_iChannels)) { //if requested size requires more than one buffer filling
- timesamps=(WV_BUF_LENGTH/m_iChannels); //tempbuffer must hold (timesamps * channels) samples
+ if (timesamps > (WV_BUF_LENGTH / getChannels())) { //if requested size requires more than one buffer filling
+ timesamps=(WV_BUF_LENGTH / getChannels()); //tempbuffer must hold (timesamps * channels) samples
qDebug() << "SSWV::read : performance warning, size requested > buffer size !";
}
tsdone=WavpackUnpackSamples(filewvc, tempbuffer, timesamps); //fill temp buffer with timesamps*4bytes*channels
//data is right justified, format_samples() fixes that.
- SoundSourceWV::format_samples(Bps, (char *) (dest + (sampsread>>1)*m_iChannels), tempbuffer, tsdone*m_iChannels);
+ SoundSourceWV::format_samples(Bps, (char *) (dest + (sampsread>>1) * getChannels()), tempbuffer, tsdone*getChannels());
//this will unpack the 4byte/sample
//output of wUnpackSamples(), sign-extending or truncating to output 16bit / sample.
//specifying dest+sampsread should resume the conversion where it was left if size requested
@@ -104,7 +106,7 @@ unsigned SoundSourceWV::read(volatile unsigned long size, const SAMPLE* destinat
}
- if (m_iChannels==1) { //if MONO : expand array to double it's size; see ssov.cpp
+ if (getChannels() == 1) { //if MONO : expand array to double it's size; see ssov.cpp
SampleUtil::doubleMonoToDualMono(dest, sampsread / 2);
}
@@ -119,29 +121,37 @@ inline long unsigned SoundSourceWV::length(){
Result SoundSourceWV::parseHeader() {
- setType("wv");
-
- QByteArray qBAFilename = m_qFilename.toLocal8Bit();
+ const QByteArray qBAFilename(getFilename().toLocal8Bit());
TagLib::WavPack::File f(qBAFilename.constData());
- // Takes care of all the default metadata
- bool result = processTaglibFile(f);
+ if (!readFileHeader(this, f)) {
+ return ERR;
+ }
TagLib::APE::Tag *ape = f.APETag();
if (ape) {
- processAPETag(ape);
+ readAPETag(this, *ape);
+ } else {
+ // fallback
+ const TagLib::Tag *tag(f.tag());
+ if (tag) {
+ readTag(this, *tag);
+ } else {
+ return ERR;
+ }
}
- if (result)
- return OK;
- return ERR;
+ return OK;
}
QImage SoundSourceWV::parseCoverArt() {
- setType("wv");
- TagLib::WavPack::File f(m_qFilename.toLocal8Bit().constData());
+ TagLib::WavPack::File f(getFilename().toLocal8Bit().constData());
TagLib::APE::Tag *ape = f.APETag();
- return getCoverInAPETag(ape);
+ if (ape) {
+ return Mixxx::getCoverInAPETag(*ape);
+ } else {
+ return QImage();
+ }
}
void SoundSourceWV::format_samples(int Bps, char *dst, int32_t *src, uint32_t count)
diff --git a/plugins/soundsourcewv/soundsourcewv.h b/plugins/soundsourcewv/soundsourcewv.h
index a0a84af72c..a013e42a01 100644
--- a/plugins/soundsourcewv/soundsourcewv.h
+++ b/plugins/soundsourcewv/soundsourcewv.h
@@ -35,9 +35,9 @@ class SoundSourceWV : public SoundSource {
QImage parseCoverArt();
static QList<QString> supportedFileExtensions();
private:
+ WavpackContext * filewvc; //works as a file handle to access the wv file.
int Bps;
unsigned long filelength;
- WavpackContext * filewvc; //works as a file handle to access the wv file.
int32_t tempbuffer[WV_BUF_LENGTH]; //hax ! legacy from cmus. this is 64k*4bytes.
void format_samples(int, char *, int32_t *, uint32_t);
};
diff --git a/src/soundsource.cpp b/src/soundsource.cpp
index 19741158f3..2a2a787b67 100644
--- a/src/soundsource.cpp
+++ b/src/soundsource.cpp
@@ -17,18 +17,6 @@
#include <QtDebug>
-#include <taglib/attachedpictureframe.h>
-#include <taglib/audioproperties.h>
-#include <taglib/flacpicture.h>
-#include <taglib/id3v1tag.h>
-#include <taglib/id3v2frame.h>
-#include <taglib/id3v2header.h>
-#include <taglib/tag.h>
-#include <taglib/textidentificationframe.h>
-#include <taglib/tmap.h>
-#include <taglib/tstringlist.h>
-#include <taglib/vorbisfile.h>
-#include <taglib/wavpackfile.h>
#include "soundsource.h"
#include "util/math.h"
@@ -36,607 +24,61 @@
namespace Mixxx
{
-// static
-const bool SoundSource::s_bDebugMetadata = false;
-
-/*
- SoundSource is an Uber-class for the reading and decoding of audio-files.
- Each class must have the following member functions:
- initializer with a filename
- seek()
- read()
- length()
- In addition there must be a static member:
- int ParseHeader(TrackInfoObject *Track)
- which is used for parsing header information, like trackname,length etc. The
- return type is int: 0 for OK, -1 for an error.
- */
-SoundSource::SoundSource(QString qFilename)
- : m_qFilename(qFilename),
- m_fReplayGain(0.0f),
- m_fBPM(0.0f),
- m_iDuration(0),
- m_iBitrate(0),
- m_iSampleRate(0),
- m_iChannels(0) {
-}
-
-SoundSource::~SoundSource() {
-}
-
-QList<long> *SoundSource::getCuePoints()
-{
- return 0;
-}
-
-QString SoundSource::getFilename()
-{
- return m_qFilename;
-}
-
-float SoundSource::str2bpm( QString sBpm ) {
- float bpm = sBpm.toFloat();
- if(bpm < 60) bpm = 0;
- while( bpm > 300 ) bpm = bpm / 10.;
- return bpm;
-}
-
-QString SoundSource::getArtist()
-{
- return m_sArtist;
-}
-QString SoundSource::getTitle()
-{
- return m_sTitle;
-}
-QString SoundSource::getAlbum()
-{
- return m_sAlbum;
-}
-QString SoundSource::getAlbumArtist()
-{
- return m_sAlbumArtist;
-}
-QString SoundSource::getType()
-{
- return m_sType;
-}
-QString SoundSource::getComment()
-{
- return m_sComment;
-}
-QString SoundSource::getYear()
-{
- return m_sYear;
-}
-QString SoundSource::getGenre()
-{
- return m_sGenre;
-}
-QString SoundSource::getComposer()
-{
- return m_sComposer;
-}
-QString SoundSource::getGrouping()
-{
- return m_sGrouping;
-}
-QString SoundSource::getTrackNumber()
-{
- return m_sTrackNumber;
-}
-float SoundSource::getReplayGain()
-{
- return m_fReplayGain;
-}
-float SoundSource::getBPM()
-{
- return m_fBPM;
-}
-int SoundSource::getDuration()
-{
- return m_iDuration;
-}
-int SoundSource::getBitrate()
-{
- return m_iBitrate;
-}
-unsigned int SoundSource::getSampleRate()
-{
- return m_iSampleRate;
-}
-int SoundSource::getChannels()
+namespace
{
- return m_iChannels;
-}
-
-void SoundSource::setArtist(QString artist)
-{
- m_sArtist = artist;
-}
-void SoundSource::setTitle(QString title)
-{
- m_sTitle = title;
-}
-void SoundSource::setAlbumArtist(QString albumArtist)
-{
- m_sAlbumArtist = albumArtist;
-}
-void SoundSource::setAlbum(QString album)
-{
- m_sAlbum = album;
-}
-void SoundSource::setComment(QString comment)
-{
- m_sComment = comment;
-}
-void SoundSource::setType(QString type)
-{
- m_sType = type;
-}
-void SoundSource::setYear(QString year)
-{
- m_sYear = year;
-}
-void SoundSource::setGenre(QString genre)
-{
- m_sGenre = genre;
-}
-void SoundSource::setComposer(QString composer)
-{
- m_sComposer = composer;
-}
-void SoundSource::setGrouping(QString grouping)
-{
- m_sGrouping = grouping;
-}
-void SoundSource::setTrackNumber(QString trackNumber)
-{
- m_sTrackNumber = trackNumber;
-}
-void SoundSource::setReplayGain(float replaygain)
-{
- m_fReplayGain = replaygain;
-}
-void SoundSource::setBPM(float bpm)
-{
- m_fBPM = bpm;
-}
-void SoundSource::setDuration(int duration)
-{
- m_iDuration = duration;
-}
-void SoundSource::setBitrate(int bitrate)
-{
- m_iBitrate = bitrate;
-}
-void SoundSource::setSampleRate(unsigned int samplerate)
-{
- m_iSampleRate = samplerate;
-}
-void SoundSource::setChannels(int channels)
-{
- m_iChannels = channels;
-}
-QString SoundSource::getKey(){
- return m_sKey;
-}
-void SoundSource::setKey(QString key){
- m_sKey = key;
-}
-
-QString SoundSource::toQString(TagLib::String tstring) const {
- if (tstring == TagLib::String::null) {
- return QString();
- }
- return TStringToQString(tstring);
-}
-
-bool SoundSource::processTaglibFile(TagLib::File& f) {
- if (s_bDebugMetadata)
- qDebug() << "Parsing" << getFilename();
-
- if (f.isValid()) {
- TagLib::Tag *tag = f.tag();
- if (tag) {
- QString title = toQString(tag->title());
- setTitle(title);
-
- QString artist = toQString(tag->artist());
- setArtist(artist);
-
- QString album = toQString(tag->album());
- setAlbum(album);
-
- QString comment = toQString(tag->comment());
- setComment(comment);
-
- QString genre = toQString(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);
- }
+ const float BPM_ZERO = 0.0f;
+ const float BPM_MIN = 60.0f;
+ const float BPM_MAX = 300.0f;
- 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 SoundSource::parseReplayGainString (QString sReplayGain) {
- QString ReplayGainstring = sReplayGain.remove( " dB" );
- float fReplayGain = db2ratio(ReplayGainstring.toFloat());
- // I found some mp3s of mine with replaygain tag set to 0dB even if not normalized.
- // This is because of Rapid Evolution 3, I suppose. I prefer to rescan them by setting value to 0 (i.e. rescan via analyserrg)
- if (fReplayGain == 1.0f) {
- fReplayGain = 0.0f;
- }
- setReplayGain(fReplayGain);
-}
-
-void SoundSource::processBpmString(QString tagName, QString sBpm) {
- if (s_bDebugMetadata)
- qDebug() << tagName << "BPM" << sBpm;
- if (sBpm.length() > 0) {
- float fBpm = str2bpm(sBpm);
- if (fBpm > 0)
- setBPM(fBpm);
- }
-}
-
-bool SoundSource::processID3v2Tag(TagLib::ID3v2::Tag* id3v2) {
-
- // Print every frame in the file.
- if (s_bDebugMetadata) {
- TagLib::ID3v2::FrameList::ConstIterator it = id3v2->frameList().begin();
- for(; it != id3v2->frameList().end(); it++) {
- qDebug() << "ID3V2" << (*it)->frameID().data() << "-"
- << toQString((*it)->toString());
- }
- }
-
- TagLib::ID3v2::FrameList bpmFrame = id3v2->frameListMap()["TBPM"];
- if (!bpmFrame.isEmpty()) {
- QString sBpm = toQString(bpmFrame.front()->toString());
- processBpmString("ID3v2", sBpm);
- }
-
- TagLib::ID3v2::FrameList keyFrame = id3v2->frameListMap()["TKEY"];
- if (!keyFrame.isEmpty()) {
- QString sKey = toQString(keyFrame.front()->toString());
- setKey(sKey);
- }
- // Foobar2000-style ID3v2.3.0 tags
- // TODO: Check if everything is ok.
- TagLib::ID3v2::FrameList frames = id3v2->frameListMap()["TXXX"];
- for ( TagLib::ID3v2::FrameList::Iterator it = frames.begin(); it != frames.end(); ++it ) {
- TagLib::ID3v2::UserTextIdentificationFrame* ReplayGainframe =
- dynamic_cast<TagLib::ID3v2::UserTextIdentificationFrame*>( *it );
- if ( ReplayGainframe && ReplayGainframe->fieldList().size() >= 2 )
- {
- QString desc = toQString( ReplayGainframe->description() ).toLower();
- if ( desc == "replaygain_album_gain" ){
- QString sReplayGain = toQString( ReplayGainframe->fieldList()[1]);