aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/Output/oss/outputoss.cpp306
1 files changed, 169 insertions, 137 deletions
diff --git a/src/plugins/Output/oss/outputoss.cpp b/src/plugins/Output/oss/outputoss.cpp
index 9dfcadbbd..51e36e90f 100644
--- a/src/plugins/Output/oss/outputoss.cpp
+++ b/src/plugins/Output/oss/outputoss.cpp
@@ -20,6 +20,14 @@
***************************************************************************/
#include <QApplication>
+extern "C"
+{
+#ifdef HAVE_SYS_SOUNDCARD_H
+#include <sys/soundcard.h>
+#else
+#include <soundcard.h>
+#endif
+}
#include "outputoss.h"
#include <qmmp/constants.h>
@@ -88,70 +96,72 @@ void OutputOSS::seek(long pos)
OutputOSS::OutputOSS(QObject * parent)
- : Output(parent), m_inited(FALSE), m_pause(FALSE), m_play(FALSE),
- m_userStop(FALSE),
- m_totalWritten(0), m_currentSeconds(-1),
- m_bps(1), m_frequency(-1), m_channels(-1), m_precision(-1),
- do_select(TRUE),
- m_audio_fd(-1), m_mixer_fd(-1)
+ : Output(parent), m_inited(FALSE), m_pause(FALSE), m_play(FALSE),
+ m_userStop(FALSE),
+ m_totalWritten(0), m_currentSeconds(-1),
+ m_bps(1), m_frequency(-1), m_channels(-1), m_precision(-1),
+ do_select(TRUE),
+ m_audio_fd(-1), m_mixer_fd(-1)
{
-QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
-m_master = true;
-m_audio_device = settings.value("OSS/device","/dev/dsp").toString();
-m_mixer_device = settings.value("OSS/mixer_device","/dev/mixer").toString();
-openMixer();
+ QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat);
+ m_master = true;
+ m_audio_device = settings.value("OSS/device","/dev/dsp").toString();
+ m_mixer_device = settings.value("OSS/mixer_device","/dev/mixer").toString();
+ openMixer();
}
OutputOSS::~OutputOSS()
{
if (m_audio_fd > 0)
{
- close(m_audio_fd);
- m_audio_fd = -1;
+ close(m_audio_fd);
+ m_audio_fd = -1;
}
if (m_mixer_fd > 0)
{
- close(m_mixer_fd);
- m_mixer_fd = -1;
+ close(m_mixer_fd);
+ m_mixer_fd = -1;
}
}
void OutputOSS::configure(long freq, int chan, int prec, int rate)
{
// we need to configure
- if (freq != m_frequency || chan != m_channels || prec != m_precision) {
- // we have already configured, but are changing settings...
- // reset the device
- resetDSP();
+ if (freq != m_frequency || chan != m_channels || prec != m_precision)
+ {
+ // we have already configured, but are changing settings...
+ // reset the device
+ resetDSP();
- m_frequency = freq;
- m_channels = chan;
- m_precision = prec;
+ m_frequency = freq;
+ m_channels = chan;
+ m_precision = prec;
- m_bps = freq * chan * (prec / 8);
+ m_bps = freq * chan * (prec / 8);
- int p;
- switch(prec) {
- default:
- case 16:
+ int p;
+ switch (prec)
+ {
+ default:
+ case 16:
#if defined(AFMT_S16_NE)
- p = AFMT_S16_NE;
+ p = AFMT_S16_NE;
#else
- p = AFMT_S16_LE;
+ p = AFMT_S16_LE;
#endif
- break;
+ break;
- case 8:
- p = AFMT_S8;
- break;
+ case 8:
+ p = AFMT_S8;
+ break;
- }
+ }
- ioctl(m_audio_fd, SNDCTL_DSP_SETFMT, &p);
- ioctl(m_audio_fd, SNDCTL_DSP_SAMPLESIZE, &prec);
- int stereo = (chan > 1) ? 1 : 0;
- ioctl(m_audio_fd, SNDCTL_DSP_STEREO, &stereo);
- ioctl(m_audio_fd, SNDCTL_DSP_SPEED, &freq);
+ ioctl(m_audio_fd, SNDCTL_DSP_SETFMT, &p);
+ ioctl(m_audio_fd, SNDCTL_DSP_SAMPLESIZE, &prec);
+ int stereo = (chan > 1) ? 1 : 0;
+ ioctl(m_audio_fd, SNDCTL_DSP_STEREO, &stereo);
+ ioctl(m_audio_fd, SNDCTL_DSP_SPEED, &freq);
}
m_rate = rate;
@@ -162,24 +172,24 @@ void OutputOSS::reset()
{
if (m_audio_fd > 0)
{
- close(m_audio_fd);
- m_audio_fd = -1;
+ close(m_audio_fd);
+ m_audio_fd = -1;
}
m_audio_fd = open(m_audio_device.toAscii(), O_WRONLY, 0);
if (m_audio_fd < 0)
{
- error(QString("OSSOutput: failed to open output device '%1'").
- arg(m_audio_device));
- return;
+ error(QString("OSSOutput: failed to open output device '%1'").
+ arg(m_audio_device));
+ return;
}
int flags;
if ((flags = fcntl(m_audio_fd, F_GETFL, 0)) > 0)
{
- flags &= O_NDELAY;
- fcntl(m_audio_fd, F_SETFL, flags);
+ flags &= O_NDELAY;
+ fcntl(m_audio_fd, F_SETFL, flags);
}
fd_set afd;
@@ -192,14 +202,15 @@ void OutputOSS::reset()
if (m_audio_fd > 0)
{
- close(m_mixer_fd);
- m_mixer_fd = -1;
+ close(m_mixer_fd);
+ m_mixer_fd = -1;
}
openMixer();
}
void OutputOSS::openMixer()
{
+#if SOUND_VERSION < 0x040000
if (m_mixer_fd != -1)
return;
@@ -209,21 +220,24 @@ void OutputOSS::openMixer()
}
if (m_audio_fd < 0)
{
- error(QString("OSSOutput: failed to open mixer device '%1'").
- arg(m_mixer_device));
- return;
+ error(QString("OSSOutput: failed to open mixer device '%1'").
+ arg(m_mixer_device));
+ return;
}
+#endif
}
void OutputOSS::pause()
{
- m_pause = (m_pause) ? FALSE : TRUE;
+ m_pause = !m_pause;
+ OutputState::Type state = m_pause ? OutputState::Paused: OutputState::Playing;
+ dispatch(state);
}
void OutputOSS::post()
{
if (m_audio_fd < 1)
- return;
+ return;
int unused;
ioctl(m_audio_fd, SNDCTL_DSP_POST, &unused);
@@ -232,7 +246,7 @@ void OutputOSS::post()
void OutputOSS::sync()
{
if (m_audio_fd < 1)
- return;
+ return;
int unused;
ioctl(m_audio_fd, SNDCTL_DSP_SYNC, &unused);
@@ -242,7 +256,7 @@ void OutputOSS::sync()
void OutputOSS::resetDSP()
{
if (m_audio_fd < 1)
- return;
+ return;
int unused;
ioctl(m_audio_fd, SNDCTL_DSP_RESET, &unused);
@@ -256,11 +270,11 @@ bool OutputOSS::initialize()
reset();
if (m_audio_fd < 0)
- return FALSE;
+ return FALSE;
if (m_mixer_fd < 0)
- return FALSE;
+ return FALSE;
+
-
m_currentSeconds = -1;
m_totalWritten = 0;
stat = OutputState::Stopped;
@@ -286,13 +300,13 @@ void OutputOSS::uninitialize()
resetDSP();
if (m_audio_fd > 0)
{
- close(m_audio_fd);
- m_audio_fd = -1;
+ close(m_audio_fd);
+ m_audio_fd = -1;
}
if (m_audio_fd > 0)
{
- close(m_mixer_fd);
- m_mixer_fd = -1;
+ close(m_mixer_fd);
+ m_mixer_fd = -1;
}
qDebug("OutputOSS: uninitialize");
@@ -305,8 +319,8 @@ long OutputOSS::latency()
if (! m_pause)
{
- if (ioctl(m_audio_fd, SNDCTL_DSP_GETODELAY, &used) == -1)
- used = 0;
+ if (ioctl(m_audio_fd, SNDCTL_DSP_GETODELAY, &used) == -1)
+ used = 0;
}
return used;
@@ -318,9 +332,9 @@ void OutputOSS::run()
if (! m_inited)
{
- mutex()->unlock();
+ mutex()->unlock();
- return;
+ return;
}
m_play = TRUE;
@@ -337,82 +351,86 @@ void OutputOSS::run()
FD_ZERO(&afd);
- while (! done) {
- mutex()->lock();
-
- recycler()->mutex()->lock();
-
- done = m_userStop;
+ while (! done)
+ {
+ mutex()->lock();
- while (! done && (recycler()->empty() || m_pause)) {
- post();
+ recycler()->mutex()->lock();
- mutex()->unlock();
+ done = m_userStop;
- {
- stat = m_pause ? OutputState::Paused : OutputState::Buffering;
- OutputState e((OutputState::Type) stat);
- dispatch(e);
- }
+ while (! done && (recycler()->empty() || m_pause))
+ {
+ post();
- recycler()->cond()->wakeOne();
- recycler()->cond()->wait(recycler()->mutex());
+ mutex()->unlock();
- mutex()->lock();
- done = m_userStop;
- status();
- }
+ recycler()->cond()->wakeOne();
+ recycler()->cond()->wait(recycler()->mutex());
- if (! b) {
- b = recycler()->next();
- if (b->rate)
- m_rate = b->rate;
- }
+ mutex()->lock();
+ done = m_userStop;
+ status();
+ }
- recycler()->cond()->wakeOne();
- recycler()->mutex()->unlock();
+ if (! b)
+ {
+ b = recycler()->next();
+ if (b->rate)
+ m_rate = b->rate;
+ }
- FD_ZERO(&afd);
- FD_SET(m_audio_fd, &afd);
- // nice long poll timeout
- tv.tv_sec = 5l;
- tv.tv_usec = 0l;
+ recycler()->cond()->wakeOne();
+ recycler()->mutex()->unlock();
- if (b &&
- (! do_select || (select(m_audio_fd + 1, 0, &afd, 0, &tv) > 0 &&
- FD_ISSET(m_audio_fd, &afd)))) {
- l = qMin(int(2048), int(b->nbytes - n));
- if (l > 0) {
- m = write(m_audio_fd, b->data + n, l);
- n += m;
+ FD_ZERO(&afd);
+ FD_SET(m_audio_fd, &afd);
+ // nice long poll timeout
+ tv.tv_sec = 5l;
+ tv.tv_usec = 0l;
- status();
- dispatchVisual(b, m_totalWritten, m_channels, m_precision);
- } else {
- // force buffer change
- n = b->nbytes;
- m = 0;
- }
- }
+ if (b &&
+ (! do_select || (select(m_audio_fd + 1, 0, &afd, 0, &tv) > 0 &&
+ FD_ISSET(m_audio_fd, &afd))))
+ {
+ l = qMin(int(2048), int(b->nbytes - n));
+ if (l > 0)
+ {
+ mutex()->unlock();
+ m = write(m_audio_fd, b->data + n, l);
+ mutex()->lock();
+ n += m;
+
+ status();
+ dispatchVisual(b, m_totalWritten, m_channels, m_precision);
+ }
+ else
+ {
+ // force buffer change
+ n = b->nbytes;
+ m = 0;
+ }
+ }
- m_totalWritten += m;
+ m_totalWritten += m;
- if (n == b->nbytes) {
- recycler()->mutex()->lock();
- recycler()->done();
- recycler()->mutex()->unlock();
+ if (n == b->nbytes)
+ {
+ recycler()->mutex()->lock();
+ recycler()->done();
+ recycler()->mutex()->unlock();
- b = 0;
- n = 0;
- }
+ b = 0;
+ n = 0;
+ }
- mutex()->unlock();
+ mutex()->unlock();
}
mutex()->lock();
if (! m_userStop)
- sync();
+ sync();
resetDSP();
m_play = FALSE;
@@ -427,30 +445,37 @@ void OutputOSS::setVolume(int l, int r)
int v, devs;
long cmd;
- ioctl(m_mixer_fd, SOUND_MIXER_READ_DEVMASK, &devs);
- if ((devs & SOUND_MASK_PCM) && (m_master == false))
- cmd = SOUND_MIXER_WRITE_PCM;
- else if ((devs & SOUND_MASK_VOLUME) && (m_master == true))
- cmd = SOUND_MIXER_WRITE_VOLUME;
- else
- {
- //close(mifd);
- return;
- }
- v = (r << 8) | l;
- ioctl(m_mixer_fd, cmd, &v);
+#if SOUND_VERSION < 0x040000
+ ioctl(m_mixer_fd, SOUND_MIXER_READ_DEVMASK, &devs);
+ if ((devs & SOUND_MASK_PCM) && (m_master == false))
+ cmd = SOUND_MIXER_WRITE_PCM;
+ else if ((devs & SOUND_MASK_VOLUME) && (m_master == true))
+ cmd = SOUND_MIXER_WRITE_VOLUME;
+ else
+ {
+ //close(mifd);
+ return;
+ }
+ v = (r << 8) | l;
+ ioctl(m_mixer_fd, cmd, &v);
+#else
+ cmd = SNDCTL_DSP_SETPLAYVOL;
+ v = (r << 8) | l;
+ ioctl(m_audio_fd, cmd, &v);
+#endif
}
void OutputOSS::volume(int *ll,int *rr)
{
- *ll = 0;
+ *ll = 0;
*rr = 0;
int cmd;
int v, devs;
-
+#if SOUND_VERSION < 0x040000
ioctl(m_mixer_fd, SOUND_MIXER_READ_DEVMASK, &devs);
if ((devs & SOUND_MASK_PCM) && (m_master == 0))
cmd = SOUND_MIXER_READ_PCM;
+
else if ((devs & SOUND_MASK_VOLUME) && (m_master == 1))
cmd = SOUND_MIXER_READ_VOLUME;
else
@@ -464,4 +489,11 @@ void OutputOSS::volume(int *ll,int *rr)
*rr = (*rr > 100) ? 100 : *rr;
*ll = (*ll < 0) ? 0 : *ll;
*rr = (*rr < 0) ? 0 : *rr;
+#else
+ cmd = SNDCTL_DSP_GETPLAYVOL;
+ if (ioctl(m_audio_fd, cmd, &v) == -1)
+ v = 0;
+ *rr = (v & 0xFF00) >> 8;
+ *ll = (v & 0x00FF);
+#endif
}