summaryrefslogtreecommitdiffstats
path: root/plugins/oss-sound
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/oss-sound')
-rw-r--r--plugins/oss-sound/CMakeL10n.txt6
-rw-r--r--plugins/oss-sound/Makefile.am18
-rw-r--r--plugins/oss-sound/icons/Makefile.am2
-rw-r--r--plugins/oss-sound/icons/hi16-action-tderadio_oss.pngbin0 -> 915 bytes
-rw-r--r--plugins/oss-sound/icons/hi32-action-tderadio_oss.pngbin0 -> 1954 bytes
-rw-r--r--plugins/oss-sound/icons/hi48-action-tderadio_oss.pngbin0 -> 3230 bytes
-rw-r--r--plugins/oss-sound/oss-sound-configuration-ui.ui129
-rw-r--r--plugins/oss-sound/oss-sound-configuration.cpp86
-rw-r--r--plugins/oss-sound/oss-sound-configuration.h52
-rw-r--r--plugins/oss-sound/oss-sound.cpp991
-rw-r--r--plugins/oss-sound/oss-sound.h225
-rw-r--r--plugins/oss-sound/po/Makefile.am2
-rw-r--r--plugins/oss-sound/po/de.po208
-rw-r--r--plugins/oss-sound/po/ru.po199
-rw-r--r--plugins/oss-sound/po/tderadio-oss-sound.pot194
15 files changed, 2112 insertions, 0 deletions
diff --git a/plugins/oss-sound/CMakeL10n.txt b/plugins/oss-sound/CMakeL10n.txt
new file mode 100644
index 0000000..216b590
--- /dev/null
+++ b/plugins/oss-sound/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-oss-sound"
+ DESTINATION "po"
+)
diff --git a/plugins/oss-sound/Makefile.am b/plugins/oss-sound/Makefile.am
new file mode 100644
index 0000000..84d2fd1
--- /dev/null
+++ b/plugins/oss-sound/Makefile.am
@@ -0,0 +1,18 @@
+SUBDIRS = po icons .
+
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = liboss-sound.la
+liboss_sound_la_SOURCES = oss-sound.cpp oss-sound-configuration-ui.ui \
+ oss-sound-configuration.cpp
+liboss_sound_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+
+noinst_HEADERS = oss-sound.h oss-sound-configuration.h
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-oss-sound.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-oss-sound.pot
diff --git a/plugins/oss-sound/icons/Makefile.am b/plugins/oss-sound/icons/Makefile.am
new file mode 100644
index 0000000..974b96b
--- /dev/null
+++ b/plugins/oss-sound/icons/Makefile.am
@@ -0,0 +1,2 @@
+icons_ICON = AUTO
+iconsdir = $(datadir)/icons
diff --git a/plugins/oss-sound/icons/hi16-action-tderadio_oss.png b/plugins/oss-sound/icons/hi16-action-tderadio_oss.png
new file mode 100644
index 0000000..dcc3d08
--- /dev/null
+++ b/plugins/oss-sound/icons/hi16-action-tderadio_oss.png
Binary files differ
diff --git a/plugins/oss-sound/icons/hi32-action-tderadio_oss.png b/plugins/oss-sound/icons/hi32-action-tderadio_oss.png
new file mode 100644
index 0000000..fab278d
--- /dev/null
+++ b/plugins/oss-sound/icons/hi32-action-tderadio_oss.png
Binary files differ
diff --git a/plugins/oss-sound/icons/hi48-action-tderadio_oss.png b/plugins/oss-sound/icons/hi48-action-tderadio_oss.png
new file mode 100644
index 0000000..0ef1022
--- /dev/null
+++ b/plugins/oss-sound/icons/hi48-action-tderadio_oss.png
Binary files differ
diff --git a/plugins/oss-sound/oss-sound-configuration-ui.ui b/plugins/oss-sound/oss-sound-configuration-ui.ui
new file mode 100644
index 0000000..eca5c58
--- /dev/null
+++ b/plugins/oss-sound/oss-sound-configuration-ui.ui
@@ -0,0 +1,129 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>OSSSoundConfigurationUI</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>OSSSoundConfigurationUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>562</width>
+ <height>411</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>groupBox20</cstring>
+ </property>
+ <property name="title">
+ <string>Devices</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="KURLRequester" row="1" column="1">
+ <property name="name">
+ <cstring>editMixerDevice</cstring>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="0" column="1">
+ <property name="name">
+ <cstring>editDSPDevice</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>PCM Device</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Mixer Device</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Buffer Size</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="2" column="1">
+ <property name="name">
+ <cstring>editBufferSize</cstring>
+ </property>
+ <property name="suffix">
+ <string> kB</string>
+ </property>
+ <property name="maxValue">
+ <number>1024</number>
+ </property>
+ <property name="minValue">
+ <number>4</number>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>groupBox21</cstring>
+ </property>
+ <property name="title">
+ <string>Extended Options</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="TQCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>chkDisablePlayback</cstring>
+ </property>
+ <property name="text">
+ <string>Disable Playback</string>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>chkDisableCapture</cstring>
+ </property>
+ <property name="text">
+ <string>Disable Capture</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="0"/>
+<includes>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">knuminput.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+</includes>
+</UI>
diff --git a/plugins/oss-sound/oss-sound-configuration.cpp b/plugins/oss-sound/oss-sound-configuration.cpp
new file mode 100644
index 0000000..2a0a783
--- /dev/null
+++ b/plugins/oss-sound/oss-sound-configuration.cpp
@@ -0,0 +1,86 @@
+/***************************************************************************
+ oss-sound-configuration.cpp - description
+ -------------------
+ begin : Thu Sep 30 2004
+ copyright : (C) 2004 by Martin Witte
+ email : witte@kawo1.rwth-aachen.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include <tqcheckbox.h>
+
+#include <kurlrequester.h>
+#include <knuminput.h>
+
+#include "oss-sound-configuration.h"
+#include "oss-sound.h"
+
+OSSSoundConfiguration::OSSSoundConfiguration (TQWidget *parent, OSSSoundDevice *dev)
+ : OSSSoundConfigurationUI(parent),
+ m_SoundDevice (dev),
+ m_dirty(true),
+ m_ignore_gui_updates(false)
+{
+ connect(editDSPDevice, TQT_SIGNAL(textChanged(const TQString &)), this, TQT_SLOT(slotSetDirty()));
+ connect(editMixerDevice, TQT_SIGNAL(textChanged(const TQString &)), this, TQT_SLOT(slotSetDirty()));
+ connect(editBufferSize, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotSetDirty()));
+ connect(chkDisablePlayback, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotSetDirty()));
+ connect(chkDisableCapture, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotSetDirty()));
+ slotCancel();
+}
+
+
+OSSSoundConfiguration::~OSSSoundConfiguration ()
+{
+}
+
+
+void OSSSoundConfiguration::slotOK()
+{
+ if (m_SoundDevice && m_dirty) {
+ m_SoundDevice->setBufferSize ( editBufferSize ->value() * 1024);
+ m_SoundDevice->enablePlayback (!chkDisablePlayback->isChecked());
+ m_SoundDevice->enableCapture (!chkDisableCapture ->isChecked());
+ m_SoundDevice->setDSPDeviceName ( editDSPDevice ->url());
+ m_SoundDevice->setMixerDeviceName( editMixerDevice ->url());
+ m_dirty = false;
+ }
+}
+
+
+void OSSSoundConfiguration::slotCancel()
+{
+ if (m_dirty) {
+ m_ignore_gui_updates = true;
+ editDSPDevice ->setURL (m_SoundDevice ? m_SoundDevice->getDSPDeviceName() : TQString());
+ editMixerDevice ->setURL (m_SoundDevice ? m_SoundDevice->getMixerDeviceName() : TQString());
+ editBufferSize ->setValue (m_SoundDevice ? m_SoundDevice->getBufferSize()/1024 : 4);
+ chkDisablePlayback->setChecked(m_SoundDevice ? !m_SoundDevice->isPlaybackEnabled() : false);
+ chkDisableCapture ->setChecked(m_SoundDevice ? !m_SoundDevice->isCaptureEnabled() : false);
+ m_ignore_gui_updates = false;
+ m_dirty = false;
+ }
+}
+
+void OSSSoundConfiguration::slotUpdateConfig()
+{
+ slotSetDirty();
+ slotCancel();
+}
+
+void OSSSoundConfiguration::slotSetDirty()
+{
+ if (!m_ignore_gui_updates) {
+ m_dirty = true;
+ }
+}
+
+#include "oss-sound-configuration.moc"
diff --git a/plugins/oss-sound/oss-sound-configuration.h b/plugins/oss-sound/oss-sound-configuration.h
new file mode 100644
index 0000000..742990c
--- /dev/null
+++ b/plugins/oss-sound/oss-sound-configuration.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ oss-sound-configuration.h - description
+ -------------------
+ begin : Thu Sep 30 2004
+ copyright : (C) 2004 by Martin Witte
+ email : witte@kawo1.rwth-aachen.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef KRADIO_OSS_SOUND_CONFIGURATION_H
+#define KRADIO_OSS_SOUND_CONFIGURATION_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "oss-sound-configuration-ui.h"
+#include "oss-sound.h"
+
+class OSSSoundConfiguration : public OSSSoundConfigurationUI
+{
+Q_OBJECT
+
+public :
+ OSSSoundConfiguration (TQWidget *parent, OSSSoundDevice *);
+ ~OSSSoundConfiguration ();
+
+protected slots:
+
+ void slotOK();
+ void slotCancel();
+ void slotSetDirty();
+
+ void slotUpdateConfig();
+
+protected:
+
+ OSSSoundDevice *m_SoundDevice;
+
+ bool m_dirty;
+ bool m_ignore_gui_updates;
+};
+
+#endif
diff --git a/plugins/oss-sound/oss-sound.cpp b/plugins/oss-sound/oss-sound.cpp
new file mode 100644
index 0000000..00801c0
--- /dev/null
+++ b/plugins/oss-sound/oss-sound.cpp
@@ -0,0 +1,991 @@
+/***************************************************************************
+ oss-sound.cpp - description
+ -------------------
+ begin : Sun Mar 21 2004
+ copyright : (C) 2004 by Martin Witte
+ email : witte@kawo1.rwth-aachen.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "oss-sound.h"
+
+#include "../../src/include/aboutwidget.h"
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/soundcard.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <math.h>
+#include <errno.h>
+
+#include "oss-sound-configuration.h"
+#include "../../src/include/utils.h"
+
+///////////////////////////////////////////////////////////////////////
+//// plugin library functions
+
+PLUGIN_LIBRARY_FUNCTIONS(OSSSoundDevice, "tderadio-oss-sound", i18n("Open Sound System (OSS) Support"));
+
+/////////////////////////////////////////////////////////////////////////////
+
+struct _lrvol { unsigned char l, r; short dummy; };
+
+OSSSoundDevice::OSSSoundDevice(const TQString &name)
+ : TQObject(NULL, NULL),
+ PluginBase(name, i18n("TDERadio OSS Sound Plugin")),
+ m_DSPDeviceName(""),
+ m_MixerDeviceName(""),
+ m_DSP_fd(-1),
+ m_Mixer_fd(-1),
+ m_DuplexMode(DUPLEX_UNKNOWN),
+ m_DSPFormat(),
+ m_PassivePlaybackStreams(),
+ m_PlaybackStreamID(),
+ m_CaptureStreamID(),
+ m_BufferSize(65536),
+ m_PlaybackBuffer(m_BufferSize),
+ m_CaptureBuffer(m_BufferSize),
+ m_CaptureRequestCounter(0),
+ m_CapturePos(0),
+ m_CaptureStartTime(0),
+ //m_PlaybackSkipCount(0),
+ m_CaptureSkipCount(0),
+ m_EnablePlayback(true),
+ m_EnableCapture(true)
+{
+ TQObject::connect(&m_PollingTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotPoll()));
+}
+
+
+OSSSoundDevice::~OSSSoundDevice()
+{
+ stopCapture(m_CaptureStreamID);
+ stopPlayback(m_PlaybackStreamID);
+ closeDSPDevice();
+ closeMixerDevice();
+}
+
+
+bool OSSSoundDevice::connectI(Interface *i)
+{
+ bool a = PluginBase::connectI(i);
+ bool b = ISoundStreamClient::connectI(i);
+ return a || b;
+}
+
+
+bool OSSSoundDevice::disconnectI(Interface *i)
+{
+ bool a = PluginBase::disconnectI(i);
+ bool b = ISoundStreamClient::disconnectI(i);
+ return a || b;
+}
+
+void OSSSoundDevice::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid)
+{
+ ISoundStreamClient::noticeConnectedI(s, pointer_valid);
+ if (s && pointer_valid) {
+ s->register4_sendReleasePlayback(this);
+ s->register4_sendReleaseCapture(this);
+ s->register4_sendPlaybackVolume(this);
+ s->register4_sendCaptureVolume(this);
+ s->register4_queryPlaybackVolume(this);
+ s->register4_queryCaptureVolume(this);
+ s->register4_sendStartPlayback(this);
+ s->register4_sendPausePlayback(this);
+ s->register4_sendStopPlayback(this);
+ s->register4_queryIsPlaybackRunning(this);
+ s->register4_sendStartCaptureWithFormat(this);
+ s->register4_sendStopCapture(this);
+ s->register4_queryIsCaptureRunning(this);
+ s->register4_notifySoundStreamClosed(this);
+ s->register4_notifySoundStreamRedirected(this);
+ s->register4_notifySoundStreamData(this);
+ }
+}
+
+// PluginBase
+
+void OSSSoundDevice::saveState (TDEConfig *c) const
+{
+ c->setGroup(TQString("oss-sound-") + PluginBase::name());
+
+ c->writeEntry("dsp-device", m_DSPDeviceName);
+ c->writeEntry("mixer-device", m_MixerDeviceName);
+ c->writeEntry("enable-playback", m_EnablePlayback);
+ c->writeEntry("enable-capture", m_EnableCapture);
+ c->writeEntry("buffer-size", m_BufferSize);
+ c->writeEntry("soundstreamclient-id", m_SoundStreamClientID);
+}
+
+
+void OSSSoundDevice::restoreState (TDEConfig *c)
+{
+ c->setGroup(TQString("oss-sound-") + PluginBase::name());
+
+ m_EnablePlayback = c->readBoolEntry("enable-playback", true);
+ m_EnableCapture = c->readBoolEntry("enable-capture", true);
+ m_BufferSize = c->readNumEntry ("buffer-size", 65536);
+
+ setDSPDeviceName (c->readEntry ("dsp-device", "/dev/dsp"));
+ setMixerDeviceName (c->readEntry ("mixer-device", "/dev/mixer"));
+
+ m_PlaybackBuffer.resize(m_BufferSize);
+ m_CaptureBuffer.resize(m_BufferSize);
+
+ setSoundStreamClientID(c->readEntry("soundstreamclient-id", getSoundStreamClientID()));
+
+ emit sigUpdateConfig();
+}
+
+
+void OSSSoundDevice::setMixerDeviceName(const TQString &dev_name)
+{
+ if (m_MixerDeviceName != dev_name) {
+ m_MixerDeviceName = dev_name;
+ if (m_Mixer_fd >= 0)
+ openMixerDevice(true);
+ getMixerChannels(SOUND_MIXER_DEVMASK, m_PlaybackChannels, m_revPlaybackChannels);
+ getMixerChannels(SOUND_MIXER_RECMASK, m_CaptureChannels, m_revCaptureChannels);
+ notifyPlaybackChannelsChanged(m_SoundStreamClientID, m_PlaybackChannels);
+ notifyCaptureChannelsChanged(m_SoundStreamClientID, m_CaptureChannels);
+ }
+}
+
+
+ConfigPageInfo OSSSoundDevice::createConfigurationPage()
+{
+ OSSSoundConfiguration *conf = new OSSSoundConfiguration(NULL, this);
+ TQObject::connect(this, TQT_SIGNAL(sigUpdateConfig()), conf, TQT_SLOT(slotUpdateConfig()));
+ return ConfigPageInfo (conf,
+ i18n("OSS Sound"),
+ i18n("OSS Sound Device Options"),
+ "tderadio_oss");
+}
+
+
+AboutPageInfo OSSSoundDevice::createAboutPage()
+{
+/* TDEAboutData aboutData("tderadio",
+ NULL,
+ NULL,
+ I18N_NOOP("OSS Sound Plugin for TDERadio"),
+ TDEAboutData::License_GPL,
+ "(c) 2004 Martin Witte",
+ 0,
+ "http://sourceforge.net/projects/tderadio",
+ 0);
+ aboutData.addAuthor("Martin Witte", "", "witte@kawo1.rwth-aachen.de");
+
+ return AboutPageInfo(
+ new TDERadioAboutWidget(aboutData, TDERadioAboutWidget::AbtTabbed),
+ i18n("OSS Sound"),
+ i18n("OSS Sound"),
+ "tderadio_oss_sound"
+ );
+*/
+ return AboutPageInfo();
+}
+
+
+
+bool OSSSoundDevice::preparePlayback(SoundStreamID id, const TQString &channel, bool active_mode, bool start_immediately)
+{
+ if (id.isValid() && m_revPlaybackChannels.contains(channel)) {
+ m_PlaybackStreams.insert(id, SoundStreamConfig(m_revPlaybackChannels[channel], active_mode));
+ if (start_immediately)
+ startPlayback(id);
+ return true;
+ // FIXME: what to do if stream is already playing?
+ }
+ return false;
+}
+
+
+bool OSSSoundDevice::prepareCapture(SoundStreamID id, const TQString &channel)
+{
+ if (id.isValid() && m_revCaptureChannels.contains(channel)) {
+ m_CaptureStreams.insert(id, SoundStreamConfig(m_revCaptureChannels[channel]));
+ return true;
+ // FIXME: what to do if stream is already playing?
+ }
+ return false;
+}
+
+bool OSSSoundDevice::releasePlayback(SoundStreamID id)
+{
+ if (id.isValid() && m_PlaybackStreams.contains(id)) {
+ if (m_PlaybackStreamID == id || m_PassivePlaybackStreams.contains(id)) {
+ stopPlayback(id);
+ }
+ m_PlaybackStreams.remove(id);
+ return true;
+ }
+ return false;
+}
+
+bool OSSSoundDevice::releaseCapture(SoundStreamID id)
+{
+ if (id.isValid() && m_CaptureStreams.contains(id)) {
+ if (m_CaptureStreamID == id) {
+ stopCapture(id);
+ }
+ m_CaptureStreams.remove(id);
+ return true;
+ }
+ return false;
+}
+
+bool OSSSoundDevice::supportsPlayback() const
+{
+ return m_EnablePlayback;
+}
+
+
+bool OSSSoundDevice::supportsCapture() const
+{
+ return m_EnableCapture;
+}
+
+
+bool OSSSoundDevice::startPlayback(SoundStreamID id)
+{
+ if (id.isValid() && m_PlaybackStreams.contains(id) && m_EnablePlayback) {
+
+ SoundStreamConfig &cfg = m_PlaybackStreams[id];
+
+ bool ok = false;
+ if (cfg.m_ActiveMode) {
+ if (!m_PlaybackStreamID.isValid()) {
+ m_PlaybackStreamID = id;
+ ok = true;
+ }
+ } else {
+ if (!m_PassivePlaybackStreams.contains(id))
+ m_PassivePlaybackStreams.append(id);
+ ok = true;
+ }
+
+ if (ok) {
+ openMixerDevice();
+ if (cfg.m_Volume >= 0)
+ writeMixerVolume(cfg.m_Channel, cfg.m_Volume);
+ }
+
+ // error handling?
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool OSSSoundDevice::pausePlayback(SoundStreamID /*id*/)
+{
+ //return stopPlayback(id);
+ return false;
+}
+
+
+bool OSSSoundDevice::stopPlayback(SoundStreamID id)
+{
+ if (id.isValid() && m_PlaybackStreams.contains(id)) {
+
+ SoundStreamConfig &cfg = m_PlaybackStreams[id];
+
+ if (!cfg.m_ActiveMode) {
+ if (m_PassivePlaybackStreams.contains(id)) {
+// writeMixerVolume(cfg.m_Channel, 0);
+ m_PassivePlaybackStreams.remove(id);
+ }
+ } else if (m_PlaybackStreamID == id) {
+ m_PlaybackStreamID = SoundStreamID::InvalidID;
+ m_PlaybackBuffer.clear();
+ closeDSPDevice();
+ }
+
+ closeMixerDevice();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool OSSSoundDevice::isPlaybackRunning(SoundStreamID id, bool &b) const
+{
+ if (id.isValid() && m_PlaybackStreams.contains(id)) {
+ b = true;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool OSSSoundDevice::startCaptureWithFormat(SoundStreamID id,
+ const SoundFormat &proposed_format,
+ SoundFormat &real_format,
+ bool force_format)
+{
+ if (m_CaptureStreams.contains(id) && m_EnableCapture) {
+
+ if (m_CaptureStreamID != id) {
+ m_CapturePos = 0;
+ m_CaptureStartTime = time(NULL);
+ }
+
+ if (m_CaptureStreamID != id || force_format) {
+
+ m_CaptureStreamID = id;
+ SoundStreamConfig &cfg = m_CaptureStreams[id];
+
+ openMixerDevice();
+ selectCaptureChannel(cfg.m_Channel);
+ if (cfg.m_Volume >= 0)
+ writeMixerVolume(cfg.m_Channel, cfg.m_Volume);
+
+ openDSPDevice(proposed_format);
+
+ // FIXME: error handling?
+ }
+
+ real_format = m_DSPFormat;
+ m_CaptureRequestCounter++;
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool OSSSoundDevice::stopCapture(SoundStreamID id)
+{
+ if (id.isValid() && m_CaptureStreamID == id) {
+
+ if (--m_CaptureRequestCounter == 0) {
+ m_CaptureStreamID = SoundStreamID::InvalidID;
+ m_CaptureBuffer.clear();
+
+ closeMixerDevice();
+ closeDSPDevice();
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool OSSSoundDevice::isCaptureRunning(SoundStreamID id, bool &b, SoundFormat &sf) const
+{
+ if (id.isValid() && m_CaptureStreamID == id) {
+ b = true;
+ sf = m_DSPFormat;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool OSSSoundDevice::noticeSoundStreamClosed(SoundStreamID id)
+{
+ bool found = false;
+ if (m_PlaybackStreamID == id || m_PassivePlaybackStreams.contains(id)) {
+ stopPlayback(id);
+ found = true;
+ }
+ if (m_CaptureStreamID == id) {
+ stopCapture(id);
+ found = true;
+ }
+ m_PlaybackStreams.remove(id);
+ m_CaptureStreams.remove(id);
+ return found;
+}
+
+
+bool OSSSoundDevice::noticeSoundStreamRedirected(SoundStreamID oldID, SoundStreamID newID)
+{
+ bool found = false;
+ if (m_PlaybackStreams.contains(oldID)) {
+ m_PlaybackStreams.insert(newID, m_PlaybackStreams[oldID]);
+ if (newID != oldID)
+ m_PlaybackStreams.remove(oldID);
+ found = true;
+ }
+ if (m_CaptureStreams.contains(oldID)) {
+ m_CaptureStreams.insert(newID, m_CaptureStreams[oldID]);
+ if (newID != oldID)
+ m_CaptureStreams.remove(oldID);
+ found = true;
+ }
+
+ if (m_PlaybackStreamID == oldID)
+ m_PlaybackStreamID = newID;
+ if (m_CaptureStreamID == oldID)
+ m_CaptureStreamID = newID;
+ if (m_PassivePlaybackStreams.contains(oldID)) {
+ m_PassivePlaybackStreams.remove(oldID);
+ m_PassivePlaybackStreams.append(newID);
+ }
+ return found;
+}
+
+
+bool OSSSoundDevice::noticeSoundStreamData(SoundStreamID id,
+ const SoundFormat &format,
+ const char *data, size_t size, size_t &consumed_size,
+ const SoundMetaData &/*md*/
+ )
+{
+ if (!id.isValid() || id != m_PlaybackStreamID)
+ return false;
+
+ if (m_DSP_fd < 0) {
+ openDSPDevice(format);
+ } else if (format != m_DSPFormat) {
+ if (m_CaptureStreamID.isValid())
+ return false;
+
+ // flush playback buffer
+ size_t buffersize = 0;
+ char *buffer = m_PlaybackBuffer.getData(buffersize);
+ write(m_DSP_fd, buffer, buffersize);
+
+ // if not all could be written, it must be discarded
+ m_PlaybackBuffer.clear();
+
+ closeDSPDevice();
+ openDSPDevice(format);
+ // error handling ?
+ }
+
+ size_t n = m_PlaybackBuffer.addData(data, size);
+ consumed_size = (consumed_size == SIZE_T_DONT_CARE) ? n : min(consumed_size, n);
+
+// if (n < size) {
+// m_PlaybackSkipCount += size - n;
+// } else if (m_PlaybackSkipCount > 0) {
+// logWarning(i18n("%1: Playback buffer overflow. Skipped %1 bytes").arg(m_DSPDeviceName).arg(TQString::number(m_PlaybackSkipCount)));
+// m_PlaybackSkipCount = 0;
+// }
+
+ return true; //m_PlaybackSkipCount == 0;
+}
+
+
+
+void OSSSoundDevice::slotPoll()
+{
+ int err = 0;
+
+ if (m_CaptureStreamID.isValid() && m_DSP_fd >= 0) {
+
+ size_t bufferSize = 0;
+ char *buffer = m_CaptureBuffer.getFreeSpace(bufferSize);
+
+ int bytesRead = read(m_DSP_fd, buffer, bufferSize);
+
+ if (bytesRead > 0) {
+ m_CaptureBuffer.removeFreeSpace(bytesRead);
+ } else if (bytesRead < 0 && errno == EAGAIN) {
+ bytesRead = 0;
+ } else if (bytesRead == 0) {
+ err = -1;
+ logError(i18n("OSS device %1: No data to record").arg(m_DSPDeviceName));
+ } else {
+ err = errno;
+ }
+
+ while (m_CaptureBuffer.getFillSize() > m_CaptureBuffer.getSize() / 3) {
+ size_t size = 0;
+ buffer = m_CaptureBuffer.getData(size);
+ time_t cur_time = time(NULL);
+ size_t consumed_size = SIZE_T_DONT_CARE;
+ notifySoundStreamData(m_CaptureStreamID, m_DSPFormat, buffer, size, consumed_size, SoundMetaData(m_CapturePos, cur_time - m_CaptureStartTime, cur_time, i18n("internal stream, not stored (%1)").arg(m_DSPDeviceName)));
+ if (consumed_size == SIZE_T_DONT_CARE)
+ consumed_size = size;
+ m_CaptureBuffer.removeData(consumed_size);
+ m_CapturePos += consumed_size;
+ if (consumed_size < size)
+ break;
+ }
+ }
+
+ if (m_PlaybackStreamID.isValid()/* && m_DSP_fd >= 0*/) {
+
+ if (m_PlaybackBuffer.getFillSize() > 0 && m_DSP_fd >= 0) {
+
+ size_t buffersize = 0;
+ char *buffer = m_PlaybackBuffer.getData(buffersize);
+ int bytesWritten = write(m_DSP_fd, buffer, buffersize);
+
+ if (bytesWritten > 0) {
+ m_PlaybackBuffer.removeData(bytesWritten);
+ } else if (bytesWritten < 0 && errno == EAGAIN) {
+ bytesWritten = 0;
+ } else {
+ err = errno;
+ }
+ }
+
+ if (m_PlaybackBuffer.getFreeSize() > 0)
+ notifyReadyForPlaybackData(m_PlaybackStreamID, m_PlaybackBuffer.getFreeSize());
+ }
+
+ if (err) {
+ logError(i18n("Error %1 while handling OSS device %2").arg(TQString().setNum(err)).arg(m_DSPDeviceName));
+ }
+
+ if (m_PlaybackStreamID.isValid())
+ checkMixerVolume(m_PlaybackStreamID);
+ if (m_CaptureStreamID.isValid())
+ checkMixerVolume(m_CaptureStreamID);
+
+ TQValueListConstIterator<SoundStreamID> end = m_PassivePlaybackStreams.end();
+ for (TQValueListConstIterator<SoundStreamID> it = m_PassivePlaybackStreams.begin(); it != end; ++it)
+ checkMixerVolume(*it);
+
+}
+
+
+bool OSSSoundDevice::openDSPDevice(const SoundFormat &format, bool reopen)
+{
+ if (m_DSP_fd >= 0) {
+
+ if (reopen) {
+
+ closeDSPDevice ( /* force = */ true);
+
+ } else {
+
+ if (format != m_DSPFormat)
+ return false;
+
+ if (m_DuplexMode != DUPLEX_FULL && m_CaptureStreamID.isValid() && m_PlaybackStreamID.isValid())
+ return false;
+
+ return true;
+ }
+ } else {
+ if (reopen)
+ return true;
+ }
+
+ m_DSPFormat = format;
+
+ // first testopen for CAPS
+ m_DSP_fd = open(m_DSPDeviceName.ascii(), O_NONBLOCK | O_RDONLY);
+ bool err = m_DSP_fd < 0;
+ if (err) {
+ logError(i18n("Cannot open DSP device %1").arg(m_DSPDeviceName));
+ return false;
+ }
+ int caps = 0;
+ err |= (ioctl (m_DSP_fd, SNDCTL_DSP_GETCAPS, &caps) != 0);
+ if (err)
+ logError(i18n("Cannot read DSP capabilities for %1").arg(m_DSPDeviceName));
+
+ m_DuplexMode = (caps & DSP_CAP_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF;
+ close (m_DSP_fd);
+ m_DSP_fd = -1;
+
+ // opening and seeting up the device file
+ int mode = O_NONBLOCK;
+ if (m_DuplexMode == DUPLEX_FULL) {
+ mode |= O_RDWR;
+ } else if (m_CaptureStreamID.isValid()) {
+ mode |= O_RDONLY;
+ } else {
+ mode |= O_WRONLY;
+ }
+
+ m_DSP_fd = open(m_DSPDeviceName.ascii(), mode);
+
+ err = m_DSP_fd < 0;
+ if (err) {
+ logError(i18n("Cannot open DSP device %1").arg(m_DSPDeviceName));
+ return false;
+ }
+
+ int oss_format = getOSSFormat(m_DSPFormat);
+ err |= (ioctl(m_DSP_fd, SNDCTL_DSP_SETFMT, &oss_format) != 0);
+ if (err)
+ logError(i18n("Cannot set DSP sample format for %1").arg(m_DSPDeviceName));
+
+ int channels = m_DSPFormat.m_Channels;
+ err |= (ioctl(m_DSP_fd, SNDCTL_DSP_CHANNELS, &channels) != 0);
+ if (err)
+ logError(i18n("Cannot set number of channels for %1").arg(m_DSPDeviceName));
+
+ int rate = m_DSPFormat.m_SampleRate;
+ err |= (ioctl(m_DSP_fd, SNDCTL_DSP_SPEED, &rate) != 0);
+ if (err)
+ logError(i18n("Cannot set sampling rate for %1").arg(m_DSPDeviceName));
+ if (rate != (int)m_DSPFormat.m_SampleRate) {
+ logWarning(i18n("Asking for %1 Hz but %2 uses %3 Hz").
+ arg(TQString::number(m_DSPFormat.m_SampleRate)).
+ arg(m_DSPDeviceName).
+ arg(TQString::number(rate)));
+ m_DSPFormat.m_SampleRate = rate;
+ }
+
+ int stereo = m_DSPFormat.m_Channels == 2;
+ err |= (ioctl(m_DSP_fd, SNDCTL_DSP_STEREO, &stereo) != 0);
+ if (err)
+ logError(i18n("Cannot set stereo mode for %1").arg(m_DSPDeviceName));
+
+ unsigned sampleSize = m_DSPFormat.m_SampleBits;
+ err |= (ioctl(m_DSP_fd, SNDCTL_DSP_SAMPLESIZE, &sampleSize) != 0);
+ if (err || sampleSize != m_DSPFormat.m_SampleBits)
+ logError(i18n("Cannot set sample size for %1").arg(m_DSPDeviceName));
+
+ // setup buffer, ask for 40ms latency
+ int tmp = (400 * m_DSPFormat.frameSize() * m_DSPFormat.m_SampleRate) / 1000;
+ int mask = -1; for (; tmp; tmp >>= 1) ++mask;
+ if (mask < 8) mask = 12; // default 4kB
+ mask |= 0x7FFF0000;
+ err |= ioctl (m_DSP_fd, SNDCTL_DSP_SETFRAGMENT, &mask);
+ if (err)
+ logError(i18n("Cannot set buffers for %1").arg(m_DSPDeviceName));
+
+ int bufferBlockSize = 0;
+ err |= ioctl (m_DSP_fd, SNDCTL_DSP_GETBLKSIZE, &bufferBlockSize);
+ if (err) {
+ logError(i18n("Cannot read buffer size for %1").arg(m_DSPDeviceName));
+ } else {
+ logInfo(i18n("%1 uses buffer blocks of %2 bytes").arg(m_DSPDeviceName).arg(TQString::number(bufferBlockSize)));
+ size_t tmp = (((m_BufferSize - 1) / bufferBlockSize) + 1) * bufferBlockSize;
+ setBufferSize(tmp);
+ logInfo(i18n("adjusted own buffer size to %1 bytes").arg(TQString::number(tmp)));
+ }
+
+ int trigger = ~PCM_ENABLE_INPUT & ~PCM_ENABLE_OUTPUT;
+ ioctl(m_DSP_fd, SNDCTL_DSP_SETTRIGGER, &trigger);
+ trigger = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT;
+ ioctl(m_DSP_fd, SNDCTL_DSP_SETTRIGGER, &trigger);
+
+ if (!err) {
+ m_PollingTimer.start(40);
+ } else {
+ closeDSPDevice();
+ }
+
+ m_CaptureSkipCount = 0;
+ //m_PlaybackSkipCount = 0;
+
+ return !err;
+}
+
+
+bool OSSSoundDevice::closeDSPDevice(bool force)
+{
+ if ((!m_PlaybackStreamID.isValid() && !m_CaptureStreamID.isValid()) || force) {
+
+ if (m_Mixer_fd < 0)
+ m_PollingTimer.stop();
+
+ if (m_DSP_fd >= 0)
+ close (m_DSP_fd);
+ m_DSP_fd = -1;
+
+ m_PlaybackBuffer.clear();
+ m_CaptureBuffer.clear();
+ }
+ return true;
+}
+
+
+bool OSSSoundDevice::openMixerDevice(bool reopen)
+{
+ if (reopen) {
+ if (m_Mixer_fd >= 0)
+ closeMixerDevice(/* force = */ true);
+ else
+ return true;
+ }
+
+ if (m_Mixer_fd < 0)
+ m_Mixer_fd = open(m_MixerDeviceName.ascii(), O_RDONLY);
+
+ if (m_Mixer_fd < 0) {
+ logError(i18n("Cannot open mixer device %1").arg(m_MixerDeviceName));
+ } else {
+ m_PollingTimer.start(40);
+ }
+ return m_Mixer_fd >= 0;
+}
+
+
+bool OSSSoundDevice::closeMixerDevice(bool force)
+{
+ if ((!m_PlaybackStreamID.isValid() && !m_CaptureStreamID.isValid()) || force) {
+
+ if (m_DSP_fd < 0)
+ m_PollingTimer.stop();
+
+ if (m_Mixer_fd >= 0)
+ close (m_Mixer_fd);
+ m_Mixer_fd = -1;
+ }
+ return m_Mixer_fd < 0;
+}
+
+
+void OSSSoundDevice::getMixerChannels(int query, TQStringList &retval, TQMap<TQString, int> &revmap) const
+{
+ retval.clear();
+ revmap.clear();
+
+ int fd = m_Mixer_fd;
+ if (fd < 0)
+ fd = open(m_MixerDeviceName.ascii(), O_RDONLY);
+
+ if (fd < 0) {
+ logError(i18n("OSSSoundDevice::getMixerChannels: Cannot open mixer device %1").arg(m_MixerDeviceName));
+ }
+
+ if (fd >= 0) {
+ int mask = 0;
+ if ( ioctl(fd, MIXER_READ(query), &mask) == 0 ) {
+ for (int i = 0; i < SOUND_MIXER_NRDEVICES; ++i) {
+ if (mask & (1 << i)) {
+ static const char *labels[] = SOUND_DEVICE_LABELS;
+ retval.append(i18n(labels[i]));
+ revmap.insert(i18n(labels[i]), i);
+ }
+ }
+ } else {
+ logError(i18n("OSSSoundDevice::getMixerChannels: Cannot read mixer device mask on device %1").arg(m_MixerDeviceName));
+ }
+ }
+ if (fd != m_Mixer_fd)
+ close(fd);
+}
+
+
+const TQStringList &OSSSoundDevice::getPlaybackChannels() const
+{
+ return m_PlaybackChannels;
+}
+
+
+const TQStringList &OSSSoundDevice::getCaptureChannels() const
+{
+ return m_CaptureChannels;
+}
+
+
+bool OSSSoundDevice::setPlaybackVolume(SoundStreamID id, float volume)
+{
+ if (id.isValid() && (m_PlaybackStreamID == id || m_PassivePlaybackStreams.contains(id))) {
+ SoundStreamConfig &cfg = m_PlaybackStreams[id];
+
+ if (rint(100*volume) != rint(100*cfg.m_Volume)) {
+ cfg.m_Volume = writeMixerVolume(cfg.m_Channel, volume);
+ notifyPlaybackVolumeChanged(id, cfg.m_Volume);
+ }
+ return true;
+ }
+ return false;
+}
+
+
+bool OSSSoundDevice::setCaptureVolume(SoundStreamID id, float volume)
+{
+ if (id.isValid() && m_CaptureStreamID == id) {
+ SoundStreamConfig &cfg = m_CaptureStreams[id];
+
+ if (rint(100*volume) != rint(100*cfg.m_Volume)) {
+ cfg.m_Volume = writeMixerVolume(cfg.m_Channel, volume);
+ notifyCaptureVolumeChanged(id, cfg.m_Volume);
+ }
+ return true;
+ }
+ return false;
+}
+
+
+bool OSSSoundDevice::getPlaybackVolume(SoundStreamID id, float &volume) const
+{
+ if (id.isValid() && (m_PlaybackStreamID == id || m_PassivePlaybackStreams.contains(id))) {
+ const SoundStreamConfig &cfg = m_PlaybackStreams[id];
+ volume = cfg.m_Volume;
+ return true;
+ }
+ return false;
+}
+
+
+bool OSSSoundDevice::getCaptureVolume(SoundStreamID id, float &volume) const
+{
+ if (id.isValid() && m_CaptureStreamID == id) {
+ const SoundStreamConfig &cfg = m_CaptureStreams[id];
+ volume = cfg.m_Volume;
+ return true;
+ }
+ return false;
+}
+
+
+void OSSSoundDevice::checkMixerVolume(SoundStreamID id)
+{
+ if (m_Mixer_fd >= 0 && id.isValid()) {
+
+ if (m_PassivePlaybackStreams.contains(id) || m_PlaybackStreamID == id) {
+ SoundStreamConfig &cfg = m_PlaybackStreams[id];
+
+ float v = readMixerVolume(cfg.m_Channel);
+ if (rint(100*cfg.m_Volume) != rint(100*v)) {
+ cfg.m_Volume = v;
+ notifyPlaybackVolumeChanged(id, v);
+ }
+ }
+
+ if (m_CaptureStreamID == id) {
+ SoundStreamConfig &cfg = m_CaptureStreams[id];
+
+ float v = readMixerVolume(cfg.m_Channel);
+ if (rint(100*cfg.m_Volume) != rint(100*v)) {
+ cfg.m_Volume = v;
+ notifyCaptureVolumeChanged(id, v);
+ }
+ }
+ }
+}
+
+
+float OSSSoundDevice::readMixerVolume(int channel) const
+{
+ _lrvol tmpvol;
+ int err = ioctl(m_Mixer_fd, MIXER_READ(channel), &tmpvol);
+ if (err) {
+ logError("OSSSound::readMixerVolume: " +
+ i18n("error %1 while reading volume from %2")
+ .arg(TQString().setNum(err))
+ .arg(m_MixerDeviceName));
+ tmpvol.l = tmpvol.r = 0;
+ }
+ return float(tmpvol.l) / 100.0;
+}
+
+
+float OSSSoundDevice::writeMixerVolume (int channel, float vol)
+{
+ if (vol > 1.0) vol = 1.0;
+ if (vol < 0) vol = 0.0;
+
+ const int divs = 100;
+ vol = rint(vol * divs) / float(divs);
+
+ if (m_Mixer_fd >= 0) {
+ _lrvol tmpvol;
+ tmpvol.r = tmpvol.l = (unsigned int)(rint(vol * divs));
+ int err = ioctl(m_Mixer_fd, MIXER_WRITE(channel), &tmpvol);
+ if (err != 0) {
+ logError("OSSSoundDevice::writeMixerVolume: " +
+ i18n("error %1 while setting volume to %2 on device %3")
+ .arg(TQString().setNum(err))
+ .arg(TQString().setNum(vol))
+ .arg(m_MixerDeviceName));
+ return -1;
+ }
+ }
+ return vol;
+}
+
+
+void OSSSoundDevice::selectCaptureChannel (int channel)
+{
+ int x = 1 << channel;
+ int err = ioctl(m_Mixer_fd, SOUND_MIXER_WRITE_RECSRC, &x);
+ if (err)
+ logError(i18n("Selecting recording source on device %1 failed with error code %2")
+ .arg(m_MixerDeviceName)
+ .arg(TQString::number(err)));
+ _lrvol tmpvol;
+ err = ioctl(m_Mixer_fd, MIXER_READ(SOUND_MIXER_IGAIN), &tmpvol);
+ if (err)
+ logError(i18n("Reading igain volume on device %1 failed with error code %2")
+ .arg(m_MixerDeviceName)
+ .arg(TQString::number(err)));
+ if (tmpvol.r == 0 && tmpvol.l == 0) {
+ tmpvol.r = tmpvol.l = 1;
+ err = ioctl(m_Mixer_fd, MIXER_WRITE(SOUND_MIXER_IGAIN), &tmpvol);
+ if (err)
+ logError(i18n("Setting igain volume on device %1 failed with error code %2")
+ .arg(m_MixerDeviceName)
+ .arg(TQString::number(err)));
+ }
+}
+
+
+int OSSSoundDevice::getOSSFormat(const SoundFormat &f)
+{
+ if (f.m_SampleBits == 16) {
+ switch (2 * f.m_IsSigned + (f.m_Endianess == LITTLE_ENDIAN)) {
+ case 0: return AFMT_U16_BE;
+ case 1: return AFMT_U16_LE;
+ case 2: return AFMT_S16_BE;
+ case 3: return AFMT_S16_LE;
+ }
+ }
+ if (f.m_SampleBits == 8) {
+ switch (f.m_IsSigned) {
+ case 0: return AFMT_U8;
+ case 1: return AFMT_S8;
+ }
+ }
+ return 0;
+}
+
+
+void OSSSoundDevice::setBufferSize(int s)
+{
+ m_BufferSize = s;
+ m_PlaybackBuffer.resize(m_BufferSize);
+ m_CaptureBuffer.resize(m_BufferSize);
+}
+
+
+void OSSSoundDevice::enablePlayback(bool on)
+{
+ m_EnablePlayback = on;
+}
+
+
+void OSSSoundDevice::enableCapture(bool on)
+{
+ m_EnableCapture = on;
+}
+
+
+void OSSSoundDevice::setDSPDeviceName(const TQString &s)
+{
+ m_DSPDeviceName = s;
+ SoundFormat f = m_DSPFormat;
+ if (m_DSP_fd >= 0)
+ openDSPDevice(f, /* reopen = */ true);
+}
+
+
+TQString OSSSoundDevice::getSoundStreamClientDescription() const
+{
+ return i18n("OSS Sound Device %1").arg(PluginBase::name());
+}
+
+
+
+#include "oss-sound.moc"
diff --git a/plugins/oss-sound/oss-sound.h b/plugins/oss-sound/oss-sound.h
new file mode 100644
index 0000000..68f7ce4
--- /dev/null
+++ b/plugins/oss-sound/oss-sound.h
@@ -0,0 +1,225 @@
+/***************************************************************************
+ oss-sound.h - description
+ -------------------
+ begin : Sun Mar 21 2004
+ copyright : (C) 2004 by Martin Witte
+ email : witte@kawo1.rwth-aachen.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#ifndef _KRADIO_OSS_SOUND_H
+#define _KRADIO_OSS_SOUND_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/ringbuffer.h"
+#include "../../src/include/plugins.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+
+#include <tqobject.h>
+#include <tqtimer.h>
+
+enum DUPLEX_MODE { DUPLEX_UNKNOWN, DUPLEX_FULL, DUPLEX_HALF };
+
+
+struct SoundStreamConfig
+{
+ SoundStreamConfig()
+ : m_ActiveMode(false),
+ m_Channel(-1),
+ m_Volume(-1)
+ {}
+
+ SoundStreamConfig(int _channel, bool active_mode = true)
+ : m_ActiveMode(active_mode),
+ m_Channel(_channel),
+ m_Volume(-1)
+ {}
+
+ SoundStreamConfig(const SoundStreamConfig &c)
+ : m_ActiveMode(c.m_ActiveMode),
+ m_Channel(c.m_Channel),
+ m_Volume(c.m_Volume)
+ {}
+
+ bool m_ActiveMode;
+ int m_Channel;
+ float m_Volume;
+};
+
+
+class OSSSoundDevice : public TQObject,
+ public PluginBase,
+ public ISoundStreamClient
+{
+Q_OBJECT
+
+
+public:
+ OSSSoundDevice (const TQString &name);
+ virtual ~OSSSoundDevice ();
+
+ virtual bool connectI(Interface *i);
+ virtual bool disconnectI(Interface *i);
+
+ // PluginBase
+
+public:
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+ virtual TQString pluginClassName() const { return "OSSSoundDevice"; }
+
+ virtual const TQString &name() const { return PluginBase::name(); }
+ virtual TQString &name() { return PluginBase::name(); }
+
+ virtual ConfigPageInfo createConfigurationPage();
+ virtual AboutPageInfo createAboutPage();
+
+ // ISoundStreamClient: direct device access
+
+RECEIVERS:
+ void noticeConnectedI (ISoundStreamServer *s, bool pointer_valid);
+ bool preparePlayback(SoundStreamID id, const TQString &channel, bool active_mode, bool start_immediately);
+ bool prepareCapture(SoundStreamID id, const TQString &channel);
+ bool releasePlayback(SoundStreamID id);
+ bool releaseCapture(SoundStreamID id);
+
+ANSWERS:
+ bool supportsPlayback() const;
+ bool supportsCapture() const;
+
+ TQString getSoundStreamClientDescription() const;
+
+ // ISoundStreamClient: mixer access
+
+protected:
+ void getMixerChannels(int query_playback_or_rec_mask, TQStringList &retval, TQMap<TQString, int> &revmap) const;
+
+ANSWERS:
+ const TQStringList &getPlaybackChannels() const;
+ const TQStringList &getCaptureChannels() const;
+
+RECEIVERS:
+ bool setPlaybackVolume(SoundStreamID id, float volume);
+ bool setCaptureVolume(SoundStreamID id, float volume);
+ bool getPlaybackVolume(SoundStreamID id, float &volume) const;
+ bool getCaptureVolume(SoundStreamID id, float &volume) const;
+
+ // ISoundStreamClient: generic broadcasts
+
+RECEIVERS:
+ bool startPlayback(SoundStreamID id);
+ bool pausePlayback(SoundStreamID id);
+ bool stopPlayback(SoundStreamID id);
+ bool isPlaybackRunning(SoundStreamID id, bool &b) const;
+
+ bool startCaptureWithFormat(SoundStreamID id,
+ const SoundFormat &proposed_format,
+ SoundFormat &real_format,
+ bool force_format);
+ bool stopCapture(SoundStreamID id);
+ bool isCaptureRunning(SoundStreamID id, bool &b, SoundFormat &sf) const;
+
+ bool noticeSoundStreamClosed(SoundStreamID id);
+ bool noticeSoundStreamRedirected(SoundStreamID oldID, SoundStreamID newID);
+
+ bool noticeSoundStreamData(SoundStreamID id,
+ const SoundFormat &,
+ const char *data, size_t size, size_t &consumed_size,
+ const SoundMetaData &md
+ );
+
+
+ // Config Access
+
+ int getBufferSize() const { return m_BufferSize; }
+ bool isPlaybackEnabled() const { return m_EnablePlayback; }
+ bool isCaptureEnabled() const { return m_EnableCapture; }
+ const TQString &getDSPDeviceName() const { return m_DSPDeviceName; }
+ const TQString &getMixerDeviceName() const { return m_MixerDeviceName; }
+
+ void setBufferSize(int s);
+ void enablePlayback(bool on);
+ void enableCapture(bool on);
+ void setDSPDeviceName(const TQString &s);
+ void setMixerDeviceName(const TQString &dev_name);
+
+ // own functions
+
+ static int getOSSFormat(const SoundFormat &f);
+
+protected slots:
+
+ void slotPoll();
+
+signals:
+
+ void sigUpdateConfig();
+
+protected:
+
+ bool openDSPDevice(const SoundFormat &format, bool reopen = false);
+ bool closeDSPDevice(bool force = false);
+
+ bool openMixerDevice(bool reopen = false);
+ bool closeMixerDevice(bool force = false);
+
+ void checkMixerVolume(SoundStreamID id);
+ float readMixerVolume(int channel) const;
+ float writeMixerVolume(int channel, float vol);
+
+ void selectCaptureChannel (int channel);
+
+ TQString m_DSPDeviceName,
+ m_MixerDeviceName;
+ int m_DSP_fd,
+ m_Mixer_fd;
+ DUPLEX_MODE m_DuplexMode;
+ SoundFormat m_DSPFormat;
+
+ TQStringList m_PlaybackChannels,
+ m_CaptureChannels;
+ TQMap<TQString, int> m_revPlaybackChannels,
+ m_revCaptureChannels;
+
+ TQMap<SoundStreamID, SoundStreamConfig>
+ m_PlaybackStreams,
+ m_CaptureStreams;
+
+ TQValueList<SoundStreamID>
+ m_PassivePlaybackStreams;
+ SoundStreamID m_PlaybackStreamID,
+ m_CaptureStreamID;
+
+ size_t m_BufferSize;
+ RingBuffer m_PlaybackBuffer,
+ m_CaptureBuffer;
+
+ unsigned m_CaptureRequestCounter;
+ TQ_UINT64 m_CapturePos;
+ time_t m_CaptureStartTime;
+
+
+ size_t //m_PlaybackSkipCount,
+ m_CaptureSkipCount;
+
+ bool m_EnablePlayback,
+ m_EnableCapture;
+
+ TQTimer m_PollingTimer;
+};
+
+
+
+#endif
diff --git a/plugins/oss-sound/po/Makefile.am b/plugins/oss-sound/po/Makefile.am
new file mode 100644
index 0000000..daec2a5
--- /dev/null
+++ b/plugins/oss-sound/po/Makefile.am
@@ -0,0 +1,2 @@
+PACKAGE = tderadio-oss-sound
+POFILES = AUTO
diff --git a/plugins/oss-sound/po/de.po b/plugins/oss-sound/po/de.po
new file mode 100644
index 0000000..876b1bf
--- /dev/null
+++ b/plugins/oss-sound/po/de.po
@@ -0,0 +1,208 @@
+# translation of de.po to
+# translation of tderadio-oss-sound.po to
+# This file is put in the public domain.
+#
+# Ernst Martin Witte <emw@nocabal.de>, 2006.
+msgid ""
+msgstr ""
+"Project-Id-Version: de\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-05-11 04:30+0200\n"
+"PO-Revision-Date: 2019-11-24 00:55+0000\n"
+"Last-Translator: Chris <xchrisx@uber.space>\n"
+"Language-Team: German <https://mirror.git.trinitydesktop.org/weblate/"
+"projects/applications/tderadio-oss-sound/de/>\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 3.9.1\n"
+
+#. Instead of a literal translation, add your name to the end of the list (separated by a comma).
+msgid ""
+"_: NAME OF TRANSLATORS\n"
+"Your names"
+msgstr "Ernst Martin Witte"
+
+#. Instead of a literal translation, add your email to the end of the list (separated by a comma).
+msgid ""
+"_: EMAIL OF TRANSLATORS\n"
+"Your emails"
+msgstr "emw@nocabal.de"
+
+#: oss-sound.cpp:38
+msgid "Open Sound System (OSS) Support"
+msgstr "Unterstützung für das Open Sound System (OSS)"
+
+#: oss-sound.cpp:46
+msgid "TDERadio OSS Sound Plugin"
+msgstr "TDERadio Plugin für das Open Sound System (OSS)"
+
+#: oss-sound.cpp:172
+msgid "OSS Sound"
+msgstr "OSS-Sound"
+
+#: oss-sound.cpp:173
+msgid "OSS Sound Device Options"
+msgstr "Geräteoptionen für den OSS Sound"
+
+#: oss-sound.cpp:507
+msgid "OSS device %1: No data to record"
+msgstr "OSS Gerät %1: Keine Daten zum Aufnehmen"
+
+#: oss-sound.cpp:517
+msgid "internal stream, not stored (%1)"
+msgstr "interner, nicht aufgezeichneter Datenstrom (%1)"
+
+#: oss-sound.cpp:549
+msgid "Error %1 while handling OSS device %2"
+msgstr "Fehler %1 beim Behandeln vom OSS-Gerät %2"
+
+#: oss-sound.cpp:593 oss-sound.cpp:619
+#, c-format
+msgid "Cannot open DSP device %1"
+msgstr "Die Audio-Gerätedatei %1 kann nicht geöffnet werden"
+
+#: oss-sound.cpp:599
+#, c-format
+msgid "Cannot read DSP capabilities for %1"
+msgstr "DSP-Fähigkeiten des Gerätes %1 können nicht gelesen werden."
+
+#: oss-sound.cpp:626
+#, c-format
+msgid "Cannot set DSP sample format for %1"
+msgstr "Kann das Abtastformat für %1 nicht schreiben"
+
+#: oss-sound.cpp:631
+#, c-format
+msgid "Cannot set number of channels for %1"
+msgstr "Kann die Anzahl der Kanäle für %1 nicht festlegen"
+
+#: oss-sound.cpp:636
+#, c-format
+msgid "Cannot set sampling rate for %1"
+msgstr "Kann die Abtastrate für %1 nicht setzen"
+
+#: oss-sound.cpp:638
+msgid "Asking for %1 Hz but %2 uses %3 Hz"
+msgstr ""
+"%1 Hz sollen als Abtastrate verwendet werden, kann aber nur %3 Hz für das "
+"Gerät %2 verwendens"
+
+#: oss-sound.cpp:648
+#, c-format
+msgid "Cannot set stereo mode for %1"
+msgstr "Kann den Stereo-Modus für %1 nicht setzen"
+
+#: oss-sound.cpp:653
+#, c-format
+msgid "Cannot set sample size for %1"
+msgstr "Kann das Quantisierung-Format für %1 nicht setzen"
+
+#: oss-sound.cpp:662
+#, c-format
+msgid "Cannot set buffers for %1"
+msgstr "Kann die Puffer für %1 nicht einstellen"
+
+#: oss-sound.cpp:667
+#, c-format
+msgid "Cannot read buffer size for %1"
+msgstr "Puffergröße des Gerätes %1 kann nicht gelesen werden."
+
+#: oss-sound.cpp:669
+msgid "%1 uses buffer blocks of %2 bytes"
+msgstr "Gerät %1 verwendet Pufferblöcke von %2 Bytes"
+
+#: oss-sound.cpp:672
+msgid "adjusted own buffer size to %1 bytes"
+msgstr "Die interne Puffergröße wurde auf %1 bytes angepasst"
+
+#: oss-sound.cpp:724
+#, c-format
+msgid "Cannot open mixer device %1"
+msgstr "Die Mixergerätedatei %1 kann nicht geöffnet werden"
+
+#: oss-sound.cpp:757
+#, c-format
+msgid "OSSSoundDevice::getMixerChannels: Cannot open mixer device %1"
+msgstr "OSSSoundDevice::getMixerChannels: Kann den Mixer %1 nicht öffnen"
+
+#: oss-sound.cpp:771
+#, c-format
+msgid ""
+"OSSSoundDevice::getMixerChannels: Cannot read mixer device mask on device %1"
+msgstr ""
+"OSSSoundDevice::getMixerChannels: Gerätemaske des Mixers %1 nicht gelesen "
+"werden."
+
+#: oss-sound.cpp:876
+msgid "error %1 while reading volume from %2"
+msgstr "Fehler %1 beim Lesen der Lautstärke von %2"
+
+#: oss-sound.cpp:899
+msgid "error %1 while setting volume to %2 on device %3"
+msgstr "Fehler %1 beim setzen der Lautstärke %2 auf dem Gerät %3"
+
+#: oss-sound.cpp:915
+msgid "Selecting recording source on device %1 failed with error code %2"
+msgstr ""
+"Das Auswählen der Aufnahmequelle auf dem Gerät %1 schlug mit Fehlercode %2 "
+"fehl"
+
+#: oss-sound.cpp:921
+msgid "Reading igain volume on device %1 failed with error code %2"
+msgstr ""
+"Das Lesen der Aufnahmeverstärkung vom Geräte %1 schlug fehl mit dem "
+"Fehlercode %2"
+
+#: oss-sound.cpp:928
+msgid "Setting igain volume on device %1 failed with error code %2"
+msgstr ""
+"Das Schreiben der Aufnahmeverstärkung vom Geräte %1 schlug fehl mit dem "
+"Fehlercode %2"
+
+#: oss-sound.cpp:986
+#, c-format
+msgid "OSS Sound Device %1"
+msgstr "OSS Sound Gerät %1"
+
+#: oss-sound-configuration-ui.ui:27
+#, no-c-format
+msgid "Devices"
+msgstr "Geräte"
+
+#: oss-sound-configuration-ui.ui:51
+#, no-c-format
+msgid "PCM Device"
+msgstr "Gerät"
+
+#: oss-sound-configuration-ui.ui:59
+#, no-c-format
+msgid "Mixer Device"
+msgstr "Mixer Gerätedatei"
+
+#: oss-sound-configuration-ui.ui:67
+#, no-c-format
+msgid "Buffer Size"
+msgstr "Puffergröße"
+
+#: oss-sound-configuration-ui.ui:75
+#, no-c-format
+msgid " kB"
+msgstr " kB"
+
+#: oss-sound-configuration-ui.ui:91
+#, no-c-format
+msgid "Extended Options"
+msgstr "Erweiterte Optionen"
+
+#: oss-sound-configuration-ui.ui:105
+#, no-c-format
+msgid "Disable Playback"
+msgstr "Wiedergabe abschalten"
+
+#: oss-sound-configuration-ui.ui:113
+#, no-c-format
+msgid "Disable Capture"
+msgstr "Aufnahme abschalten"
diff --git a/plugins/oss-sound/po/ru.po b/plugins/oss-sound/po/ru.po
new file mode 100644
index 0000000..6d3941c
--- /dev/null
+++ b/plugins/oss-sound/po/ru.po
@@ -0,0 +1,199 @@
+# translation of ru.po to
+# translation of tderadio-oss-sound.po to
+# This file is put in the public domain.
+# Алексей Кузнецов <Alexey.Kouznetsov@GMail.com>, 2006.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ru\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-05-11 04:30+0200\n"
+"PO-Revision-Date: 2006-11-08 12:45+0300\n"
+"Last-Translator: Алексей Кузнецов <Alexey.Kouznetsov@GMail.com>\n"
+"Language-Team: <ru@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.10\n"
+
+#. Instead of a literal translation, add your name to the end of the list (separated by a comma).
+msgid ""
+"_: NAME OF TRANSLATORS\n"
+"Your names"
+msgstr "Алексей Кузнецов"
+
+#. Instead of a literal translation, add your email to the end of the list (separated by a comma).
+msgid ""
+"_: EMAIL OF TRANSLATORS\n"
+"Your emails"
+msgstr "Alexey.Kouznetsov@GMail.com"
+
+#: oss-sound.cpp:38
+msgid "Open Sound System (OSS) Support"
+msgstr "Поддержка Открытой звуковой системы (OSS)"
+
+#: oss-sound.cpp:46
+msgid "TDERadio OSS Sound Plugin"
+msgstr "Модуль OSS для TDERadio"
+
+#: oss-sound.cpp:172
+msgid "OSS Sound"
+msgstr "OSS"
+
+#: oss-sound.cpp:173
+msgid "OSS Sound Device Options"
+msgstr "Параметры звука для драйвера OSS"
+
+#: oss-sound.cpp:507
+msgid "OSS device %1: No data to record"
+msgstr "Устройство OSS %1: для записи нет данных"
+
+#: oss-sound.cpp:517
+msgid "internal stream, not stored (%1)"
+msgstr ""
+
+#: oss-sound.cpp:549
+msgid "Error %1 while handling OSS device %2"
+msgstr "Ошибка %1 при работе с устройством OSS %2."
+
+#: oss-sound.cpp:593 oss-sound.cpp:619
+#, c-format
+msgid "Cannot open DSP device %1"
+msgstr "Не могу открыть устройство звуковой платы %1"
+
+#: oss-sound.cpp:599
+#, c-format
+msgid "Cannot read DSP capabilities for %1"
+msgstr "Не могу узнать возможности звуковой платы %1"
+
+#: oss-sound.cpp:626
+#, c-format
+msgid "Cannot set DSP sample format for %1"
+msgstr "Не могу установить формат данных для звуковой платы %1"
+
+#: oss-sound.cpp:631
+#, c-format
+msgid "Cannot set number of channels for %1"
+msgstr "Не могу установить число каналов для звуковой платы %1"
+
+#: oss-sound.cpp:636
+#, c-format
+msgid "Cannot set sampling rate for %1"
+msgstr "Не могу установить частоту дискретизации для звуковой платы %1"
+
+#: oss-sound.cpp:638
+msgid "Asking for %1 Hz but %2 uses %3 Hz"
+msgstr "Был дан запрос на %1 Гц, однако %2 использует %3 Гц."
+
+#: oss-sound.cpp:648
+#, c-format
+msgid "Cannot set stereo mode for %1"
+msgstr "Не могу установить стерео режим для звуковой платы %1"
+
+#: oss-sound.cpp:653
+#, c-format
+msgid "Cannot set sample size for %1"
+msgstr "Не могу установить размер элемента выборки для звуковой платы %1"
+
+#: oss-sound.cpp:662
+#, c-format
+msgid "Cannot set buffers for %1"
+msgstr "Не могу установить буферы для звуковой платы %1"
+
+#: oss-sound.cpp:667
+#, c-format
+msgid "Cannot read buffer size for %1"
+msgstr "Не могу узнать размер буфера звуковой платы %1"
+
+#: oss-sound.cpp:669
+msgid "%1 uses buffer blocks of %2 bytes"
+msgstr "%1 использует блоки буфера по %2 байт"
+
+#: oss-sound.cpp:672
+msgid "adjusted own buffer size to %1 bytes"
+msgstr "Размер собственного буфера установлен %1 байт."
+
+#: oss-sound.cpp:724
+#, c-format
+msgid "Cannot open mixer device %1"
+msgstr "Не могу открыть устройство микшера %1"
+
+#: oss-sound.cpp:757
+#, c-format
+msgid "OSSSoundDevice::getMixerChannels: Cannot open mixer device %1"
+msgstr ""
+"OSSSoundDevice::getMixerChannels: Не могу открыть устройство микшера %1"
+
+#: oss-sound.cpp:771
+#, c-format
+msgid ""
+"OSSSoundDevice::getMixerChannels: Cannot read mixer device mask on device %1"
+msgstr ""
+"OSSSoundDevice::getMixerChannels: не могу прочесть маску устройства микшера "
+"для устройства %1"
+
+#: oss-sound.cpp:876
+msgid "error %1 while reading volume from %2"
+msgstr "Ошибка %1 при считывании громкости с %2."
+
+#: oss-sound.cpp:899
+msgid "error %1 while setting volume to %2 on device %3"
+msgstr "Ошибка %1 при установке громкости %2 на устройстве %3."
+
+#: oss-sound.cpp:915
+msgid "Selecting recording source on device %1 failed with error code %2"
+msgstr "Выбор источника записи на устройстве %1 не удался (код ошибки %2)"
+
+#: oss-sound.cpp:921
+msgid "Reading igain volume on device %1 failed with error code %2"
+msgstr "Считывание громкости записи с устройства %1 не удалось (код ошибки %2)"
+
+#: oss-sound.cpp:928
+msgid "Setting igain volume on device %1 failed with error code %2"
+msgstr "Установка громкости записи на устройстве %1 не удалась (код ошибки %2)"
+
+#: oss-sound.cpp:986
+#, c-format
+msgid "OSS Sound Device %1"
+msgstr "Устройство OSS: %1"
+
+#: oss-sound-configuration-ui.ui:27
+#, no-c-format
+msgid "Devices"
+msgstr "Устройства"
+
+#: oss-sound-configuration-ui.ui:51
+#, no-c-format
+msgid "PCM Device"
+msgstr "Устройство PCM"
+
+#: oss-sound-configuration-ui.ui:59
+#, no-c-format
+msgid "Mixer Device"
+msgstr "Устройство микшера"
+
+#: oss-sound-configuration-ui.ui:67
+#, no-c-format
+msgid "Buffer Size"
+msgstr "Размер буфера"
+
+#: oss-sound-configuration-ui.ui:75
+#, no-c-format
+msgid " kB"
+msgstr " кБ"
+
+#: oss-sound-configuration-ui.ui:91
+#, no-c-format
+msgid "Extended Options"
+msgstr "Дополнительные параметры"
+
+#: oss-sound-configuration-ui.ui:105
+#, no-c-format
+msgid "Disable Playback"
+msgstr "Запретить &воспроизведение"
+
+#: oss-sound-configuration-ui.ui:113
+#, no-c-format
+msgid "Disable Capture"
+msgstr "Запретить &запись"
diff --git a/plugins/oss-sound/po/tderadio-oss-sound.pot b/plugins/oss-sound/po/tderadio-oss-sound.pot
new file mode 100644
index 0000000..e6bef6e
--- /dev/null
+++ b/plugins/oss-sound/po/tderadio-oss-sound.pot
@@ -0,0 +1,194 @@
+# SOME DESCRIPTIVE TITLE.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2020-05-11 04:30+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Instead of a literal translation, add your name to the end of the list (separated by a comma).
+#, ignore-inconsistent
+msgid ""
+"_: NAME OF TRANSLATORS\n"
+"Your names"
+msgstr ""
+
+#. Instead of a literal translation, add your email to the end of the list (separated by a comma).
+#, ignore-inconsistent
+msgid ""
+"_: EMAIL OF TRANSLATORS\n"
+"Your emails"
+msgstr ""
+
+#: oss-sound.cpp:38
+msgid "Open Sound System (OSS) Support"
+msgstr ""
+
+#: oss-sound.cpp:46
+msgid "TDERadio OSS Sound Plugin"
+msgstr ""
+
+#: oss-sound.cpp:172
+msgid "OSS Sound"
+msgstr ""
+
+#: oss-sound.cpp:173
+msgid "OSS Sound Device Options"
+msgstr ""
+
+#: oss-sound.cpp:507
+msgid "OSS device %1: No data to record"
+msgstr ""
+
+#: oss-sound.cpp:517
+msgid "internal stream, not stored (%1)"
+msgstr ""
+
+#: oss-sound.cpp:549
+msgid "Error %1 while handling OSS device %2"
+msgstr ""
+
+#: oss-sound.cpp:593 oss-sound.cpp:619
+#, c-format
+msgid "Cannot open DSP device %1"
+msgstr ""
+
+#: oss-sound.cpp:599
+#, c-format
+msgid "Cannot read DSP capabilities for %1"
+msgstr ""
+
+#: oss-sound.cpp:626
+#, c-format
+msgid "Cannot set DSP sample format for %1"
+msgstr ""
+
+#: oss-sound.cpp:631
+#, c-format
+msgid "Cannot set number of channels for %1"
+msgstr ""
+
+#: oss-sound.cpp:636
+#, c-format
+msgid "Cannot set sampling rate for %1"
+msgstr ""
+
+#: oss-sound.cpp:638
+msgid "Asking for %1 Hz but %2 uses %3 Hz"
+msgstr ""
+
+#: oss-sound.cpp:648
+#, c-format
+msgid "Cannot set stereo mode for %1"
+msgstr ""
+
+#: oss-sound.cpp:653
+#, c-format
+msgid "Cannot set sample size for %1"
+msgstr ""
+
+#: oss-sound.cpp:662
+#, c-format
+msgid "Cannot set buffers for %1"
+msgstr ""
+
+#: oss-sound.cpp:667
+#, c-format
+msgid "Cannot read buffer size for %1"
+msgstr ""
+
+#: oss-sound.cpp:669
+msgid "%1 uses buffer blocks of %2 bytes"
+msgstr ""
+
+#: oss-sound.cpp:672
+msgid "adjusted own buffer size to %1 bytes"
+msgstr ""
+
+#: oss-sound.cpp:724
+#, c-format
+msgid "Cannot open mixer device %1"
+msgstr ""
+
+#: oss-sound.cpp:757
+#, c-format
+msgid "OSSSoundDevice::getMixerChannels: Cannot open mixer device %1"
+msgstr ""
+
+#: oss-sound.cpp:771
+#, c-format
+msgid ""
+"OSSSoundDevice::getMixerChannels: Cannot read mixer device mask on device %1"
+msgstr ""
+
+#: oss-sound.cpp:876
+msgid "error %1 while reading volume from %2"
+msgstr ""
+
+#: oss-sound.cpp:899
+msgid "error %1 while setting volume to %2 on device %3"
+msgstr ""
+
+#: oss-sound.cpp:915
+msgid "Selecting recording source on device %1 failed with error code %2"
+msgstr ""
+
+#: oss-sound.cpp:921
+msgid "Reading igain volume on device %1 failed with error code %2"
+msgstr ""
+
+#: oss-sound.cpp:928
+msgid "Setting igain volume on device %1 failed with error code %2"
+msgstr ""
+
+#: oss-sound.cpp:986
+#, c-format
+msgid "OSS Sound Device %1"
+msgstr ""
+
+#: oss-sound-configuration-ui.ui:27
+#, no-c-format
+msgid "Devices"
+msgstr ""
+
+#: oss-sound-configuration-ui.ui:51
+#, no-c-format
+msgid "PCM Device"
+msgstr ""
+
+#: oss-sound-configuration-ui.ui:59
+#, no-c-format
+msgid "Mixer Device"
+msgstr ""
+
+#: oss-sound-configuration-ui.ui:67
+#, no-c-format
+msgid "Buffer Size"
+msgstr ""
+
+#: oss-sound-configuration-ui.ui:75
+#, no-c-format
+msgid " kB"
+msgstr ""
+
+#: oss-sound-configuration-ui.ui:91
+#, no-c-format
+msgid "Extended Options"
+msgstr ""
+
+#: oss-sound-configuration-ui.ui:105
+#, no-c-format
+msgid "Disable Playback"
+msgstr ""
+
+#: oss-sound-configuration-ui.ui:113
+#, no-c-format
+msgid "Disable Capture"
+msgstr ""