aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2012-12-07 18:45:38 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2012-12-07 18:45:38 +0000
commit8bded202c7204ad3f655030078c74c17fd121122 (patch)
tree56d9172d0f856e0ce4abac146c14238194cd74a7
parentcbb5689bad0caedcedd9d0366adde5d06b87989e (diff)
downloadqmmp-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
-rw-r--r--src/plugins/Output/alsa/outputalsa.cpp7
-rw-r--r--src/plugins/Output/alsa/outputalsa.h10
-rw-r--r--src/plugins/Output/alsa/outputalsafactory.cpp4
-rw-r--r--src/plugins/Output/alsa/outputalsafactory.h2
-rw-r--r--src/plugins/Output/jack/outputjack.cpp2
-rw-r--r--src/plugins/Output/jack/outputjack.h10
-rw-r--r--src/plugins/Output/jack/outputjackfactory.cpp4
-rw-r--r--src/plugins/Output/jack/outputjackfactory.h2
-rw-r--r--src/plugins/Output/null/outputnull.cpp2
-rw-r--r--src/plugins/Output/null/outputnull.h10
-rw-r--r--src/plugins/Output/null/outputnullfactory.cpp4
-rw-r--r--src/plugins/Output/null/outputnullfactory.h2
-rw-r--r--src/plugins/Output/oss/outputoss.cpp2
-rw-r--r--src/plugins/Output/oss/outputoss.h11
-rw-r--r--src/plugins/Output/oss/outputossfactory.cpp6
-rw-r--r--src/plugins/Output/oss/outputossfactory.h2
-rw-r--r--src/plugins/Output/oss4/outputoss4.cpp4
-rw-r--r--src/plugins/Output/oss4/outputoss4.h12
-rw-r--r--src/plugins/Output/oss4/outputoss4factory.cpp4
-rw-r--r--src/plugins/Output/oss4/outputoss4factory.h2
-rw-r--r--src/plugins/Output/pulseaudio/outputpulseaudio.cpp3
-rw-r--r--src/plugins/Output/pulseaudio/outputpulseaudio.h8
-rw-r--r--src/plugins/Output/pulseaudio/outputpulseaudiofactory.cpp4
-rw-r--r--src/plugins/Output/pulseaudio/outputpulseaudiofactory.h2
-rw-r--r--src/plugins/Output/waveout/outputwaveout.cpp10
-rw-r--r--src/plugins/Output/waveout/outputwaveout.h10
-rw-r--r--src/plugins/Output/waveout/outputwaveoutfactory.cpp4
-rw-r--r--src/plugins/Output/waveout/outputwaveoutfactory.h2
-rw-r--r--src/qmmp/output.cpp352
-rw-r--r--src/qmmp/output.h100
-rw-r--r--src/qmmp/outputfactory.h5
-rw-r--r--src/qmmp/outputwriter.cpp419
-rw-r--r--src/qmmp/outputwriter_p.h133
-rw-r--r--src/qmmp/qmmp.pro8
-rw-r--r--src/qmmp/qmmpaudioengine.cpp11
-rw-r--r--src/qmmp/qmmpaudioengine_p.h6
-rw-r--r--src/qmmp/recycler.h3
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>