diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2014-02-14 11:34:05 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2014-02-14 11:34:05 +0000 |
| commit | 68c87d72dd28b523a09f661264837f4aa3e7025d (patch) | |
| tree | 2c84d264a3d34ff39cb4d66407bcd8f3042a51f7 | |
| parent | 1c04cf0a921cb403862778cd694adb9ecfddb28b (diff) | |
| download | qmmp-68c87d72dd28b523a09f661264837f4aa3e7025d.tar.gz qmmp-68c87d72dd28b523a09f661264837f4aa3e7025d.tar.bz2 qmmp-68c87d72dd28b523a09f661264837f4aa3e7025d.zip | |
added directsound plugin
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@4089 90c681e8-e032-0410-971d-27865f9a5e38
| -rw-r--r-- | src/plugins/Output/Output.pro | 1 | ||||
| -rw-r--r-- | src/plugins/Output/directsound/directsound.pro | 46 | ||||
| -rw-r--r-- | src/plugins/Output/directsound/outputdirectsound.cpp | 264 | ||||
| -rw-r--r-- | src/plugins/Output/directsound/outputdirectsound.h | 73 | ||||
| -rw-r--r-- | src/plugins/Output/directsound/outputdirectsoundfactory.cpp | 66 | ||||
| -rw-r--r-- | src/plugins/Output/directsound/outputdirectsoundfactory.h | 45 |
6 files changed, 495 insertions, 0 deletions
diff --git a/src/plugins/Output/Output.pro b/src/plugins/Output/Output.pro index c17adbeac..d07513257 100644 --- a/src/plugins/Output/Output.pro +++ b/src/plugins/Output/Output.pro @@ -2,6 +2,7 @@ include(../../../qmmp.pri) TEMPLATE = subdirs win32:SUBDIRS += waveout +win32:SUBDIRS += directsound SUBDIRS += null diff --git a/src/plugins/Output/directsound/directsound.pro b/src/plugins/Output/directsound/directsound.pro new file mode 100644 index 000000000..71ea2bfbc --- /dev/null +++ b/src/plugins/Output/directsound/directsound.pro @@ -0,0 +1,46 @@ +include(../../plugins.pri) + +HEADERS += outputdirectsoundfactory.h \ + outputdirectsound.h + +SOURCES += outputdirectsoundfactory.cpp \ + outputdirectsound.cpp + +HEADERS += ../../../../src/qmmp/output.h + + +TARGET=$$PLUGINS_PREFIX/Output/directsound + +INCLUDEPATH += ../../../ +QMAKE_LIBDIR += ../../../../bin + +CONFIG += warn_on \ +thread \ +plugin + +TEMPLATE = lib +LIBS += -lqmmp0 -ldxguid -lstrmiids -ldmoguids -lmsdmo -lole32 -loleaut32 -luuid -lgdi32 -ldsound + +TRANSLATIONS = translations/directsound_plugin_cs.ts \ + translations/directsound_plugin_de.ts \ + translations/directsound_plugin_zh_CN.ts \ + translations/directsound_plugin_zh_TW.ts \ + translations/directsound_plugin_ru.ts \ + translations/directsound_plugin_pl.ts \ + translations/directsound_plugin_uk_UA.ts \ + translations/directsound_plugin_it.ts \ + translations/directsound_plugin_tr.ts \ + translations/directsound_plugin_lt.ts \ + translations/directsound_plugin_nl.ts \ + translations/directsound_plugin_ja.ts \ + translations/directsound_plugin_es.ts \ + translations/directsound_plugin_sr_BA.ts \ + translations/directsound_plugin_sr_RS.ts +#RESOURCES = translations/translations.qrc + +isEmpty (LIB_DIR){ +LIB_DIR = /lib +} + +target.path = $$LIB_DIR/qmmp/Output +INSTALLS += target diff --git a/src/plugins/Output/directsound/outputdirectsound.cpp b/src/plugins/Output/directsound/outputdirectsound.cpp new file mode 100644 index 000000000..feaa2cf08 --- /dev/null +++ b/src/plugins/Output/directsound/outputdirectsound.cpp @@ -0,0 +1,264 @@ +/***************************************************************************
+ * Copyright (C) 2014 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 <QObject>
+#include <string.h>
+#include <iostream>
+#include <unistd.h>
+#include <qmmp/buffer.h>
+#include <qmmp/visual.h>
+#include "outputdirectsound.h"
+
+#define DS_BUFSIZE (48*1024)
+
+OutputDirectSound::OutputDirectSound() : Output()
+{
+ m_ds = 0;
+ m_primaryBuffer = 0;
+ m_dsBuffer = 0;
+ m_dsBufferAt = 0;
+}
+
+OutputDirectSound::~OutputDirectSound()
+{
+ uninitialize();
+}
+
+bool OutputDirectSound::initialize(quint32 freq, int chan, Qmmp::AudioFormat format)
+{
+ Q_UNUSED(format);
+ DSBUFFERDESC bufferDesc;
+
+ HRESULT result = DirectSoundCreate8(0, &m_ds, 0);
+ if(result != DS_OK)
+ {
+ qWarning("OutputDirectSound: DirectSoundCreate8 failed, error code = 0x%lx", result);
+ m_ds = 0;
+ return false;
+ }
+
+ if((result = m_ds->SetCooperativeLevel(GetDesktopWindow(), DSSCL_PRIORITY)) != DS_OK)
+ {
+ qWarning("OutputDirectSound: SetCooperativeLevel failed, error code = 0x%lx", result);
+ return false;
+ }
+
+ ZeroMemory(&bufferDesc, sizeof(DSBUFFERDESC));
+ bufferDesc.dwSize = sizeof(DSBUFFERDESC);
+ bufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
+ bufferDesc.dwBufferBytes = 0;
+ bufferDesc.lpwfxFormat = NULL;
+
+ if((result = m_ds->CreateSoundBuffer(&bufferDesc, &m_primaryBuffer, NULL)) != DS_OK)
+ {
+ m_primaryBuffer = 0;
+ qWarning("OutputDirectSound: CreateSoundBuffer failed, error code = 0x%lx", result);
+ return false;
+ }
+
+ WAVEFORMATEX wfex;
+ ZeroMemory(&wfex, sizeof(WAVEFORMATEX));
+ wfex.wFormatTag = WAVE_FORMAT_PCM;
+ wfex.nChannels = chan;
+ wfex.nSamplesPerSec = freq;
+ wfex.wBitsPerSample = 16;
+ wfex.nBlockAlign = (wfex.wBitsPerSample / 8) * wfex.nChannels;
+ wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;
+
+ if((result = m_primaryBuffer->SetFormat(&wfex)) != DS_OK)
+ {
+ qWarning("OutputDirectSound: SetFormat failed, error code = 0x%lx", result);
+ return false;
+ }
+
+ if((result = m_primaryBuffer->Play(0, 0, DSBPLAY_LOOPING)) != DS_OK)
+ {
+ qWarning("OutputDirectSound: Play failed, error code = 0x%lx", result);
+ return false;
+ }
+
+ ZeroMemory(&wfex, sizeof(WAVEFORMATEX));
+ wfex.wFormatTag = WAVE_FORMAT_PCM;
+ wfex.nChannels = chan;
+ wfex.nSamplesPerSec = freq;
+ wfex.wBitsPerSample = 16;
+ wfex.nBlockAlign = (wfex.wBitsPerSample / 8) * wfex.nChannels;
+ wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;
+
+ ZeroMemory(&bufferDesc, sizeof(DSBUFFERDESC));
+ bufferDesc.dwSize = sizeof(DSBUFFERDESC);
+ bufferDesc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN |
+ DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;
+ bufferDesc.lpwfxFormat = &wfex;
+ bufferDesc.dwBufferBytes = DS_BUFSIZE; // buffer size
+
+ IDirectSoundBuffer *pDSB;
+ if((result = m_ds->CreateSoundBuffer(&bufferDesc, &pDSB, NULL)) != DS_OK)
+ {
+ qWarning("OutputDirectSound: CreateSoundBuffer failed, error code = 0x%lx", result);
+ return false;
+ }
+
+ if((result = pDSB->QueryInterface(IID_IDirectSoundBuffer8, (void**)&m_dsBuffer)) != DS_OK)
+ {
+ m_dsBuffer = 0;
+ qWarning("OutputDirectSound: QueryInterface failed, error code = 0x%lx", result);
+ pDSB->Release();
+ return false;
+ }
+
+ m_dsBuffer->SetCurrentPosition(0);
+ m_dsBuffer->Play(0,0,DSBPLAY_LOOPING);
+ m_dsBufferAt = 0;
+ configure(freq, chan, Qmmp::PCM_S16LE);
+ return true;
+}
+
+
+qint64 OutputDirectSound::latency()
+{
+ return 0;
+}
+
+qint64 OutputDirectSound::writeAudio(unsigned char *data, qint64 len)
+{
+ unsigned char *ptr = 0, *ptr2 = 0;
+ DWORD size = 0, size2 = 0;
+
+ DWORD available = bytesToWrite(); //available bytes
+ if(available < 128)
+ {
+ usleep(5000);
+ return 0;
+ }
+ DWORD lockSize = qMin((DWORD)len, available); //required size
+
+ HRESULT result = m_dsBuffer->Lock(m_dsBufferAt, lockSize,
+ (void**)&ptr, (DWORD*)&size,
+ (void**)&ptr2, (DWORD*)&size2, 0);
+ if(result == DSERR_BUFFERLOST)
+ {
+ m_dsBuffer->Restore();
+ result = m_dsBuffer->Lock(m_dsBufferAt, lockSize,
+ (void**)&ptr, (DWORD*)&size,
+ (void**)&ptr2, (DWORD*)&size2, 0);
+ }
+ if(result != DS_OK)
+ {
+ qWarning("OutputDirectSound: unable to lock buffer, error = 0x%lx", result);
+ return -1;
+ }
+
+ DWORD totalSize = size + size2; //total locked size
+ memmove(ptr, data, size);
+ if(size2 > 0)
+ memmove(ptr2, data + size, size2);
+
+ m_dsBuffer->Unlock((void*)ptr, size, (void*)ptr2, size2);
+
+ m_dsBufferAt += totalSize;
+ m_dsBufferAt %= DS_BUFSIZE;
+ return totalSize;
+}
+
+void OutputDirectSound::drain()
+{
+ DWORD dsCurrentPlayCursor = 0;
+ m_dsBuffer->GetCurrentPosition((DWORD*)&dsCurrentPlayCursor, 0);
+
+ while(dsCurrentPlayCursor >= m_dsBufferAt)
+ {
+ m_dsBuffer->GetCurrentPosition((DWORD*)&dsCurrentPlayCursor, 0);
+ }
+ while (dsCurrentPlayCursor <= m_dsBufferAt)
+ {
+ m_dsBuffer->GetCurrentPosition((DWORD*)&dsCurrentPlayCursor, 0);
+ }
+}
+
+void OutputDirectSound::suspend()
+{
+ m_dsBuffer->Stop();
+}
+
+void OutputDirectSound::resume()
+{
+ HRESULT result = m_dsBuffer->Play(0,0,DSBPLAY_LOOPING);
+ if(result == DSERR_BUFFERLOST)
+ {
+ result = m_dsBuffer->Play(0,0,DSBPLAY_LOOPING);
+ m_dsBuffer->Restore();
+ }
+}
+
+void OutputDirectSound::reset()
+{
+ m_dsBuffer->SetCurrentPosition(m_dsBufferAt-128);
+}
+
+void OutputDirectSound::uninitialize()
+{
+ m_dsBufferAt = 0;
+ if(m_dsBuffer)
+ {
+ m_dsBuffer->Stop();
+ m_dsBuffer->Release();
+ m_dsBuffer = 0;
+ }
+ if(m_primaryBuffer)
+ {
+ m_primaryBuffer->Stop();
+ m_primaryBuffer->Release();
+ m_primaryBuffer = 0;
+ }
+ if(m_ds)
+ {
+ m_ds->Release();
+ m_ds = 0;
+ }
+}
+
+DWORD OutputDirectSound::bytesToWrite()
+{
+ DWORD dsCurrentPlayCursor = 0;
+ m_dsBuffer->GetCurrentPosition((DWORD*)&dsCurrentPlayCursor, 0);
+ long available = dsCurrentPlayCursor - m_dsBufferAt; //available bytes
+
+ if(available < 0)
+ {
+ available += DS_BUFSIZE;
+ }
+ return available;
+}
+
+/***** MIXER *****/
+VolumeDirectSound::VolumeDirectSound()
+{}
+
+VolumeDirectSound::~VolumeDirectSound()
+{}
+
+void VolumeDirectSound::setVolume(const VolumeSettings &vol)
+{
+}
+
+VolumeSettings VolumeDirectSound::volume() const
+{
+}
diff --git a/src/plugins/Output/directsound/outputdirectsound.h b/src/plugins/Output/directsound/outputdirectsound.h new file mode 100644 index 000000000..c78d88fb4 --- /dev/null +++ b/src/plugins/Output/directsound/outputdirectsound.h @@ -0,0 +1,73 @@ +/***************************************************************************
+ * Copyright (C) 2014 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 OUTPUTDIRECTSOUND_H
+#define OUTPUTDIRECTSOUND_H
+
+#include <stdio.h>
+#include <windows.h>
+#include <initguid.h>
+#include <dsound.h>
+#include <qmmp/volume.h>
+#include <qmmp/output.h>
+
+/**
+ @author Ilya Kotov <forkotov02@hotmail.ru>
+*/
+class OutputDirectSound : public Output
+{
+public:
+ OutputDirectSound();
+ ~OutputDirectSound();
+
+ bool initialize(quint32, int, Qmmp::AudioFormat format);
+
+ //output api
+ qint64 latency();
+ qint64 writeAudio(unsigned char *data, qint64 size);
+ void drain();
+ void suspend();
+ void resume();
+ void reset();
+
+private:
+ // helper functions
+ void status();
+ void uninitialize();
+ DWORD bytesToWrite();
+
+ IDirectSound8 *m_ds;
+ IDirectSoundBuffer *m_primaryBuffer;
+ IDirectSoundBuffer8 *m_dsBuffer;
+ DWORD m_dsBufferAt;
+};
+
+class VolumeDirectSound : public Volume
+{
+public:
+ VolumeDirectSound();
+ ~VolumeDirectSound();
+
+ void setVolume(const VolumeSettings &vol);
+ VolumeSettings volume() const;
+};
+
+
+#endif // OUTPUTDIRECTSOUND_H
diff --git a/src/plugins/Output/directsound/outputdirectsoundfactory.cpp b/src/plugins/Output/directsound/outputdirectsoundfactory.cpp new file mode 100644 index 000000000..3238b8ff8 --- /dev/null +++ b/src/plugins/Output/directsound/outputdirectsoundfactory.cpp @@ -0,0 +1,66 @@ +/***************************************************************************
+ * Copyright (C) 2014 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 <QtGui>
+#include "outputdirectsound.h"
+#include "outputdirectsoundfactory.h"
+
+
+const OutputProperties OutputDirectSoundFactory::properties() const
+{
+ OutputProperties properties;
+ properties.name = tr("DirectSound Plugin");
+ properties.hasAbout = true;
+ properties.hasSettings = false;
+ properties.shortName = "directsound";
+ return properties;
+}
+
+Output* OutputDirectSoundFactory::create()
+{
+ return new OutputDirectSound();
+}
+
+Volume *OutputDirectSoundFactory::createVolume()
+{
+ return new VolumeDirectSound();
+}
+
+void OutputDirectSoundFactory::showSettings(QWidget* parent)
+{
+ Q_UNUSED(parent);
+}
+
+void OutputDirectSoundFactory::showAbout(QWidget *parent)
+{
+ QMessageBox::about (parent, tr("About DirectSound Output Plugin"),
+ tr("Qmmp DirectSound Output Plugin")+"\n"+
+ tr("Written by: Ilya Kotov <forkotov02@hotmail.ru>"));
+}
+
+QTranslator *OutputDirectSoundFactory::createTranslator(QObject *parent)
+{
+ QTranslator *translator = new QTranslator(parent);
+ QString locale = Qmmp::systemLanguageID();
+ translator->load(QString(":/directsound_plugin_") + locale);
+ return translator;
+}
+
+Q_EXPORT_PLUGIN2(directsound,OutputDirectSoundFactory)
diff --git a/src/plugins/Output/directsound/outputdirectsoundfactory.h b/src/plugins/Output/directsound/outputdirectsoundfactory.h new file mode 100644 index 000000000..57fef18b3 --- /dev/null +++ b/src/plugins/Output/directsound/outputdirectsoundfactory.h @@ -0,0 +1,45 @@ +/***************************************************************************
+ * Copyright (C) 2014 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 OUTPUTDIRECTSOUNDFACTORY_H
+#define OUTPUTDIRECTSOUNDFACTORY_H
+
+#include <QObject>
+#include <QString>
+#include <QIODevice>
+#include <QWidget>
+#include <qmmp/output.h>
+#include <qmmp/outputfactory.h>
+
+
+class OutputDirectSoundFactory : public QObject, OutputFactory
+{
+Q_OBJECT
+Q_INTERFACES(OutputFactory)
+
+public:
+ const OutputProperties properties() const;
+ Output* create();
+ Volume *createVolume();
+ void showSettings(QWidget* parent);
+ void showAbout(QWidget *parent);
+ QTranslator *createTranslator(QObject *parent);
+};
+
+#endif
|
