diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2012-12-07 18:45:38 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2012-12-07 18:45:38 +0000 |
| commit | 8bded202c7204ad3f655030078c74c17fd121122 (patch) | |
| tree | 56d9172d0f856e0ce4abac146c14238194cd74a7 /src | |
| parent | cbb5689bad0caedcedd9d0366adde5d06b87989e (diff) | |
| download | qmmp-8bded202c7204ad3f655030078c74c17fd121122.tar.gz qmmp-8bded202c7204ad3f655030078c74c17fd121122.tar.bz2 qmmp-8bded202c7204ad3f655030078c74c17fd121122.zip | |
output api refactoring
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@3034 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src')
37 files changed, 654 insertions, 528 deletions
diff --git a/src/plugins/Output/alsa/outputalsa.cpp b/src/plugins/Output/alsa/outputalsa.cpp index 9900bba51..c9ed0eecd 100644 --- a/src/plugins/Output/alsa/outputalsa.cpp +++ b/src/plugins/Output/alsa/outputalsa.cpp @@ -19,8 +19,8 @@ ***************************************************************************/ #include <QObject> -#include <QApplication> -#include <QtGlobal> +//#include <QApplication> +//#include <QtGlobal> #include <QDir> #include <QSettings> #include <QTimer> @@ -36,8 +36,7 @@ #include <qmmp/statehandler.h> #include "outputalsa.h" -OutputALSA::OutputALSA(QObject * parent) - : Output(parent), m_inited(false) +OutputALSA::OutputALSA() : m_inited(false) { QSettings settings(Qmmp::configFile(), QSettings::IniFormat); QString dev_name = settings.value("ALSA/device","default").toString(); diff --git a/src/plugins/Output/alsa/outputalsa.h b/src/plugins/Output/alsa/outputalsa.h index 2b3ba4b3b..664c9b30b 100644 --- a/src/plugins/Output/alsa/outputalsa.h +++ b/src/plugins/Output/alsa/outputalsa.h @@ -23,8 +23,6 @@ class OutputALSA; - -#include <QObject> extern "C" { #include <alsa/asoundlib.h> @@ -36,22 +34,20 @@ extern "C" class OutputALSA : public Output { - Q_OBJECT public: - OutputALSA(QObject * parent = 0); + OutputALSA(); ~OutputALSA(); bool initialize(quint32, int, Qmmp::AudioFormat format); - qint64 latency(); - -private: //output api + qint64 latency(); qint64 writeAudio(unsigned char *data, qint64 maxSize); void drain(); void reset(); void suspend(); void resume(); +private: // helper functions long alsa_write(unsigned char *data, long size); void uninitialize(); diff --git a/src/plugins/Output/alsa/outputalsafactory.cpp b/src/plugins/Output/alsa/outputalsafactory.cpp index 65b08d25c..f89cf0031 100644 --- a/src/plugins/Output/alsa/outputalsafactory.cpp +++ b/src/plugins/Output/alsa/outputalsafactory.cpp @@ -35,9 +35,9 @@ const OutputProperties OutputALSAFactory::properties() const return properties; } -Output* OutputALSAFactory::create(QObject* parent) +Output* OutputALSAFactory::create() { - return new OutputALSA(parent); + return new OutputALSA(); } Volume *OutputALSAFactory::createVolume() diff --git a/src/plugins/Output/alsa/outputalsafactory.h b/src/plugins/Output/alsa/outputalsafactory.h index 1b33cdf60..b1543104d 100644 --- a/src/plugins/Output/alsa/outputalsafactory.h +++ b/src/plugins/Output/alsa/outputalsafactory.h @@ -38,7 +38,7 @@ Q_INTERFACES(OutputFactory) public: const OutputProperties properties() const; - Output* create(QObject* parent); + Output* create(); Volume *createVolume(); void showSettings(QWidget* parent); void showAbout(QWidget *parent); diff --git a/src/plugins/Output/jack/outputjack.cpp b/src/plugins/Output/jack/outputjack.cpp index 8845da21b..ffaa480ef 100644 --- a/src/plugins/Output/jack/outputjack.cpp +++ b/src/plugins/Output/jack/outputjack.cpp @@ -33,7 +33,7 @@ #define JACK_TIMEOUT 500000L -OutputJACK::OutputJACK(QObject *parent) : Output(parent), m_inited(false) +OutputJACK::OutputJACK() : Output(), m_inited(false) { JACK_Init(); m_wait_time = 0; diff --git a/src/plugins/Output/jack/outputjack.h b/src/plugins/Output/jack/outputjack.h index c5b691852..7670ec291 100644 --- a/src/plugins/Output/jack/outputjack.h +++ b/src/plugins/Output/jack/outputjack.h @@ -24,7 +24,7 @@ class OutputJACK; #include <qmmp/output.h> -#include <QObject> + extern "C" { #include <jack/jack.h> @@ -34,20 +34,18 @@ extern "C" class OutputJACK : public Output { - Q_OBJECT public: - OutputJACK(QObject * parent = 0); + OutputJACK(); ~OutputJACK(); bool initialize(quint32, int, Qmmp::AudioFormat format); + //output api qint64 latency(); - -private: - //output api qint64 writeAudio(unsigned char *data, qint64 maxSize); void drain(){} void reset(); +private: // helper functions void uninitialize(); qint64 m, m_wait_time; diff --git a/src/plugins/Output/jack/outputjackfactory.cpp b/src/plugins/Output/jack/outputjackfactory.cpp index 672f9bac8..4b56a412a 100644 --- a/src/plugins/Output/jack/outputjackfactory.cpp +++ b/src/plugins/Output/jack/outputjackfactory.cpp @@ -34,9 +34,9 @@ const OutputProperties OutputJACKFactory::properties() const return properties; } -Output* OutputJACKFactory::create(QObject* parent) +Output* OutputJACKFactory::create() { - return new OutputJACK(parent); + return new OutputJACK(); } Volume *OutputJACKFactory::createVolume() diff --git a/src/plugins/Output/jack/outputjackfactory.h b/src/plugins/Output/jack/outputjackfactory.h index 090661fb6..2bacf7c1c 100644 --- a/src/plugins/Output/jack/outputjackfactory.h +++ b/src/plugins/Output/jack/outputjackfactory.h @@ -37,7 +37,7 @@ Q_INTERFACES(OutputFactory) public: const OutputProperties properties() const; - Output* create(QObject* parent); + Output* create(); Volume *createVolume(); void showSettings(QWidget* parent); void showAbout(QWidget *parent); diff --git a/src/plugins/Output/null/outputnull.cpp b/src/plugins/Output/null/outputnull.cpp index 9aa1c149a..a7ea91997 100644 --- a/src/plugins/Output/null/outputnull.cpp +++ b/src/plugins/Output/null/outputnull.cpp @@ -21,7 +21,7 @@ #include "outputnull.h" -OutputNull::OutputNull(QObject * parent) : Output(parent) +OutputNull::OutputNull() : Output() { m_bytes_per_second = 0; } diff --git a/src/plugins/Output/null/outputnull.h b/src/plugins/Output/null/outputnull.h index ceee8455b..06fb05158 100644 --- a/src/plugins/Output/null/outputnull.h +++ b/src/plugins/Output/null/outputnull.h @@ -21,7 +21,6 @@ #ifndef OUTPUTNULL_H #define OUTPUTNULL_H -#include <QObject> #include <qmmp/output.h> /** @@ -29,19 +28,18 @@ */ class OutputNull : public Output { - Q_OBJECT public: - OutputNull(QObject * parent = 0); + OutputNull(); ~OutputNull(); bool initialize(quint32, int, Qmmp::AudioFormat format); - qint64 latency(); - -private: //output api + qint64 latency(); qint64 writeAudio(unsigned char *data, qint64 maxSize); void drain(); void reset(); + +private: qint64 m_bytes_per_second; }; diff --git a/src/plugins/Output/null/outputnullfactory.cpp b/src/plugins/Output/null/outputnullfactory.cpp index c9ece723a..7ce8bf407 100644 --- a/src/plugins/Output/null/outputnullfactory.cpp +++ b/src/plugins/Output/null/outputnullfactory.cpp @@ -34,9 +34,9 @@ const OutputProperties OutputNullFactory::properties() const return properties; } -Output* OutputNullFactory::create(QObject* parent) +Output* OutputNullFactory::create() { - return new OutputNull(parent); + return new OutputNull(); } Volume *OutputNullFactory::createVolume() diff --git a/src/plugins/Output/null/outputnullfactory.h b/src/plugins/Output/null/outputnullfactory.h index 001fbac1a..1a00a44f0 100644 --- a/src/plugins/Output/null/outputnullfactory.h +++ b/src/plugins/Output/null/outputnullfactory.h @@ -37,7 +37,7 @@ Q_INTERFACES(OutputFactory) public: const OutputProperties properties() const; - Output* create(QObject* parent); + Output* create(); Volume *createVolume(); void showSettings(QWidget* parent); void showAbout(QWidget *parent); diff --git a/src/plugins/Output/oss/outputoss.cpp b/src/plugins/Output/oss/outputoss.cpp index 03d85c7ae..148e18f7a 100644 --- a/src/plugins/Output/oss/outputoss.cpp +++ b/src/plugins/Output/oss/outputoss.cpp @@ -44,7 +44,7 @@ extern "C" #include <qmmp/visual.h> #include "outputoss.h" -OutputOSS::OutputOSS(QObject * parent) : Output(parent), m_audio_fd(-1) +OutputOSS::OutputOSS() : Output(), m_audio_fd(-1) { QSettings settings(Qmmp::configFile(), QSettings::IniFormat); m_audio_device = settings.value("OSS/device","/dev/dsp").toString(); diff --git a/src/plugins/Output/oss/outputoss.h b/src/plugins/Output/oss/outputoss.h index d3a02a463..c031dadd2 100644 --- a/src/plugins/Output/oss/outputoss.h +++ b/src/plugins/Output/oss/outputoss.h @@ -23,26 +23,23 @@ #ifndef OUTPUTOSS_H #define OUTPUTOSS_H -class OutputOSS; - #include <qmmp/output.h> #include <qmmp/volume.h> class OutputOSS : public Output { -Q_OBJECT public: - OutputOSS(QObject * parent = 0); + OutputOSS(); virtual ~OutputOSS(); bool initialize(quint32, int, Qmmp::AudioFormat format); - qint64 latency(); - -private: //output api + qint64 latency(); qint64 writeAudio(unsigned char *data, qint64 maxSize); void drain(); void reset(); + +private: //oss void post(); void sync(); diff --git a/src/plugins/Output/oss/outputossfactory.cpp b/src/plugins/Output/oss/outputossfactory.cpp index 41b14abaf..7e661d5a7 100644 --- a/src/plugins/Output/oss/outputossfactory.cpp +++ b/src/plugins/Output/oss/outputossfactory.cpp @@ -25,9 +25,9 @@ #include "outputossfactory.h" -Output* OutputOSSFactory::create(QObject* parent) +Output* OutputOSSFactory::create() { - return new OutputOSS(parent); + return new OutputOSS(); } const OutputProperties OutputOSSFactory::properties() const @@ -48,7 +48,7 @@ Volume *OutputOSSFactory::createVolume() void OutputOSSFactory::showSettings(QWidget* parent) { SettingsDialog *s = new SettingsDialog(parent); - s -> show(); + s->show(); } void OutputOSSFactory::showAbout(QWidget *parent) diff --git a/src/plugins/Output/oss/outputossfactory.h b/src/plugins/Output/oss/outputossfactory.h index e8f63f4e6..f3b6f1064 100644 --- a/src/plugins/Output/oss/outputossfactory.h +++ b/src/plugins/Output/oss/outputossfactory.h @@ -37,7 +37,7 @@ Q_INTERFACES(OutputFactory) public: const OutputProperties properties() const; - Output* create(QObject* parent); + Output* create(); Volume *createVolume(); void showSettings(QWidget* parent); void showAbout(QWidget *parent); diff --git a/src/plugins/Output/oss4/outputoss4.cpp b/src/plugins/Output/oss4/outputoss4.cpp index 9b75a91f6..4f97d0f80 100644 --- a/src/plugins/Output/oss4/outputoss4.cpp +++ b/src/plugins/Output/oss4/outputoss4.cpp @@ -47,7 +47,7 @@ extern "C" OutputOSS4 *OutputOSS4::m_instance = 0; VolumeOSS4 *OutputOSS4::m_vc = 0; -OutputOSS4::OutputOSS4(QObject *parent) : Output(parent) +OutputOSS4::OutputOSS4() : Output() { m_audio_fd = -1; QSettings settings(Qmmp::configFile(), QSettings::IniFormat); @@ -118,7 +118,7 @@ bool OutputOSS4::initialize(quint32 freq, int chan, Qmmp::AudioFormat format) qWarning("OutputOSS4: unsupported audio format"); return false; } - + if (ioctl(m_audio_fd, SNDCTL_DSP_SETFMT, &p) == -1) qWarning("OutputOSS4: ioctl SNDCTL_DSP_SETFMT failed: %s",strerror(errno)); diff --git a/src/plugins/Output/oss4/outputoss4.h b/src/plugins/Output/oss4/outputoss4.h index 2b0f7ad73..ee8ccf6af 100644 --- a/src/plugins/Output/oss4/outputoss4.h +++ b/src/plugins/Output/oss4/outputoss4.h @@ -34,23 +34,21 @@ class VolumeOSS4; */ class OutputOSS4 : public Output { -Q_OBJECT public: - OutputOSS4(QObject *parent = 0); + OutputOSS4(); virtual ~OutputOSS4(); bool initialize(quint32, int, Qmmp::AudioFormat format); int fd(); - qint64 latency(); - static OutputOSS4 *instance(); - static VolumeOSS4 *m_vc; - -private: //output api qint64 writeAudio(unsigned char *data, qint64 maxSize); void drain(); void reset(); + qint64 latency(); + + static OutputOSS4 *instance(); + static VolumeOSS4 *m_vc; private: void post(); diff --git a/src/plugins/Output/oss4/outputoss4factory.cpp b/src/plugins/Output/oss4/outputoss4factory.cpp index 9723cc8be..222988e7a 100644 --- a/src/plugins/Output/oss4/outputoss4factory.cpp +++ b/src/plugins/Output/oss4/outputoss4factory.cpp @@ -25,9 +25,9 @@ #include "outputoss4factory.h" -Output* OutputOSS4Factory::create(QObject* parent) +Output* OutputOSS4Factory::create() { - return new OutputOSS4(parent); + return new OutputOSS4(); } const OutputProperties OutputOSS4Factory::properties() const diff --git a/src/plugins/Output/oss4/outputoss4factory.h b/src/plugins/Output/oss4/outputoss4factory.h index 0c6f2361b..75ea31738 100644 --- a/src/plugins/Output/oss4/outputoss4factory.h +++ b/src/plugins/Output/oss4/outputoss4factory.h @@ -36,7 +36,7 @@ Q_INTERFACES(OutputFactory) public: const OutputProperties properties() const; - Output* create(QObject* parent); + Output* create(); Volume *createVolume(); void showSettings(QWidget* parent); void showAbout(QWidget *parent); diff --git a/src/plugins/Output/pulseaudio/outputpulseaudio.cpp b/src/plugins/Output/pulseaudio/outputpulseaudio.cpp index e591205e6..65a23cd7c 100644 --- a/src/plugins/Output/pulseaudio/outputpulseaudio.cpp +++ b/src/plugins/Output/pulseaudio/outputpulseaudio.cpp @@ -23,8 +23,7 @@ extern "C"{ } #include "outputpulseaudio.h" -OutputPulseAudio::OutputPulseAudio(QObject * parent) - : Output(parent) +OutputPulseAudio::OutputPulseAudio(): Output() { m_connection = 0; } diff --git a/src/plugins/Output/pulseaudio/outputpulseaudio.h b/src/plugins/Output/pulseaudio/outputpulseaudio.h index 54fcba77a..3e6c18ab6 100644 --- a/src/plugins/Output/pulseaudio/outputpulseaudio.h +++ b/src/plugins/Output/pulseaudio/outputpulseaudio.h @@ -32,20 +32,18 @@ extern "C"{ */ class OutputPulseAudio : public Output { - Q_OBJECT public: - OutputPulseAudio(QObject * parent = 0); + OutputPulseAudio(); ~OutputPulseAudio(); bool initialize(quint32, int, Qmmp::AudioFormat format); - qint64 latency(); - -private: //output api + qint64 latency(); qint64 writeAudio(unsigned char *data, qint64 maxSize); void drain(); void reset(); +private: // helper functions void uninitialize(); pa_simple *m_connection; diff --git a/src/plugins/Output/pulseaudio/outputpulseaudiofactory.cpp b/src/plugins/Output/pulseaudio/outputpulseaudiofactory.cpp index 7185f3b09..a000f0339 100644 --- a/src/plugins/Output/pulseaudio/outputpulseaudiofactory.cpp +++ b/src/plugins/Output/pulseaudio/outputpulseaudiofactory.cpp @@ -34,9 +34,9 @@ const OutputProperties OutputPulseAudioFactory::properties() const return properties; } -Output* OutputPulseAudioFactory::create(QObject* parent) +Output* OutputPulseAudioFactory::create() { - return new OutputPulseAudio(parent); + return new OutputPulseAudio(); } Volume *OutputPulseAudioFactory::createVolume() diff --git a/src/plugins/Output/pulseaudio/outputpulseaudiofactory.h b/src/plugins/Output/pulseaudio/outputpulseaudiofactory.h index 497f1b789..7ab29c3be 100644 --- a/src/plugins/Output/pulseaudio/outputpulseaudiofactory.h +++ b/src/plugins/Output/pulseaudio/outputpulseaudiofactory.h @@ -38,7 +38,7 @@ Q_INTERFACES(OutputFactory) public: const OutputProperties properties() const; - Output* create(QObject* parent); + Output* create(); Volume *createVolume(); void showSettings(QWidget* parent); void showAbout(QWidget *parent); diff --git a/src/plugins/Output/waveout/outputwaveout.cpp b/src/plugins/Output/waveout/outputwaveout.cpp index f4deb58c0..ae9c631c5 100644 --- a/src/plugins/Output/waveout/outputwaveout.cpp +++ b/src/plugins/Output/waveout/outputwaveout.cpp @@ -73,7 +73,7 @@ free_memory (void) GlobalFree (hg);
}
-OutputWaveOut::OutputWaveOut(QObject * parent) : Output(parent)
+OutputWaveOut::OutputWaveOut() : Output()
{
//m_connection = 0;
//m_dev = 0;
@@ -117,10 +117,10 @@ bool OutputWaveOut::initialize(quint32 freq, int chan, Qmmp::AudioFormat format) return false;
case WAVERR_BADFORMAT:
qWarning("OutputWaveOut: This audio format is not supported.");
- return false;
+ return false;
case WAVERR_SYNC:
qWarning("OutputWaveOut: The device is synchronous.");
- return false;
+ return false;
default:
qWarning("OutputWaveOut: Unknown media error.");
return false;
@@ -149,7 +149,7 @@ qint64 OutputWaveOut::writeAudio(unsigned char *data, qint64 len) void* allocptr;
len = qMin(len, (qint64)1024);
-
+
while (PlayedWaveHeadersCount > 0) // free used blocks ...
free_memory ();
@@ -158,7 +158,7 @@ qint64 OutputWaveOut::writeAudio(unsigned char *data, qint64 len) usleep(500);
return 0;
}
-
+
if ((hg2 = GlobalAlloc (GMEM_MOVEABLE, len)) == NULL) // allocate some memory for a copy of the buffer
{
qWarning("OutputWaveOut: GlobalAlloc failed");
diff --git a/src/plugins/Output/waveout/outputwaveout.h b/src/plugins/Output/waveout/outputwaveout.h index eef0b8fca..619653e84 100644 --- a/src/plugins/Output/waveout/outputwaveout.h +++ b/src/plugins/Output/waveout/outputwaveout.h @@ -21,7 +21,6 @@ #ifndef OUTPUTWAVEOUT_H
#define OUTPUTWAVEOUT_H
-#include <QObject>
#include <stdio.h>
#include <windows.h>
#include <qmmp/output.h>
@@ -31,22 +30,21 @@ */
class OutputWaveOut : public Output
{
- Q_OBJECT
public:
- OutputWaveOut(QObject * parent = 0);
+ OutputWaveOut();
~OutputWaveOut();
bool initialize(quint32, int, Qmmp::AudioFormat format);
- qint64 latency();
-private:
//output api
+ qint64 latency();
qint64 writeAudio(unsigned char *data, qint64 size);
void drain();
void suspend();
void resume();
- void reset();
+ void reset();
+private:
// helper functions
void status();
void uninitialize();
diff --git a/src/plugins/Output/waveout/outputwaveoutfactory.cpp b/src/plugins/Output/waveout/outputwaveoutfactory.cpp index e35cd1e12..01fcb4b06 100644 --- a/src/plugins/Output/waveout/outputwaveoutfactory.cpp +++ b/src/plugins/Output/waveout/outputwaveoutfactory.cpp @@ -33,9 +33,9 @@ const OutputProperties OutputWaveOutFactory::properties() const return properties;
}
-Output* OutputWaveOutFactory::create(QObject* parent)
+Output* OutputWaveOutFactory::create()
{
- return new OutputWaveOut(parent);
+ return new OutputWaveOut();
}
Volume *OutputWaveOutFactory::createVolume()
diff --git a/src/plugins/Output/waveout/outputwaveoutfactory.h b/src/plugins/Output/waveout/outputwaveoutfactory.h index c770a4348..86cc1014d 100644 --- a/src/plugins/Output/waveout/outputwaveoutfactory.h +++ b/src/plugins/Output/waveout/outputwaveoutfactory.h @@ -35,7 +35,7 @@ Q_INTERFACES(OutputFactory) public:
const OutputProperties properties() const;
- Output* create(QObject* parent);
+ Output* create();
Volume *createVolume();
void showSettings(QWidget* parent);
void showAbout(QWidget *parent);
diff --git a/src/qmmp/output.cpp b/src/qmmp/output.cpp index 58141f84b..703696c88 100644 --- a/src/qmmp/output.cpp +++ b/src/qmmp/output.cpp @@ -8,7 +8,6 @@ #include <QObject> #include <QStringList> #include <QApplication> -#include <QTimer> #include <stdio.h> #include "audioparameters.h" #include "qmmpsettings.h" @@ -17,54 +16,11 @@ #include "qmmp.h" #include "output.h" -extern "C" { -#include "equ/iir.h" -} - -//static functions -static inline void s8_to_s16(qint8 *in, qint16 *out, qint64 samples) -{ - for(qint64 i = 0; i < samples; ++i) - out[i] = in[i] << 8; - return; -} - -static inline void s24_to_s16(qint32 *in, qint16 *out, qint64 samples) -{ - for(qint64 i = 0; i < samples; ++i) - out[i] = in[i] >> 8; - return; -} - -static inline void s32_to_s16(qint32 *in, qint16 *out, qint64 samples) -{ - for(qint64 i = 0; i < samples; ++i) - out[i] = in[i] >> 16; - return; -} - -Output::Output (QObject* parent) : QThread (parent) +Output::Output() { - m_handler = StateHandler::instance(); m_frequency = 0; m_channels = 0; m_format = Qmmp::PCM_UNKNOWM; - m_totalWritten = 0; - m_currentMilliseconds = -1; - m_bytesPerMillisecond = 0; - m_userStop = false; - m_finish = false; - m_visBuffer = 0; - m_visBufferSize = 0; - m_kbps = 0; - m_skip = false; - m_pause = false; - m_prev_pause = false; - m_useEq = false; - m_eqEnabled = false; - m_settings = QmmpSettings::instance(); - connect(m_settings,SIGNAL(eqSettingsChanged()), SLOT(updateEqSettings())); - updateEqSettings(); } void Output::configure(quint32 freq, int chan, Qmmp::AudioFormat format) @@ -72,72 +28,6 @@ void Output::configure(quint32 freq, int chan, Qmmp::AudioFormat format) m_frequency = freq; m_channels = chan; m_format = format; - QMap<Qmmp::AudioFormat, QString> formatNames; - formatNames.insert(Qmmp::PCM_S8, "s8"); - formatNames.insert(Qmmp::PCM_S16LE, "s16le"); - formatNames.insert(Qmmp::PCM_S24LE, "s24le"); - formatNames.insert(Qmmp::PCM_S32LE, "s32le"); - qDebug("Output: [%s] %d Hz, %d ch, %s", qPrintable(Output::currentFactory()->properties().shortName), - freq, chan, qPrintable(formatNames.value(format))); - m_bytesPerMillisecond = freq * chan * AudioParameters::sampleSize(format) / 1000; - m_recycler.configure(freq, chan, format); //calculate output buffer size - //visual buffer - if(m_visBuffer) - delete [] m_visBuffer; - m_visBufferSize = QMMP_BLOCK_FRAMES * 2 * chan; //16-bit samples - m_visBuffer = new unsigned char [m_visBufferSize]; - m_useEq = m_eqEnabled && m_frequency && m_format == Qmmp::PCM_S16LE; - if(m_frequency) - { - init_iir(m_frequency, m_settings->eqSettings().bands()); - clean_history(); - } -} - -void Output::pause() -{ - mutex()->lock(); - m_pause = !m_pause; - mutex()->unlock(); - Qmmp::State state = m_pause ? Qmmp::Paused: Qmmp::Playing; - dispatch(state); -} - -void Output::stop() -{ - m_userStop = true; -} - -void Output::finish() -{ - m_finish = true; -} - -qint64 Output::written() -{ - return m_totalWritten; -} - -void Output::seek(qint64 pos, bool reset) -{ - m_totalWritten = pos * m_bytesPerMillisecond; - m_currentMilliseconds = -1; - m_skip = isRunning() && reset; -} - -Recycler *Output::recycler() -{ - return &m_recycler; -} - -QMutex *Output::mutex() -{ - return &m_mutex; -} - -void Output::setStateHandler(StateHandler *handler) -{ - m_handler = handler; } AudioParameters Output::audioParameters() const @@ -165,11 +55,6 @@ int Output::sampleSize() const return AudioParameters::sampleSize(m_format); } -qint64 Output::bufferSize() const -{ - return m_recycler.size(); -} - void Output::suspend() {} @@ -179,237 +64,6 @@ void Output::resume() Output::~Output() {} -void Output::dispatchVisual (Buffer *buffer) -{ - if (!buffer) - return; - - int sampleSize = AudioParameters::sampleSize(m_format); - int samples = buffer->nbytes/sampleSize; - int outSize = samples*2; - if((m_format != Qmmp::PCM_S16LE) && outSize > m_visBufferSize) //increase buffer size - { - delete[] m_visBuffer; - m_visBufferSize = outSize; - m_visBuffer = new unsigned char [m_visBufferSize]; - } - switch(m_format) - { - case Qmmp::PCM_S8: - s8_to_s16((qint8 *)buffer->data, (qint16 *) m_visBuffer, samples); - break; - case Qmmp::PCM_S16LE: - m_visBuffer = buffer->data; - outSize = buffer->nbytes; - break; - case Qmmp::PCM_S24LE: - s24_to_s16((qint32 *)buffer->data, (qint16 *) m_visBuffer, samples); - break; - case Qmmp::PCM_S32LE: - s32_to_s16((qint32 *)buffer->data, (qint16 *) m_visBuffer, samples); - break; - default: - return; - } - foreach (Visual *visual, *Visual::visuals()) - { - visual->mutex()->lock (); - visual->add (m_visBuffer, outSize, m_channels); - visual->mutex()->unlock(); - } - if(m_format == Qmmp::PCM_S16LE) - m_visBuffer = 0; -} - - -void Output::clearVisuals() -{ - foreach (Visual *visual, *Visual::visuals()) - { - visual->mutex()->lock (); - visual->clear (); - visual->mutex()->unlock(); - } -} - -void Output::dispatch(qint64 elapsed, - int bitrate, - int frequency, - int precision, - int channels) -{ - if (m_handler) - m_handler->dispatch(elapsed, bitrate, frequency, precision, channels); -} - -void Output::dispatch(const Qmmp::State &state) -{ - if (m_handler) - m_handler->dispatch(state); - if (state == Qmmp::Stopped) - clearVisuals(); -} - -void Output::run() -{ - mutex()->lock (); - if (!m_bytesPerMillisecond) - { - qWarning("Output: invalid audio parameters"); - mutex()->unlock (); - return; - } - mutex()->unlock (); - - bool done = false; - Buffer *b = 0; - qint64 l, m = 0; - - dispatch(Qmmp::Playing); - - while (!done) - { - mutex()->lock (); - if(m_pause != m_prev_pause) - { - if(m_pause) - { - suspend(); - mutex()->unlock(); - m_prev_pause = m_pause; - continue; - } - else - resume(); - m_prev_pause = m_pause; - } - recycler()->mutex()->lock (); - done = m_userStop || (m_finish && recycler()->empty()); - - while (!done && (recycler()->empty() || m_pause)) - { - mutex()->unlock(); - recycler()->cond()->wakeOne(); - recycler()->cond()->wait(recycler()->mutex()); - mutex()->lock (); - done = m_userStop || m_finish; - } - - status(); - if (!b) - { - b = recycler()->next(); - if (b && b->rate) - m_kbps = b->rate; - } - - recycler()->cond()->wakeOne(); - recycler()->mutex()->unlock(); - mutex()->unlock(); - if (b) - { - if (m_useEq) - { - switch(m_format) - { - case Qmmp::PCM_S16LE: - iir((void*) b->data, b->nbytes, m_channels); - break; - case Qmmp::PCM_S24LE: - case Qmmp::PCM_S32LE: - iir32((void*) b->data, b->nbytes, m_channels); - break; - default: - ; - } - } - dispatchVisual(b); - if (SoftwareVolume::instance()) - SoftwareVolume::instance()->changeVolume(b, m_channels, m_format); - l = 0; - m = 0; - while (l < b->nbytes && !m_pause) - { - mutex()->lock(); - if(m_skip) - { - m_skip = false; - reset(); - mutex()->unlock(); - break; - } - mutex()->unlock(); - m = writeAudio(b->data + l, b->nbytes - l); - if(m >= 0) - { - m_totalWritten += m; - l+= m; - } - else - break; - } - if(m < 0) - break; - } - mutex()->lock(); - //force buffer change - recycler()->mutex()->lock (); - recycler()->done(); - recycler()->mutex()->unlock(); - b = 0; - mutex()->unlock(); - } - mutex()->lock (); - //write remaining data - if(m_finish) - { - drain(); -#ifdef Q_OS_WIN - qDebug("Output: total written %I64d", m_totalWritten); -#else - qDebug("Output: total written %lld", m_totalWritten); -#endif - } - dispatch(Qmmp::Stopped); - mutex()->unlock(); -} - -void Output::status() -{ - qint64 ct = m_totalWritten / m_bytesPerMillisecond - latency(); - - if (ct < 0) - ct = 0; - - if (ct > m_currentMilliseconds) - { - m_currentMilliseconds = ct; - dispatch(m_currentMilliseconds, m_kbps, - m_frequency, AudioParameters::sampleSize(m_format)*8, m_channels); - } -} - -void Output::updateEqSettings() -{ - mutex()->lock(); - m_eqEnabled = m_settings->eqSettings().isEnabled(); - double preamp = m_settings->eqSettings().preamp(); - int bands = m_settings->eqSettings().bands(); - - init_iir(m_frequency, bands); - - set_preamp(0, 1.0 + 0.0932471 *preamp + 0.00279033 * preamp * preamp); - set_preamp(1, 1.0 + 0.0932471 *preamp + 0.00279033 * preamp * preamp); - for(int i = 0; i < bands; ++i) - { - double value = m_settings->eqSettings().gain(i); - set_gain(i,0, 0.03*value+0.000999999*value*value); - set_gain(i,1, 0.03*value+0.000999999*value*value); - } - m_useEq = isRunning() && m_eqEnabled; - mutex()->unlock(); -} - // static methods QList<OutputFactory*> *Output::m_factories = 0; @@ -447,7 +101,7 @@ void Output::checkFactories() } } -Output *Output::create (QObject *parent) +Output *Output::create () { Output *output = 0; @@ -461,7 +115,7 @@ Output *Output::create (QObject *parent) if (!fact && !m_factories->isEmpty()) fact = m_factories->at(0); if (fact) - output = fact->create (parent); + output = fact->create (); return output; } diff --git a/src/qmmp/output.h b/src/qmmp/output.h index d67318c51..59799a57b 100644 --- a/src/qmmp/output.h +++ b/src/qmmp/output.h @@ -28,15 +28,14 @@ class QmmpSettings; * @author Brad Hughes <bhughes@trolltech.com> * @author Ilya Kotov <forkotov@hotmail.ru> */ -class Output : public QThread +class Output { - Q_OBJECT public: /*! * Object contsructor. * @param parent Parent object. */ - Output(QObject * parent = 0); + Output(); /*! * Destructor. */ @@ -58,38 +57,30 @@ public: * Requests playback to pause. If it was paused already, playback should resume. * Subclasses that reimplement this function must call the base implementation. */ - void pause(); /*! - * Requests playback to stop. - */ - void stop(); - /*! - * Requests playback to finish. - */ - void finish(); - /*! - * Returns the number of bytes that were written. + * Writes up to \b maxSize bytes from \b data to the output interface device. + * Returns the number of bytes written, or -1 if an error occurred. + * Subclass should reimplement this function. */ - qint64 written(); + virtual qint64 writeAudio(unsigned char *data, qint64 maxSize) = 0; /*! - * Requests a seek to the time \b pos indicated, specified in milliseconds. - * If \b reset is \b true, this function also clears internal output buffers for faster seeking; - * otherwise does nothing with buffers. + * Writes all remaining plugin's internal data to audio output device. + * Subclass should reimplement this function. */ - void seek(qint64 pos, bool reset = false); + virtual void drain() = 0; /*! - * Returns Recycler pointer. + * Drops all plugin's internal data, resets audio device + * Subclass should reimplement this function. */ - Recycler *recycler(); + virtual void reset() = 0; /*! - * Returns mutex pointer. + * Stops processing audio data, preserving buffered audio data. */ - QMutex *mutex(); + virtual void suspend(); /*! - * Sets StateHandler pointer. May be used to override default state handler. - * @param handler StateHandler pointer; + * Resumes processing audio data. */ - void setStateHandler(StateHandler *handler); + virtual void resume(); /*! * Returns selected audio parameters. */ @@ -111,15 +102,10 @@ public: */ int sampleSize() const; /*! - * Returns buffer size in bytes. - */ - qint64 bufferSize() const; - /*! * Creates selected output. - * @param parent Parent object. * @return Output subclass object. */ - static Output *create(QObject *parent = 0); + static Output *create(); /*! * Returns a list of output factories. */ @@ -140,30 +126,6 @@ public: protected: /*! - * Writes up to \b maxSize bytes from \b data to the output interface device. - * Returns the number of bytes written, or -1 if an error occurred. - * Subclass should reimplement this function. - */ - virtual qint64 writeAudio(unsigned char *data, qint64 maxSize) = 0; - /*! - * Writes all remaining plugin's internal data to audio output device. - * Subclass should reimplement this function. - */ - virtual void drain() = 0; - /*! - * Drops all plugin's internal data, resets audio device - * Subclass should reimplement this function. - */ - virtual void reset() = 0; - /*! - * Stops processing audio data, preserving buffered audio data. - */ - virtual void suspend(); - /*! - * Resumes processing audio data. - */ - virtual void resume(); - /*! * Use this function inside initialize() reimplementation to tell about accepted audio parameters. * @param freq Sample rate. * @param chan Number of channels. @@ -171,36 +133,10 @@ protected: */ void configure(quint32 freq, int chan, Qmmp::AudioFormat format); -private slots: - void updateEqSettings(); - private: - void run(); //thread run function - void status(); - void dispatch(qint64 elapsed, - int bitrate, - int frequency, - int bits, - int channels); - void dispatch(const Qmmp::State &state); - void dispatchVisual(Buffer *buffer); - void clearVisuals(); - bool m_skip; - QMutex m_mutex; - Recycler m_recycler; - StateHandler *m_handler; quint32 m_frequency; - int m_channels, m_kbps; + int m_channels; Qmmp::AudioFormat m_format; - qint64 m_bytesPerMillisecond; - bool m_userStop, m_pause; - bool m_prev_pause; - bool m_finish; - bool m_useEq, m_eqEnabled; - qint64 m_totalWritten, m_currentMilliseconds; - unsigned char *m_visBuffer; - qint64 m_visBufferSize; - QmmpSettings *m_settings; static void checkFactories(); static QList<OutputFactory*> *m_factories; static QHash <OutputFactory*, QString> *m_files; diff --git a/src/qmmp/outputfactory.h b/src/qmmp/outputfactory.h index 53e915f43..ffc7730c8 100644 --- a/src/qmmp/outputfactory.h +++ b/src/qmmp/outputfactory.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2007-2009 by Ilya Kotov * + * Copyright (C) 2007-2012 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -65,9 +65,8 @@ public: virtual const OutputProperties properties() const = 0; /*! * Creates output provided by plugin. - * @param parent Parent object. */ - virtual Output *create(QObject *parent) = 0; + virtual Output *create() = 0; /*! * Creates volume control object provided by plugin. * Returns \b 0 if volume control is not supported by plugin. diff --git a/src/qmmp/outputwriter.cpp b/src/qmmp/outputwriter.cpp new file mode 100644 index 000000000..35c9d1d37 --- /dev/null +++ b/src/qmmp/outputwriter.cpp @@ -0,0 +1,419 @@ +/*************************************************************************** + * Copyright (C) 2012 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program 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 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "statehandler.h" +#include "visual.h" +#include "output.h" +#include "volumecontrol_p.h" +#include "outputwriter_p.h" + +extern "C" { +#include "equ/iir.h" +} + +//static functions +static inline void s8_to_s16(qint8 *in, qint16 *out, qint64 samples) +{ + for(qint64 i = 0; i < samples; ++i) + out[i] = in[i] << 8; + return; +} + +static inline void s24_to_s16(qint32 *in, qint16 *out, qint64 samples) +{ + for(qint64 i = 0; i < samples; ++i) + out[i] = in[i] >> 8; + return; +} + +static inline void s32_to_s16(qint32 *in, qint16 *out, qint64 samples) +{ + for(qint64 i = 0; i < samples; ++i) + out[i] = in[i] >> 16; + return; +} + +OutputWriter::OutputWriter (QObject* parent) : QThread (parent) +{ + m_handler = StateHandler::instance(); + m_frequency = 0; + m_channels = 0; + m_output = 0; + m_format = Qmmp::PCM_UNKNOWM; + m_totalWritten = 0; + m_currentMilliseconds = -1; + m_bytesPerMillisecond = 0; + m_userStop = false; + m_finish = false; + m_visBuffer = 0; + m_visBufferSize = 0; + m_kbps = 0; + m_skip = false; + m_pause = false; + m_prev_pause = false; + m_useEq = false; + m_eqEnabled = false; + m_settings = QmmpSettings::instance(); + connect(m_settings,SIGNAL(eqSettingsChanged()), SLOT(updateEqSettings())); + updateEqSettings(); +} + +OutputWriter::~OutputWriter() +{ + if(m_output) + { + delete m_output; + m_output = 0; + } +} + +bool OutputWriter::initialize(quint32 freq, int chan, Qmmp::AudioFormat format) +{ + m_output = Output::create(); + m_frequency = freq; + m_channels = chan; + m_format = format; + if(!m_output) + { + qWarning("OutputWriter: unable to create output"); + return false; + } + + if (!m_output->initialize(freq, chan, format)) + { + qWarning("QmmpAudioEngine: unable to initialize output"); + delete m_output; + m_output = 0; + return false; + } + QMap<Qmmp::AudioFormat, QString> formatNames; + formatNames.insert(Qmmp::PCM_S8, "s8"); + formatNames.insert(Qmmp::PCM_S16LE, "s16le"); + formatNames.insert(Qmmp::PCM_S24LE, "s24le"); + formatNames.insert(Qmmp::PCM_S32LE, "s32le"); + qDebug("OutputWriter: [%s] %d Hz, %d ch, %s", + qPrintable(Output::currentFactory()->properties().shortName), + freq, chan, qPrintable(formatNames.value(format))); + m_bytesPerMillisecond = freq * chan * AudioParameters::sampleSize(format) / 1000; + m_recycler.configure(freq, chan, format); //calculate output buffer size + //visual buffer + if(m_visBuffer) + delete [] m_visBuffer; + m_visBufferSize = QMMP_BLOCK_FRAMES * 2 * chan; //16-bit samples + m_visBuffer = new unsigned char [m_visBufferSize]; + m_useEq = m_eqEnabled && m_frequency && m_format == Qmmp::PCM_S16LE; + if(m_frequency) + { + init_iir(m_frequency, m_settings->eqSettings().bands()); + clean_history(); + } + return true; +} + +void OutputWriter::pause() +{ + mutex()->lock(); + m_pause = !m_pause; + mutex()->unlock(); + Qmmp::State state = m_pause ? Qmmp::Paused: Qmmp::Playing; + dispatch(state); +} + +void OutputWriter::stop() +{ + m_userStop = true; +} + +void OutputWriter::finish() +{ + m_finish = true; +} + +void OutputWriter::seek(qint64 pos, bool reset) +{ + m_totalWritten = pos * m_bytesPerMillisecond; + m_currentMilliseconds = -1; + m_skip = isRunning() && reset; +} + +Recycler *OutputWriter::recycler() +{ + return &m_recycler; +} + +QMutex *OutputWriter::mutex() +{ + return &m_mutex; +} + +AudioParameters OutputWriter::audioParameters() const +{ + return AudioParameters(m_frequency, m_channels, m_format); +} + +quint32 OutputWriter::sampleRate() +{ + return m_frequency; +} + +int OutputWriter::channels() +{ + return m_channels; +} + +Qmmp::AudioFormat OutputWriter::format() const +{ + return m_format; +} + +int OutputWriter::sampleSize() const +{ + return AudioParameters::sampleSize(m_format); +} + +void OutputWriter::dispatchVisual (Buffer *buffer) +{ + if (!buffer) + return; + + int sampleSize = AudioParameters::sampleSize(m_format); + int samples = buffer->nbytes/sampleSize; + int outSize = samples*2; + if((m_format != Qmmp::PCM_S16LE) && outSize > m_visBufferSize) //increase buffer size + { + delete[] m_visBuffer; + m_visBufferSize = outSize; + m_visBuffer = new unsigned char [m_visBufferSize]; + } + switch(m_format) + { + case Qmmp::PCM_S8: + s8_to_s16((qint8 *)buffer->data, (qint16 *) m_visBuffer, samples); + break; + case Qmmp::PCM_S16LE: + m_visBuffer = buffer->data; + outSize = buffer->nbytes; + break; + case Qmmp::PCM_S24LE: + s24_to_s16((qint32 *)buffer->data, (qint16 *) m_visBuffer, samples); + break; + case Qmmp::PCM_S32LE: + s32_to_s16((qint32 *)buffer->data, (qint16 *) m_visBuffer, samples); + break; + default: + return; + } + foreach (Visual *visual, *Visual::visuals()) + { + visual->mutex()->lock (); + visual->add (m_visBuffer, outSize, m_channels); + visual->mutex()->unlock(); + } + if(m_format == Qmmp::PCM_S16LE) + m_visBuffer = 0; +} + +void OutputWriter::clearVisuals() +{ + foreach (Visual *visual, *Visual::visuals()) + { + visual->mutex()->lock (); + visual->clear (); + visual->mutex()->unlock(); + } +} + +void OutputWriter::dispatch(qint64 elapsed, + int bitrate, + int frequency, + int precision, + int channels) +{ + if (m_handler) + m_handler->dispatch(elapsed, bitrate, frequency, precision, channels); +} + +void OutputWriter::dispatch(const Qmmp::State &state) +{ + if (m_handler) + m_handler->dispatch(state); + if (state == Qmmp::Stopped) + clearVisuals(); +} + +void OutputWriter::run() +{ + mutex()->lock (); + if (!m_bytesPerMillisecond) + { + qWarning("OutputWriter: invalid audio parameters"); + mutex()->unlock (); + return; + } + mutex()->unlock (); + + bool done = false; + Buffer *b = 0; + qint64 l, m = 0; + + dispatch(Qmmp::Playing); + + while (!done) + { + mutex()->lock (); + if(m_pause != m_prev_pause) + { + if(m_pause) + { + m_output->suspend(); + mutex()->unlock(); + m_prev_pause = m_pause; + continue; + } + else + m_output->resume(); + m_prev_pause = m_pause; + } + recycler()->mutex()->lock (); + done = m_userStop || (m_finish && recycler()->empty()); + + while (!done && (recycler()->empty() || m_pause)) + { + mutex()->unlock(); + recycler()->cond()->wakeOne(); + recycler()->cond()->wait(recycler()->mutex()); + mutex()->lock (); + done = m_userStop || m_finish; + } + + status(); + if (!b) + { + b = recycler()->next(); + if (b && b->rate) + m_kbps = b->rate; + } + + recycler()->cond()->wakeOne(); + recycler()->mutex()->unlock(); + mutex()->unlock(); + if (b) + { + if (m_useEq) + { + switch(m_format) + { + case Qmmp::PCM_S16LE: + iir((void*) b->data, b->nbytes, m_channels); + break; + case Qmmp::PCM_S24LE: + case Qmmp::PCM_S32LE: + iir32((void*) b->data, b->nbytes, m_channels); + break; + default: + ; + } + } + dispatchVisual(b); + if (SoftwareVolume::instance()) + SoftwareVolume::instance()->changeVolume(b, m_channels, m_format); + l = 0; + m = 0; + while (l < b->nbytes && !m_pause) + { + mutex()->lock(); + if(m_skip) + { + m_skip = false; + m_output->reset(); + mutex()->unlock(); + break; + } + mutex()->unlock(); + m = m_output->writeAudio(b->data + l, b->nbytes - l); + if(m >= 0) + { + m_totalWritten += m; + l+= m; + } + else + break; + } + if(m < 0) + break; + } + mutex()->lock(); + //force buffer change + recycler()->mutex()->lock (); + recycler()->done(); + recycler()->mutex()->unlock(); + b = 0; + mutex()->unlock(); + } + mutex()->lock (); + //write remaining data + if(m_finish) + { + m_output->drain(); +#ifdef Q_OS_WIN + qDebug("OutputWriter: total written %I64d", m_totalWritten); +#else + qDebug("OutputWriter: total written %lld", m_totalWritten); +#endif + } + dispatch(Qmmp::Stopped); + mutex()->unlock(); +} + +void OutputWriter::status() +{ + qint64 ct = m_totalWritten / m_bytesPerMillisecond - m_output->latency(); + + if (ct < 0) + ct = 0; + + if (ct > m_currentMilliseconds) + { + m_currentMilliseconds = ct; + dispatch(m_currentMilliseconds, m_kbps, + m_frequency, AudioParameters::sampleSize(m_format)*8, m_channels); + } +} + +void OutputWriter::updateEqSettings() +{ + mutex()->lock(); + m_eqEnabled = m_settings->eqSettings().isEnabled(); + double preamp = m_settings->eqSettings().preamp(); + int bands = m_settings->eqSettings().bands(); + + init_iir(m_frequency, bands); + + set_preamp(0, 1.0 + 0.0932471 *preamp + 0.00279033 * preamp * preamp); + set_preamp(1, 1.0 + 0.0932471 *preamp + 0.00279033 * preamp * preamp); + for(int i = 0; i < bands; ++i) + { + double value = m_settings->eqSettings().gain(i); + set_gain(i,0, 0.03*value+0.000999999*value*value); + set_gain(i,1, 0.03*value+0.000999999*value*value); + } + m_useEq = isRunning() && m_eqEnabled; + mutex()->unlock(); +} diff --git a/src/qmmp/outputwriter_p.h b/src/qmmp/outputwriter_p.h new file mode 100644 index 000000000..96c94638e --- /dev/null +++ b/src/qmmp/outputwriter_p.h @@ -0,0 +1,133 @@ +/*************************************************************************** + * Copyright (C) 2012 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program 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 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef OUTPUTWRITER_P_H +#define OUTPUTWRITER_P_H + +#include <QThread> +#include <QMutex> +#include "recycler.h" +#include "audioparameters.h" + +class QTimer; +class QmmpSettings; +class StateHandler; +class Output; + +/** @internal + @author Ilya Kotov <forkotov02@hotmail.ru> +*/ +class OutputWriter : public QThread +{ + Q_OBJECT +public: + explicit OutputWriter(QObject *parent = 0); + + ~OutputWriter(); + /*! + * Prepares object for usage and setups required audio parameters. + * @param freq Sample rate. + * @param chan Number of channels. + * @param format Audio format + * @return initialization result (\b true - success, \b false - failure) + */ + bool initialize(quint32 freq, int chan, Qmmp::AudioFormat format); + /*! + * Requests playback to pause. If it was paused already, playback should resume. + */ + void pause(); + /*! + * Requests playback to stop. + */ + void stop(); + /*! + * Requests playback to finish. + */ + void finish(); + /*! + * Requests a seek to the time \b pos indicated, specified in milliseconds. + * If \b reset is \b true, this function also clears internal output buffers for faster seeking; + * otherwise does nothing with buffers. + */ + void seek(qint64 pos, bool reset = false); + /*! + * Returns Recycler pointer. + */ + Recycler *recycler(); + /*! + * Returns mutex pointer. + */ + QMutex *mutex(); + /*! + * Returns selected audio parameters. + */ + AudioParameters audioParameters() const; + /*! + * Returns samplerate. + */ + quint32 sampleRate(); + /*! + * Returns channels number. + */ + int channels(); + /*! + * Returns selected audio format. + */ + Qmmp::AudioFormat format() const; + /*! + * Returns sample size in bytes. + */ + int sampleSize() const; + +private slots: + void updateEqSettings(); + +private: + void run(); //thread run function + void status(); + void dispatch(qint64 elapsed, + int bitrate, + int frequency, + int bits, + int channels); + void dispatch(const Qmmp::State &state); + void dispatchVisual(Buffer *buffer); + void clearVisuals(); + bool m_skip; + QMutex m_mutex; + Recycler m_recycler; + StateHandler *m_handler; + quint32 m_frequency; + int m_channels, m_kbps; + Qmmp::AudioFormat m_format; + qint64 m_bytesPerMillisecond; + bool m_userStop, m_pause; + bool m_prev_pause; + bool m_finish; + bool m_useEq, m_eqEnabled; + qint64 m_totalWritten, m_currentMilliseconds; + unsigned char *m_visBuffer; + qint64 m_visBufferSize; + QmmpSettings *m_settings; + Output *m_output; + +}; + +#endif // OUTPUTWRITER_P_H diff --git a/src/qmmp/qmmp.pro b/src/qmmp/qmmp.pro index 549156c79..c31cb2761 100644 --- a/src/qmmp/qmmp.pro +++ b/src/qmmp/qmmp.pro @@ -35,7 +35,8 @@ HEADERS += \ qmmpevents_p.h \ volume.h \ volumecontrol_p.h \ - recycler.h + recycler.h \ + outputwriter_p.h SOURCES += recycler.cpp \ decoder.cpp \ output.cpp \ @@ -62,7 +63,8 @@ SOURCES += recycler.cpp \ audioconverter.cpp \ qmmpsettings.cpp \ eqsettings.cpp \ - qmmpevents.cpp + qmmpevents.cpp \ + outputwriter.cpp FORMS += unix:TARGET = ../../lib/qmmp win32:TARGET = ../../../bin/qmmp @@ -122,3 +124,5 @@ INCLUDEPATH += ./ + + diff --git a/src/qmmp/qmmpaudioengine.cpp b/src/qmmp/qmmpaudioengine.cpp index ff4f49ca1..5c06bdad5 100644 --- a/src/qmmp/qmmpaudioengine.cpp +++ b/src/qmmp/qmmpaudioengine.cpp @@ -25,10 +25,11 @@ #include "effect.h" #include "buffer.h" #include "decoder.h" -#include "output.h" +#include "outputwriter_p.h" #include "decoderfactory.h" #include "effectfactory.h" #include "inputsource.h" +#include "statehandler.h" #include "audioconverter_p.h" #include "qmmpaudioengine_p.h" #include "metadatamanager.h" @@ -521,15 +522,15 @@ void QmmpAudioEngine::sendMetaData() } } -Output *QmmpAudioEngine::createOutput() +OutputWriter *QmmpAudioEngine::createOutput() { - Output *output = Output::create(0); - if(!output) + OutputWriter *output = new OutputWriter(this); + /*if(!output) { qWarning("QmmpAudioEngine: unable to create output"); StateHandler::instance()->dispatch(Qmmp::FatalError); return 0; - } + }*/ if (!output->initialize(m_ap.sampleRate(), m_ap.channels(), m_ap.format()) || output->audioParameters() != m_ap) //TODO add soundconverter { diff --git a/src/qmmp/qmmpaudioengine_p.h b/src/qmmp/qmmpaudioengine_p.h index d8023b799..52731027b 100644 --- a/src/qmmp/qmmpaudioengine_p.h +++ b/src/qmmp/qmmpaudioengine_p.h @@ -27,7 +27,7 @@ #include "audioparameters.h" class QIODevice; -class Output; +class OutputWriter; class Effect; class DecoderFactory; class StateHandler; @@ -69,13 +69,13 @@ private: void addOffset(); qint64 produceSound(char *data, qint64 size, quint32 brate); void sendMetaData(); - Output *createOutput(); + OutputWriter *createOutput(); void prepareEffects(Decoder *d); DecoderFactory *m_factory; QList <Effect*> m_effects; QList <Effect*> m_blockedEffects; - Output *m_output; + OutputWriter *m_output; bool m_done, m_finish, m_user_stop; uint m_bks; diff --git a/src/qmmp/recycler.h b/src/qmmp/recycler.h index fc143779d..222b3886f 100644 --- a/src/qmmp/recycler.h +++ b/src/qmmp/recycler.h @@ -10,8 +10,7 @@ #include <QMutex> #include <QWaitCondition> #include "qmmp.h" - -class Buffer; +#include "buffer.h" /*! @brief The Recycler class provides a queue of audio buffers. * @author Brad Hughes <bhughes@trolltech.com> |
