From c7f3051ec952396d65fd73a599dfdbc45c70f4f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Mon, 5 Oct 2015 20:34:40 +0200 Subject: Fix wavpack plugin, use WavpackOpenFileInputEx for unicode file paths in windows --- plugins/soundsourcewv/soundsourcewv.cpp | 161 +++++++++++++++++++++++++++++--- plugins/soundsourcewv/soundsourcewv.h | 20 +++- 2 files changed, 165 insertions(+), 16 deletions(-) (limited to 'plugins') diff --git a/plugins/soundsourcewv/soundsourcewv.cpp b/plugins/soundsourcewv/soundsourcewv.cpp index de4700ac73..20af06ba2b 100644 --- a/plugins/soundsourcewv/soundsourcewv.cpp +++ b/plugins/soundsourcewv/soundsourcewv.cpp @@ -4,6 +4,7 @@ //format_samples adapted from cmus (Peter Lemenkov) #include +#include #include "soundsourcewv.h" #include "soundsourcetaglib.h" @@ -12,19 +13,42 @@ #include namespace Mixxx { +//static +WavpackStreamReader SoundSourceWV::s_streamReader = { + SoundSourceWV::ReadBytesCallback, + SoundSourceWV::GetPosCallback, + SoundSourceWV::SetPosAbsCallback, + SoundSourceWV::SetPosRelCallback, + SoundSourceWV::PushBackByteCallback, + SoundSourceWV::GetlengthCallback, + SoundSourceWV::CanSeekCallback, + SoundSourceWV::WriteBytesCallback +}; + SoundSourceWV::SoundSourceWV(QString qFilename) : SoundSource(qFilename), filewvc(NULL), Bps(0), - filelength(0) { + filelength(0), + m_pWVFile(NULL), + m_pWVCFile(NULL) { setType("wv"); } - SoundSourceWV::~SoundSourceWV(){ if (filewvc) { WavpackCloseFile(filewvc); - filewvc=NULL; + filewvc = NULL; + } + if (m_pWVFile) { + m_pWVFile->close(); + delete m_pWVFile; + m_pWVFile = NULL; + } + if (m_pWVCFile) { + m_pWVCFile->close(); + delete m_pWVCFile; + m_pWVCFile = NULL; } } @@ -39,9 +63,20 @@ QList SoundSourceWV::supportedFileExtensions() Result SoundSourceWV::open() { QByteArray qBAFilename(getFilename().toLocal8Bit()); - char msg[80]; //hold possible error message - - filewvc = WavpackOpenFileInput(qBAFilename.constData(), msg, OPEN_2CH_MAX | OPEN_WVC,0); + char msg[80]; // hold possible error message + + // We use WavpackOpenFileInputEx to support Unicode paths on windows + // http://www.wavpack.com/lib_use.txt + m_pWVFile = new QFile(getFilename()); + m_pWVFile->open(QFile::ReadOnly); + QString correctionfileName(getFilename() + "c"); + if (QFile::exists(correctionfileName)) { + // If there is a correction file, open it as well + m_pWVCFile = new QFile(correctionfileName); + m_pWVCFile->open(QFile::ReadOnly); + } + filewvc = WavpackOpenFileInputEx(&s_streamReader, m_pWVFile, m_pWVCFile, msg, + OPEN_2CH_MAX | OPEN_WVC, 0); if (!filewvc) { qDebug() << "SSWV::open: failed to open file : "<< msg; return ERR; @@ -49,7 +84,10 @@ Result SoundSourceWV::open() if (WavpackGetMode(filewvc) & MODE_FLOAT) { qDebug() << "SSWV::open: cannot load 32bit float files"; WavpackCloseFile(filewvc); - filewvc=NULL; + filewvc = NULL; + m_pWVFile->close(); + delete m_pWVFile; + m_pWVFile = NULL; return ERR; } // wavpack_open succeeded -> populate variables @@ -57,8 +95,9 @@ Result SoundSourceWV::open() setSampleRate(WavpackGetSampleRate(filewvc)); setChannels(WavpackGetReducedChannels(filewvc)); Bps=WavpackGetBytesPerSample(filewvc); - qDebug () << "SSWV::open: opened filewvc with filelength: "<2) { qDebug() << "SSWV::open: warning: input file has > 2 bytes per sample, will be truncated to 16bits"; } @@ -83,13 +122,13 @@ 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 / getChannels())) { //if requested size requires more than one buffer filling - timesamps=(WV_BUF_LENGTH / getChannels()); //tempbuffer must hold (timesamps * channels) samples + timesamps = (size-sampsread) >> 1; // timesamps still remaining + if (timesamps > (unsigned long)(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 + 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) * getChannels()), tempbuffer, tsdone*getChannels()); @@ -199,4 +238,100 @@ void SoundSourceWV::format_samples(int Bps, char *dst, int32_t *src, uint32_t co return; } +//static +int32_t SoundSourceWV::ReadBytesCallback(void* id, void* data, int bcount) +{ + QFile* pFile = static_cast(id); + if (!pFile) { + return 0; + } + return pFile->read((char*)data, bcount); +} + + +// static +uint32_t SoundSourceWV::GetPosCallback(void *id) +{ + QFile* pFile = static_cast(id); + if (!pFile) { + return 0; + } + pFile->reset(); + return pFile->pos(); +} + +//static +int SoundSourceWV::SetPosAbsCallback(void* id, unsigned int pos) +{ + QFile* pFile = static_cast(id); + if (!pFile) { + return 0; + } + pFile->reset(); + return pFile->seek(pos) ? 0 : -1; +} + +//static +int SoundSourceWV::SetPosRelCallback(void *id, int delta, int mode) +{ + QFile* pFile = static_cast(id); + if (!pFile) { + return 0; + } + + switch(mode) { + case SEEK_SET: + pFile->reset(); + return pFile->seek(delta) ? 0 : -1; + case SEEK_CUR: + return pFile->seek(delta) ? 0 : -1; + case SEEK_END: + pFile->reset(); + return pFile->seek(pFile->size() + delta) ? 0 : -1; + default: + return -1; + } +} + +//static +int SoundSourceWV::PushBackByteCallback(void* id, int c) +{ + QFile* pFile = static_cast(id); + if (!pFile) { + return 0; + } + pFile->ungetChar((char)c); + return 1; +} + +//static +uint32_t SoundSourceWV::GetlengthCallback(void* id) +{ + QFile* pFile = static_cast(id); + if (!pFile) { + return 0; + } + return pFile->size(); +} + +//static +int SoundSourceWV::CanSeekCallback(void *id) +{ + QFile* pFile = static_cast(id); + if (!pFile) { + return 0; + } + return pFile->isSequential() ? 0 : 1; +} + +//static +int32_t SoundSourceWV::WriteBytesCallback(void* id, void* data, int32_t bcount) +{ + QFile* pFile = static_cast(id); + if (!pFile) { + return 0; + } + return (int32_t)pFile->write((char*)data, bcount); +} + } // namespace Mixxx diff --git a/plugins/soundsourcewv/soundsourcewv.h b/plugins/soundsourcewv/soundsourcewv.h index a013e42a01..7332d66d97 100644 --- a/plugins/soundsourcewv/soundsourcewv.h +++ b/plugins/soundsourcewv/soundsourcewv.h @@ -19,6 +19,8 @@ #define MY_EXPORT #endif +class QFile; + #define WV_BUF_LENGTH 65536 namespace Mixxx { @@ -35,11 +37,23 @@ class SoundSourceWV : public SoundSource { QImage parseCoverArt(); static QList supportedFileExtensions(); private: - WavpackContext * filewvc; //works as a file handle to access the wv file. + static int32_t ReadBytesCallback(void* id, void* data, int bcount); + static uint32_t GetPosCallback(void* id); + static int SetPosAbsCallback(void* id, unsigned int pos); + static int SetPosRelCallback(void* id, int delta, int mode); + static int PushBackByteCallback(void* id, int c); + static uint32_t GetlengthCallback(void* id); + static int CanSeekCallback(void* id); + static int32_t WriteBytesCallback(void* id, void* data, int32_t bcount); + static WavpackStreamReader s_streamReader; + + WavpackContext* filewvc; // works as a file handle to access the wv file. int Bps; unsigned long filelength; - int32_t tempbuffer[WV_BUF_LENGTH]; //hax ! legacy from cmus. this is 64k*4bytes. - void format_samples(int, char *, int32_t *, uint32_t); + int32_t tempbuffer[WV_BUF_LENGTH]; // hax ! legacy from cmus. this is 64k*4bytes. + void format_samples(int, char*, int32_t*, uint32_t); + QFile* m_pWVFile; + QFile* m_pWVCFile; }; -- cgit v1.2.3