diff options
Diffstat (limited to 'tderadio3/plugins/oss-sound')
-rw-r--r-- | tderadio3/plugins/oss-sound/Makefile.am | 18 | ||||
-rw-r--r-- | tderadio3/plugins/oss-sound/icons/Makefile.am | 2 | ||||
-rw-r--r-- | tderadio3/plugins/oss-sound/icons/hi16-action-tderadio_oss.png | bin | 0 -> 1043 bytes | |||
-rw-r--r-- | tderadio3/plugins/oss-sound/icons/hi32-action-tderadio_oss.png | bin | 0 -> 2207 bytes | |||
-rw-r--r-- | tderadio3/plugins/oss-sound/icons/hi48-action-tderadio_oss.png | bin | 0 -> 3703 bytes | |||
-rw-r--r-- | tderadio3/plugins/oss-sound/oss-sound-configuration-ui.ui | 132 | ||||
-rw-r--r-- | tderadio3/plugins/oss-sound/oss-sound-configuration.cpp | 86 | ||||
-rw-r--r-- | tderadio3/plugins/oss-sound/oss-sound-configuration.h | 52 | ||||
-rw-r--r-- | tderadio3/plugins/oss-sound/oss-sound.cpp | 991 | ||||
-rw-r--r-- | tderadio3/plugins/oss-sound/oss-sound.h | 225 | ||||
-rw-r--r-- | tderadio3/plugins/oss-sound/po/Makefile.am | 2 | ||||
-rw-r--r-- | tderadio3/plugins/oss-sound/po/de.po | 200 | ||||
-rw-r--r-- | tderadio3/plugins/oss-sound/po/ru.po | 193 |
13 files changed, 1901 insertions, 0 deletions
diff --git a/tderadio3/plugins/oss-sound/Makefile.am b/tderadio3/plugins/oss-sound/Makefile.am new file mode 100644 index 0000000..ffdd5be --- /dev/null +++ b/tderadio3/plugins/oss-sound/Makefile.am @@ -0,0 +1,18 @@ +SUBDIRS = po icons . + +INCLUDES = $(all_includes) +METASOURCES = AUTO + +libkradio_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/kradio-oss-sound.pot + +messages: rc.cpp + $(EXTRACTRC) *.rc *.ui >> rc.cpp + $(XGETTEXT) rc.cpp *.h *.cpp -o po/kradio-oss-sound.pot diff --git a/tderadio3/plugins/oss-sound/icons/Makefile.am b/tderadio3/plugins/oss-sound/icons/Makefile.am new file mode 100644 index 0000000..b3f2583 --- /dev/null +++ b/tderadio3/plugins/oss-sound/icons/Makefile.am @@ -0,0 +1,2 @@ +icons_ICON = AUTO +iconsdir = $(kde_datadir)/kradio/icons diff --git a/tderadio3/plugins/oss-sound/icons/hi16-action-tderadio_oss.png b/tderadio3/plugins/oss-sound/icons/hi16-action-tderadio_oss.png Binary files differnew file mode 100644 index 0000000..a422967 --- /dev/null +++ b/tderadio3/plugins/oss-sound/icons/hi16-action-tderadio_oss.png diff --git a/tderadio3/plugins/oss-sound/icons/hi32-action-tderadio_oss.png b/tderadio3/plugins/oss-sound/icons/hi32-action-tderadio_oss.png Binary files differnew file mode 100644 index 0000000..2036faa --- /dev/null +++ b/tderadio3/plugins/oss-sound/icons/hi32-action-tderadio_oss.png diff --git a/tderadio3/plugins/oss-sound/icons/hi48-action-tderadio_oss.png b/tderadio3/plugins/oss-sound/icons/hi48-action-tderadio_oss.png Binary files differnew file mode 100644 index 0000000..dc766a8 --- /dev/null +++ b/tderadio3/plugins/oss-sound/icons/hi48-action-tderadio_oss.png diff --git a/tderadio3/plugins/oss-sound/oss-sound-configuration-ui.ui b/tderadio3/plugins/oss-sound/oss-sound-configuration-ui.ui new file mode 100644 index 0000000..422924f --- /dev/null +++ b/tderadio3/plugins/oss-sound/oss-sound-configuration-ui.ui @@ -0,0 +1,132 @@ +<!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"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/tderadio3/plugins/oss-sound/oss-sound-configuration.cpp b/tderadio3/plugins/oss-sound/oss-sound-configuration.cpp new file mode 100644 index 0000000..2a0a783 --- /dev/null +++ b/tderadio3/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 : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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/tderadio3/plugins/oss-sound/oss-sound-configuration.h b/tderadio3/plugins/oss-sound/oss-sound-configuration.h new file mode 100644 index 0000000..742990c --- /dev/null +++ b/tderadio3/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 : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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/tderadio3/plugins/oss-sound/oss-sound.cpp b/tderadio3/plugins/oss-sound/oss-sound.cpp new file mode 100644 index 0000000..0c06f33 --- /dev/null +++ b/tderadio3/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 : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 <klocale.h> +#include <kaboutdata.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, "kradio-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"), + "kradio_oss"); +} + + +AboutPageInfo OSSSoundDevice::createAboutPage() +{ +/* TDEAboutData aboutData("kradio", + NULL, + NULL, + I18N_NOOP("OSS Sound Plugin for TDERadio"), + TDEAboutData::License_GPL, + "(c) 2004 Martin Witte", + 0, + "http://sourceforge.net/projects/kradio", + 0); + aboutData.addAuthor("Martin Witte", "", "[email protected]"); + + return AboutPageInfo( + new TDERadioAboutWidget(aboutData, TDERadioAboutWidget::AbtTabbed), + i18n("OSS Sound"), + i18n("OSS Sound"), + "kradio_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/tderadio3/plugins/oss-sound/oss-sound.h b/tderadio3/plugins/oss-sound/oss-sound.h new file mode 100644 index 0000000..68f7ce4 --- /dev/null +++ b/tderadio3/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 : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * 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/tderadio3/plugins/oss-sound/po/Makefile.am b/tderadio3/plugins/oss-sound/po/Makefile.am new file mode 100644 index 0000000..d6cceda --- /dev/null +++ b/tderadio3/plugins/oss-sound/po/Makefile.am @@ -0,0 +1,2 @@ +PACKAGE = kradio-oss-sound +POFILES = AUTO diff --git a/tderadio3/plugins/oss-sound/po/de.po b/tderadio3/plugins/oss-sound/po/de.po new file mode 100644 index 0000000..5d3ab49 --- /dev/null +++ b/tderadio3/plugins/oss-sound/po/de.po @@ -0,0 +1,200 @@ +# translation of de.po to +# translation of kradio-oss-sound.po to +# This file is put in the public domain. +# +# Ernst Martin Witte <[email protected]>, 2006. +msgid "" +msgstr "" +"Project-Id-Version: de\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2006-11-12 18:41+0100\n" +"PO-Revision-Date: 2006-11-12 18:24+0100\n" +"Last-Translator: Ernst Martin Witte <[email protected]>\n" +"Language-Team: <[email protected]>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.11.4\n" + +#. i18n: file oss-sound-configuration-ui.ui line 27 +#: rc.cpp:3 rc.cpp:27 oss-sound-configuration-ui.cpp:106 +#, no-c-format +msgid "Devices" +msgstr "Geräte" + +#. i18n: file oss-sound-configuration-ui.ui line 51 +#: rc.cpp:6 rc.cpp:30 oss-sound-configuration-ui.cpp:107 +#, no-c-format +msgid "PCM Device" +msgstr "Gerät" + +#. i18n: file oss-sound-configuration-ui.ui line 59 +#: rc.cpp:9 rc.cpp:33 oss-sound-configuration-ui.cpp:108 +#, no-c-format +msgid "Mixer Device" +msgstr "Mixer Gerätedatei" + +#. i18n: file oss-sound-configuration-ui.ui line 67 +#: rc.cpp:12 rc.cpp:36 oss-sound-configuration-ui.cpp:109 +#, no-c-format +msgid "Buffer Size" +msgstr "Puffergröße" + +#. i18n: file oss-sound-configuration-ui.ui line 75 +#: rc.cpp:15 rc.cpp:39 oss-sound-configuration-ui.cpp:110 +#, no-c-format +msgid " kB" +msgstr " kB" + +#. i18n: file oss-sound-configuration-ui.ui line 91 +#: rc.cpp:18 rc.cpp:42 oss-sound-configuration-ui.cpp:111 +#, no-c-format +msgid "Extended Options" +msgstr "Erweiterte Optionen" + +#. i18n: file oss-sound-configuration-ui.ui line 105 +#: rc.cpp:21 rc.cpp:45 oss-sound-configuration-ui.cpp:112 +#, no-c-format +msgid "Disable Playback" +msgstr "Wiedergabe abschalten" + +#. i18n: file oss-sound-configuration-ui.ui line 113 +#: rc.cpp:24 rc.cpp:48 oss-sound-configuration-ui.cpp:113 +#, no-c-format +msgid "Disable Capture" +msgstr "Aufnahme abschalten" + +#: _translatorinfo.cpp:1 +msgid "" +"_: NAME OF TRANSLATORS\n" +"Your names" +msgstr "Ernst Martin Witte" + +#: _translatorinfo.cpp:3 +msgid "" +"_: EMAIL OF TRANSLATORS\n" +"Your emails" +msgstr "[email protected]" + +#: 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 +msgid "Cannot open DSP device %1" +msgstr "Die Audio-Gerätedatei %1 kann nicht geöffnet werden" + +#: oss-sound.cpp:599 +msgid "Cannot read DSP capabilities for %1" +msgstr "Kann die Fähigkeiten des Gerätes %1 nicht lesen." + +#: oss-sound.cpp:626 +msgid "Cannot set DSP sample format for %1" +msgstr "Kann das Abtastformat für %1 nicht schreiben" + +#: oss-sound.cpp:631 +msgid "Cannot set number of channels for %1" +msgstr "Kann die Anzahl der Kanäle für %1 nicht festlegen" + +#: oss-sound.cpp:636 +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 +msgid "Cannot set stereo mode for %1" +msgstr "Kann den Stereo-Modus für %1 nicht setzen" + +#: oss-sound.cpp:653 +msgid "Cannot set sample size for %1" +msgstr "Kann das Quantisierung-Format für %1 nicht setzen" + +#: oss-sound.cpp:662 +msgid "Cannot set buffers for %1" +msgstr "Kann die Puffer für %1 nicht einstellen" + +#: oss-sound.cpp:667 +msgid "Cannot read buffer size for %1" +msgstr "Kann die Puffergröße für %1 nicht lesen" + +#: 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 +msgid "Cannot open mixer device %1" +msgstr "Die Mixergerätedatei %1 kann nicht geöffnet werden" + +#: oss-sound.cpp:757 +msgid "OSSSoundDevice::getMixerChannels: Cannot open mixer device %1" +msgstr "OSSSoundDevice::getMixerChannels: Kann den Mixer %1 nicht öffnen" + +#: oss-sound.cpp:771 +msgid "" +"OSSSoundDevice::getMixerChannels: Cannot read mixer device mask on device %1" +msgstr "" +"OSSSoundDevice::getMixerChannels: Kann die Gerätemaske des Mixers %1 nicht " +"lesen" + +#: 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 +msgid "OSS Sound Device %1" +msgstr "OSS Sound Gerät %1" diff --git a/tderadio3/plugins/oss-sound/po/ru.po b/tderadio3/plugins/oss-sound/po/ru.po new file mode 100644 index 0000000..a42e5ec --- /dev/null +++ b/tderadio3/plugins/oss-sound/po/ru.po @@ -0,0 +1,193 @@ +# translation of ru.po to +# translation of kradio-oss-sound.po to +# This file is put in the public domain. +# Алексей Кузнецов <[email protected]>, 2006. +# +msgid "" +msgstr "" +"Project-Id-Version: ru\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2006-11-12 18:20+0100\n" +"PO-Revision-Date: 2006-11-08 12:45+0300\n" +"Last-Translator: Алексей Кузнецов <[email protected]>\n" +"Language-Team: <[email protected]>\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" + +#. i18n: file oss-sound-configuration-ui.ui line 27 +#: rc.cpp:3 rc.cpp:27 oss-sound-configuration-ui.cpp:106 +#, no-c-format +msgid "Devices" +msgstr "Устройства" + +#. i18n: file oss-sound-configuration-ui.ui line 51 +#: rc.cpp:6 rc.cpp:30 oss-sound-configuration-ui.cpp:107 +#, no-c-format +msgid "PCM Device" +msgstr "Устройство PCM" + +#. i18n: file oss-sound-configuration-ui.ui line 59 +#: rc.cpp:9 rc.cpp:33 oss-sound-configuration-ui.cpp:108 +#, no-c-format +msgid "Mixer Device" +msgstr "Устройство микшера" + +#. i18n: file oss-sound-configuration-ui.ui line 67 +#: rc.cpp:12 rc.cpp:36 oss-sound-configuration-ui.cpp:109 +#, no-c-format +msgid "Buffer Size" +msgstr "Размер буфера" + +#. i18n: file oss-sound-configuration-ui.ui line 75 +#: rc.cpp:15 rc.cpp:39 oss-sound-configuration-ui.cpp:110 +#, no-c-format +msgid " kB" +msgstr " кБ" + +#. i18n: file oss-sound-configuration-ui.ui line 91 +#: rc.cpp:18 rc.cpp:42 oss-sound-configuration-ui.cpp:111 +#, no-c-format +msgid "Extended Options" +msgstr "Дополнительные параметры" + +#. i18n: file oss-sound-configuration-ui.ui line 105 +#: rc.cpp:21 rc.cpp:45 oss-sound-configuration-ui.cpp:112 +#, no-c-format +msgid "Disable Playback" +msgstr "Запретить &воспроизведение" + +#. i18n: file oss-sound-configuration-ui.ui line 113 +#: rc.cpp:24 rc.cpp:48 oss-sound-configuration-ui.cpp:113 +#, no-c-format +msgid "Disable Capture" +msgstr "Запретить &запись" + +#: _translatorinfo.cpp:1 +msgid "" +"_: NAME OF TRANSLATORS\n" +"Your names" +msgstr "Алексей Кузнецов" + +#: _translatorinfo.cpp:3 +msgid "" +"_: EMAIL OF TRANSLATORS\n" +"Your emails" +msgstr "[email protected]" + +#: 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 +msgid "Cannot open DSP device %1" +msgstr "Не могу открыть устройство звуковой платы %1" + +#: oss-sound.cpp:599 +msgid "Cannot read DSP capabilities for %1" +msgstr "Не могу узнать возможности звуковой платы %1" + +#: oss-sound.cpp:626 +msgid "Cannot set DSP sample format for %1" +msgstr "Не могу установить формат данных для звуковой платы %1" + +#: oss-sound.cpp:631 +msgid "Cannot set number of channels for %1" +msgstr "Не могу установить число каналов для звуковой платы %1" + +#: oss-sound.cpp:636 +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 +msgid "Cannot set stereo mode for %1" +msgstr "Не могу установить стерео режим для звуковой платы %1" + +#: oss-sound.cpp:653 +msgid "Cannot set sample size for %1" +msgstr "Не могу установить размер элемента выборки для звуковой платы %1" + +#: oss-sound.cpp:662 +msgid "Cannot set buffers for %1" +msgstr "Не могу установить буферы для звуковой платы %1" + +#: oss-sound.cpp:667 +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 +msgid "Cannot open mixer device %1" +msgstr "Не могу открыть устройство микшера %1" + +#: oss-sound.cpp:757 +msgid "OSSSoundDevice::getMixerChannels: Cannot open mixer device %1" +msgstr "" +"OSSSoundDevice::getMixerChannels: Не могу открыть устройство микшера %1" + +#: oss-sound.cpp:771 +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 +msgid "OSS Sound Device %1" +msgstr "Устройство OSS: %1" |