aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Output/qtmultimedia/outputqtmultimedia.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/Output/qtmultimedia/outputqtmultimedia.cpp')
-rw-r--r--src/plugins/Output/qtmultimedia/outputqtmultimedia.cpp184
1 files changed, 98 insertions, 86 deletions
diff --git a/src/plugins/Output/qtmultimedia/outputqtmultimedia.cpp b/src/plugins/Output/qtmultimedia/outputqtmultimedia.cpp
index 1f39ecc60..7de68b081 100644
--- a/src/plugins/Output/qtmultimedia/outputqtmultimedia.cpp
+++ b/src/plugins/Output/qtmultimedia/outputqtmultimedia.cpp
@@ -19,7 +19,8 @@
***************************************************************************/
#include "outputqtmultimedia.h"
-
+#include <qmmp/audioparameters.h>
+#include <QMetaObject>
#include <QAudioOutput>
#include <QAudioFormat>
#include <QAudioDeviceInfo>
@@ -38,114 +39,125 @@ OutputQtMultimedia::~OutputQtMultimedia()
bool OutputQtMultimedia::initialize(quint32 freq, ChannelMap map, Qmmp::AudioFormat format)
{
- QAudioFormat qformat;
- qformat.setCodec("audio/pcm");
- qformat.setFrequency(freq);
- qformat.setByteOrder(QAudioFormat::LittleEndian);
- qformat.setChannels(map.size());
- qformat.setSampleType(QAudioFormat::SignedInt);
-
- //Size of sample representation in input data. For 24-bit is 4, high byte is ignored.
- qint64 bytes_per_sample = 0;
-
- switch (format)
- {
- case Qmmp::PCM_S8:
- qformat.setSampleSize(8);
- bytes_per_sample = 1;
- break;
- case Qmmp::PCM_S16LE:
- qformat.setSampleSize(16);
- bytes_per_sample = 2;
- break;
- case Qmmp::PCM_S24LE:
- qformat.setSampleSize(24);
- bytes_per_sample = 4;
- break;
- case Qmmp::PCM_S32LE:
- qformat.setSampleSize(32);
- bytes_per_sample = 4;
- break;
- default:
- break;
- }
-
- if (!qformat.isValid())
- return false;
-
- m_bytes_per_second = bytes_per_sample * freq * qformat.channels();
-
- const QSettings settings(Qmmp::configFile(), QSettings::IniFormat);
- const QString saved_device_name = settings.value("QTMULTIMEDIA/device").toString();
-
- QAudioDeviceInfo device_info;
- if (!saved_device_name.isEmpty())
- {
- const QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
- foreach (const QAudioDeviceInfo &info, devices)
- {
- if (info.deviceName()==saved_device_name)
- {
- if (info.isFormatSupported(qformat))
- {
- device_info = info;
- break;
- }
- else
- qDebug() << "OutputQtMultimedia: Output device: " << saved_device_name << " is not supported";
- }
- }
- }
-
- if (device_info.isNull())
- {
- device_info = QAudioDeviceInfo::defaultOutputDevice();
- if (!device_info.isFormatSupported(qformat))
- return false;
- }
-
- qDebug() << "OutputQtMultimedia: Using output device: " << device_info.deviceName();
-
- m_output.reset(new QAudioOutput(device_info, qformat));
- m_buffer = m_output->start();
-
- configure(freq, map, format);
- return true;
+ QAudioFormat qformat;
+ qformat.setCodec("audio/pcm");
+ qformat.setSampleRate(freq);
+ qformat.setByteOrder(QAudioFormat::LittleEndian);
+ qformat.setChannelCount(map.size());
+ qformat.setSampleType(QAudioFormat::SignedInt);
+
+ //Size of sample representation in input data. For 24-bit is 4, high byte is ignored.
+ qint64 bytes_per_sample = AudioParameters::sampleSize(format);
+
+ switch (format)
+ {
+ case Qmmp::PCM_S8:
+ qformat.setSampleSize(8);
+ break;
+ case Qmmp::PCM_S16LE:
+ qformat.setSampleSize(16);
+ break;
+ case Qmmp::PCM_S24LE:
+ qformat.setSampleSize(24);
+ break;
+ case Qmmp::PCM_S32LE:
+ qformat.setSampleSize(32);
+ break;
+ default:
+ break;
+ }
+
+ if (!qformat.isValid())
+ return false;
+
+ const QSettings settings(Qmmp::configFile(), QSettings::IniFormat);
+ const QString saved_device_name = settings.value("QTMULTIMEDIA/device").toString();
+
+ m_bytes_per_second = bytes_per_sample * freq * qformat.channelCount();
+
+ QAudioDeviceInfo device_info;
+ if (!saved_device_name.isEmpty())
+ {
+ const QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
+ foreach (const QAudioDeviceInfo &info, devices)
+ {
+ if (info.deviceName()==saved_device_name)
+ {
+ if (info.isFormatSupported(qformat))
+ {
+ device_info = info;
+ break;
+ }
+ else
+ qDebug() << "OutputQtMultimedia: Output device: " << saved_device_name << " is not supported";
+ }
+ }
+ }
+
+ if (device_info.isNull())
+ {
+ device_info = QAudioDeviceInfo::defaultOutputDevice();
+ if (!device_info.isFormatSupported(qformat))
+ return false;
+ }
+
+ qDebug() << "OutputQtMultimedia: Using output device: " << device_info.deviceName();
+
+ m_output.reset(new QAudioOutput(device_info, qformat));
+ m_buffer = m_output->start();
+ m_control.reset(new OutputControl(m_output.data()));
+
+ configure(freq, map, format);
+ return true;
}
qint64 OutputQtMultimedia::latency()
{
- return 0;
+ return 0;
}
qint64 OutputQtMultimedia::writeAudio(unsigned char *data, qint64 maxSize)
{
- if (!m_output->bytesFree()) {
- //If the buffer is full, waiting for some bytes to be played:
- //trying to play maxSize bytes, but not more than half of buffer.
- usleep(qMin(maxSize, static_cast<qint64>(m_output->bufferSize() / 2)) * 1000000 / m_bytes_per_second);
- }
- return m_buffer->write((const char*)data, maxSize);
+ if (!m_output->bytesFree()) {
+ //If the buffer is full, waiting for some bytes to be played:
+ //trying to play maxSize bytes, but not more than half of buffer.
+ usleep(qMin(maxSize, static_cast<qint64>(m_output->bufferSize() / 2)) * 1000000 / m_bytes_per_second);
+ }
+ return m_buffer->write((const char*)data, maxSize);
}
void OutputQtMultimedia::drain()
{
- m_buffer->waitForBytesWritten(-1);
+ m_buffer->waitForBytesWritten(-1);
}
void OutputQtMultimedia::reset()
{
- m_buffer->reset();
- m_buffer = m_output->start();
+ m_buffer->reset();
}
void OutputQtMultimedia::suspend()
{
- m_output->suspend();
+ QMetaObject::invokeMethod(m_control.data(), "suspend", Qt::QueuedConnection);
}
void OutputQtMultimedia::resume()
{
- m_output->resume();
+ QMetaObject::invokeMethod(m_control.data(), "resume", Qt::QueuedConnection);
+}
+
+OutputControl::OutputControl(QAudioOutput *o)
+{
+ m_output = o;
+}
+
+void OutputControl::suspend()
+{
+ m_output->suspend();
+}
+
+void OutputControl::resume()
+{
+ m_output->resume();
}