summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/CMakeL10n.txt3
-rw-r--r--plugins/Makefile.am4
-rw-r--r--plugins/alsa-sound/CMakeL10n.txt6
-rw-r--r--plugins/alsa-sound/Makefile.am20
-rw-r--r--plugins/alsa-sound/alsa-config-mixer-setting.cpp67
-rw-r--r--plugins/alsa-sound/alsa-config-mixer-setting.h45
-rw-r--r--plugins/alsa-sound/alsa-mixer-element-ui.ui270
-rw-r--r--plugins/alsa-sound/alsa-mixer-element.cpp139
-rw-r--r--plugins/alsa-sound/alsa-mixer-element.h63
-rw-r--r--plugins/alsa-sound/alsa-sound-configuration-ui.ui319
-rw-r--r--plugins/alsa-sound/alsa-sound-configuration.cpp353
-rw-r--r--plugins/alsa-sound/alsa-sound-configuration.h84
-rw-r--r--plugins/alsa-sound/alsa-sound.cpp1562
-rw-r--r--plugins/alsa-sound/alsa-sound.h297
-rw-r--r--plugins/alsa-sound/icons/Makefile.am7
-rw-r--r--plugins/alsa-sound/icons/alsa.pngbin0 -> 3322 bytes
-rw-r--r--plugins/alsa-sound/icons/alsa2.pngbin0 -> 2389 bytes
-rw-r--r--plugins/alsa-sound/icons/hi16-action-tderadio_alsa.pngbin0 -> 392 bytes
-rw-r--r--plugins/alsa-sound/icons/hi16-action-tderadio_alsa2.pngbin0 -> 603 bytes
-rw-r--r--plugins/alsa-sound/icons/hi22-action-tderadio_alsa.pngbin0 -> 464 bytes
-rw-r--r--plugins/alsa-sound/icons/hi22-action-tderadio_alsa2.pngbin0 -> 918 bytes
-rw-r--r--plugins/alsa-sound/icons/hi32-action-tderadio_alsa.pngbin0 -> 607 bytes
-rw-r--r--plugins/alsa-sound/icons/hi32-action-tderadio_alsa2.pngbin0 -> 1360 bytes
-rw-r--r--plugins/alsa-sound/icons/hi48-action-tderadio_alsa.pngbin0 -> 905 bytes
-rw-r--r--plugins/alsa-sound/icons/hi48-action-tderadio_alsa2.pngbin0 -> 1954 bytes
-rw-r--r--plugins/alsa-sound/icons/hi64-action-tderadio_alsa.pngbin0 -> 1280 bytes
-rw-r--r--plugins/alsa-sound/icons/hi64-action-tderadio_alsa2.pngbin0 -> 2583 bytes
-rw-r--r--plugins/alsa-sound/po/Makefile.am3
-rw-r--r--plugins/alsa-sound/po/de.po285
-rw-r--r--plugins/alsa-sound/po/ru.po284
-rw-r--r--plugins/alsa-sound/po/tderadio-alsa-sound.pot275
-rw-r--r--plugins/gui-docking-menu/CMakeL10n.txt6
-rw-r--r--plugins/gui-docking-menu/Makefile.am18
-rw-r--r--plugins/gui-docking-menu/docking-configuration.cpp114
-rw-r--r--plugins/gui-docking-menu/docking-configuration.h55
-rw-r--r--plugins/gui-docking-menu/docking.cpp674
-rw-r--r--plugins/gui-docking-menu/docking.h190
-rw-r--r--plugins/gui-docking-menu/po/Makefile.am2
-rw-r--r--plugins/gui-docking-menu/po/de.po123
-rw-r--r--plugins/gui-docking-menu/po/ru.po121
-rw-r--r--plugins/gui-docking-menu/po/tderadio-gui-docking-menu.pot119
-rw-r--r--plugins/gui-error-log/CMakeL10n.txt6
-rw-r--r--plugins/gui-error-log/Makefile.am17
-rw-r--r--plugins/gui-error-log/errorlog.cpp263
-rw-r--r--plugins/gui-error-log/errorlog.h90
-rw-r--r--plugins/gui-error-log/po/Makefile.am2
-rw-r--r--plugins/gui-error-log/po/de.po86
-rw-r--r--plugins/gui-error-log/po/ru.po87
-rw-r--r--plugins/gui-error-log/po/tderadio-gui-error-log.pot82
-rw-r--r--plugins/gui-quickbar/CMakeL10n.txt6
-rw-r--r--plugins/gui-quickbar/Makefile.am18
-rw-r--r--plugins/gui-quickbar/buttonflowlayout.cpp268
-rw-r--r--plugins/gui-quickbar/buttonflowlayout.h64
-rw-r--r--plugins/gui-quickbar/po/Makefile.am2
-rw-r--r--plugins/gui-quickbar/po/de.po56
-rw-r--r--plugins/gui-quickbar/po/ru.po56
-rw-r--r--plugins/gui-quickbar/po/tderadio-gui-quickbar.pot52
-rw-r--r--plugins/gui-quickbar/quickbar-configuration.cpp35
-rw-r--r--plugins/gui-quickbar/quickbar-configuration.h37
-rw-r--r--plugins/gui-quickbar/quickbar.cpp424
-rw-r--r--plugins/gui-quickbar/quickbar.h139
-rw-r--r--plugins/gui-standard-display/CMakeL10n.txt6
-rw-r--r--plugins/gui-standard-display/Makefile.am22
-rw-r--r--plugins/gui-standard-display/displaycfg.cpp145
-rw-r--r--plugins/gui-standard-display/displaycfg.h73
-rw-r--r--plugins/gui-standard-display/displaycfg_interfaces.cpp69
-rw-r--r--plugins/gui-standard-display/displaycfg_interfaces.h82
-rw-r--r--plugins/gui-standard-display/po/Makefile.am2
-rw-r--r--plugins/gui-standard-display/po/de.po210
-rw-r--r--plugins/gui-standard-display/po/nl.po208
-rw-r--r--plugins/gui-standard-display/po/ru.po209
-rw-r--r--plugins/gui-standard-display/po/tderadio-gui-standard-display.pot207
-rw-r--r--plugins/gui-standard-display/radioview-configuration.cpp116
-rw-r--r--plugins/gui-standard-display/radioview-configuration.h62
-rw-r--r--plugins/gui-standard-display/radioview.cpp807
-rw-r--r--plugins/gui-standard-display/radioview.h208
-rw-r--r--plugins/gui-standard-display/radioview_element.cpp34
-rw-r--r--plugins/gui-standard-display/radioview_element.h67
-rw-r--r--plugins/gui-standard-display/radioview_frequencyradio.cpp443
-rw-r--r--plugins/gui-standard-display/radioview_frequencyradio.h109
-rw-r--r--plugins/gui-standard-display/radioview_frequencyseeker.cpp250
-rw-r--r--plugins/gui-standard-display/radioview_frequencyseeker.h79
-rw-r--r--plugins/gui-standard-display/radioview_seekinterface.ui167
-rw-r--r--plugins/gui-standard-display/radioview_seekinterface.ui.h21
-rw-r--r--plugins/gui-standard-display/radioview_volume.cpp141
-rw-r--r--plugins/gui-standard-display/radioview_volume.h76
-rw-r--r--plugins/lirc/CMakeL10n.txt6
-rw-r--r--plugins/lirc/Makefile.am28
-rw-r--r--plugins/lirc/default-dot-lircrc6
-rw-r--r--plugins/lirc/lirc-configuration-ui.ui110
-rw-r--r--plugins/lirc/lirc-configuration.cpp193
-rw-r--r--plugins/lirc/lirc-configuration.h61
-rw-r--r--plugins/lirc/lircsupport.cpp553
-rw-r--r--plugins/lirc/lircsupport.h160
-rw-r--r--plugins/lirc/listviewitem_lirc.cpp51
-rw-r--r--plugins/lirc/listviewitem_lirc.h52
-rw-r--r--plugins/lirc/po/Makefile.am2
-rw-r--r--plugins/lirc/po/de.po208
-rw-r--r--plugins/lirc/po/pt.po195
-rw-r--r--plugins/lirc/po/ru.po202
-rw-r--r--plugins/lirc/po/tderadio-lirc.pot198
-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
-rw-r--r--plugins/radio/CMakeL10n.txt6
-rw-r--r--plugins/radio/Makefile.am18
-rw-r--r--plugins/radio/po/Makefile.am2
-rw-r--r--plugins/radio/po/de.po168
-rw-r--r--plugins/radio/po/ru.po171
-rw-r--r--plugins/radio/po/tderadio-radio.pot164
-rw-r--r--plugins/radio/radio-configuration-ui.ui771
-rw-r--r--plugins/radio/radio-configuration.cpp592
-rw-r--r--plugins/radio/radio-configuration.h107
-rw-r--r--plugins/radio/radio.cpp497
-rw-r--r--plugins/radio/radio.h167
-rw-r--r--plugins/recording/CMakeL10n.txt6
-rw-r--r--plugins/recording/Makefile.am22
-rw-r--r--plugins/recording/encoder.cpp172
-rw-r--r--plugins/recording/encoder.h101
-rw-r--r--plugins/recording/encoder_mp3.cpp214
-rw-r--r--plugins/recording/encoder_mp3.h56
-rw-r--r--plugins/recording/encoder_ogg.cpp250
-rw-r--r--plugins/recording/encoder_ogg.h55
-rw-r--r--plugins/recording/encoder_pcm.cpp78
-rw-r--r--plugins/recording/encoder_pcm.h46
-rw-r--r--plugins/recording/icons/Makefile.am2
-rw-r--r--plugins/recording/icons/hi16-action-tderadio_record.pngbin0 -> 399 bytes
-rw-r--r--plugins/recording/icons/hi16-app-tderadio_plus_rec.pngbin0 -> 917 bytes
-rw-r--r--plugins/recording/icons/hi22-action-tderadio_record.pngbin0 -> 573 bytes
-rw-r--r--plugins/recording/icons/hi22-app-tderadio_plus_rec.pngbin0 -> 1433 bytes
-rw-r--r--plugins/recording/icons/hi256-action-tderadio_record.pngbin0 -> 5458 bytes
-rw-r--r--plugins/recording/icons/hi32-action-tderadio_record.pngbin0 -> 808 bytes
-rw-r--r--plugins/recording/icons/hi32-app-tderadio_plus_rec.pngbin0 -> 2321 bytes
-rw-r--r--plugins/recording/icons/hi48-action-tderadio_record.pngbin0 -> 1232 bytes
-rw-r--r--plugins/recording/icons/hi48-app-tderadio_plus_rec.pngbin0 -> 4193 bytes
-rw-r--r--plugins/recording/icons/hi64-action-tderadio_record.pngbin0 -> 1534 bytes
-rw-r--r--plugins/recording/icons/hi64-app-tderadio_plus_rec.pngbin0 -> 6249 bytes
-rw-r--r--plugins/recording/po/Makefile.am2
-rw-r--r--plugins/recording/po/de.po396
-rw-r--r--plugins/recording/po/ru.po391
-rw-r--r--plugins/recording/po/tderadio-recording.pot378
-rw-r--r--plugins/recording/reccfg_interfaces.cpp151
-rw-r--r--plugins/recording/reccfg_interfaces.h102
-rw-r--r--plugins/recording/recording-config.cpp215
-rw-r--r--plugins/recording/recording-config.h73
-rw-r--r--plugins/recording/recording-configuration-ui.ui726
-rw-r--r--plugins/recording/recording-configuration.cpp414
-rw-r--r--plugins/recording/recording-configuration.h127
-rw-r--r--plugins/recording/recording-datamonitor.cpp278
-rw-r--r--plugins/recording/recording-datamonitor.h67
-rw-r--r--plugins/recording/recording-monitor.cpp402
-rw-r--r--plugins/recording/recording-monitor.h125
-rw-r--r--plugins/recording/recording.cpp731
-rw-r--r--plugins/recording/recording.h149
-rw-r--r--plugins/recording/soundstreamevent.h87
-rw-r--r--plugins/soundserver/CMakeL10n.txt6
-rw-r--r--plugins/soundserver/Makefile.am18
-rw-r--r--plugins/soundserver/po/Makefile.am2
-rw-r--r--plugins/soundserver/po/de.po44
-rw-r--r--plugins/soundserver/po/ru.po42
-rw-r--r--plugins/soundserver/po/tderadio-soundserver.pot40
-rw-r--r--plugins/soundserver/soundserver.cpp74
-rw-r--r--plugins/soundserver/soundserver.h54
-rw-r--r--plugins/streaming/CMakeL10n.txt6
-rw-r--r--plugins/streaming/Makefile.am18
-rw-r--r--plugins/streaming/icons/Makefile.am2
-rw-r--r--plugins/streaming/icons/hi16-action-tderadio_streaming.pngbin0 -> 604 bytes
-rw-r--r--plugins/streaming/icons/hi22-action-tderadio_streaming.pngbin0 -> 860 bytes
-rw-r--r--plugins/streaming/icons/hi32-action-tderadio_streaming.pngbin0 -> 1251 bytes
-rw-r--r--plugins/streaming/icons/hi48-action-tderadio_streaming.pngbin0 -> 1909 bytes
-rw-r--r--plugins/streaming/icons/hi64-action-tderadio_streaming.pngbin0 -> 2553 bytes
-rw-r--r--plugins/streaming/po/Makefile.am2
-rw-r--r--plugins/streaming/po/de.po206
-rw-r--r--plugins/streaming/po/ru.po206
-rw-r--r--plugins/streaming/po/tderadio-streaming.pot200
-rw-r--r--plugins/streaming/streaming-configuration-ui.ui769
-rw-r--r--plugins/streaming/streaming-configuration.cpp567
-rw-r--r--plugins/streaming/streaming-configuration.h98
-rw-r--r--plugins/streaming/streaming-job.cpp279
-rw-r--r--plugins/streaming/streaming-job.h101
-rw-r--r--plugins/streaming/streaming.cpp526
-rw-r--r--plugins/streaming/streaming.h146
-rw-r--r--plugins/timecontrol/CMakeL10n.txt6
-rw-r--r--plugins/timecontrol/Makefile.am17
-rw-r--r--plugins/timecontrol/icons/Makefile.am7
-rw-r--r--plugins/timecontrol/icons/hi16-action-tderadio_kalarm.pngbin0 -> 430 bytes
-rw-r--r--plugins/timecontrol/icons/hi16-action-tderadio_zzz.pngbin0 -> 295 bytes
-rw-r--r--plugins/timecontrol/icons/hi22-action-tderadio_kalarm.pngbin0 -> 823 bytes
-rw-r--r--plugins/timecontrol/icons/hi22-action-tderadio_zzz.pngbin0 -> 770 bytes
-rw-r--r--plugins/timecontrol/icons/hi32-action-tderadio_kalarm.pngbin0 -> 1544 bytes
-rw-r--r--plugins/timecontrol/icons/hi32-action-tderadio_zzz.pngbin0 -> 1304 bytes
-rw-r--r--plugins/timecontrol/icons/hi48-action-tderadio_kalarm.pngbin0 -> 1927 bytes
-rw-r--r--plugins/timecontrol/icons/hi48-action-tderadio_zzz.pngbin0 -> 2018 bytes
-rw-r--r--plugins/timecontrol/icons/tderadio_zzz.pngbin0 -> 14219 bytes
-rw-r--r--plugins/timecontrol/po/Makefile.am2
-rw-r--r--plugins/timecontrol/po/de.po116
-rw-r--r--plugins/timecontrol/po/pt.po111
-rw-r--r--plugins/timecontrol/po/ru.po116
-rw-r--r--plugins/timecontrol/po/tderadio-timecontrol.pot114
-rw-r--r--plugins/timecontrol/timecontrol-configuration-ui.ui450
-rw-r--r--plugins/timecontrol/timecontrol-configuration.cpp425
-rw-r--r--plugins/timecontrol/timecontrol-configuration.h91
-rw-r--r--plugins/timecontrol/timecontrol.cpp301
-rw-r--r--plugins/timecontrol/timecontrol.h96
-rw-r--r--plugins/timeshifter/CMakeL10n.txt6
-rw-r--r--plugins/timeshifter/Makefile.am18
-rw-r--r--plugins/timeshifter/icons/Makefile.am2
-rw-r--r--plugins/timeshifter/icons/hi16-action-tderadio_pause.pngbin0 -> 782 bytes
-rw-r--r--plugins/timeshifter/icons/hi16-app-tderadio_plus_pause.pngbin0 -> 984 bytes
-rw-r--r--plugins/timeshifter/icons/hi22-action-tderadio_pause.pngbin0 -> 1104 bytes
-rw-r--r--plugins/timeshifter/icons/hi22-app-tderadio_plus_pause.pngbin0 -> 1573 bytes
-rw-r--r--plugins/timeshifter/icons/hi32-action-tderadio_pause.pngbin0 -> 1248 bytes
-rw-r--r--plugins/timeshifter/icons/hi32-app-tderadio_plus_pause.pngbin0 -> 2601 bytes
-rw-r--r--plugins/timeshifter/icons/hi48-app-tderadio_plus_pause.pngbin0 -> 4637 bytes
-rw-r--r--plugins/timeshifter/icons/hi64-app-tderadio_plus_pause.pngbin0 -> 6527 bytes
-rw-r--r--plugins/timeshifter/po/Makefile.am3
-rw-r--r--plugins/timeshifter/po/de.po100
-rw-r--r--plugins/timeshifter/po/ru.po98
-rw-r--r--plugins/timeshifter/po/tderadio-timeshifter.pot94
-rw-r--r--plugins/timeshifter/timeshifter-configuration-ui.ui225
-rw-r--r--plugins/timeshifter/timeshifter-configuration.cpp203
-rw-r--r--plugins/timeshifter/timeshifter-configuration.h84
-rw-r--r--plugins/timeshifter/timeshifter.cpp455
-rw-r--r--plugins/timeshifter/timeshifter.h121
-rw-r--r--plugins/v4lradio/CMakeL10n.txt6
-rw-r--r--plugins/v4lradio/Makefile.am18
-rw-r--r--plugins/v4lradio/linux/videodev.h426
-rw-r--r--plugins/v4lradio/linux/videodev2.h934
-rw-r--r--plugins/v4lradio/po/Makefile.am3
-rw-r--r--plugins/v4lradio/po/de.po336
-rw-r--r--plugins/v4lradio/po/pt.po321
-rw-r--r--plugins/v4lradio/po/ru.po336
-rw-r--r--plugins/v4lradio/po/tderadio-v4lradio.pot324
-rw-r--r--plugins/v4lradio/v4lcfg_interfaces.cpp193
-rw-r--r--plugins/v4lradio/v4lcfg_interfaces.h151
-rw-r--r--plugins/v4lradio/v4lradio-configuration-ui.ui956
-rw-r--r--plugins/v4lradio/v4lradio-configuration.cpp648
-rw-r--r--plugins/v4lradio/v4lradio-configuration.h148
-rw-r--r--plugins/v4lradio/v4lradio.cpp1622
-rw-r--r--plugins/v4lradio/v4lradio.h266
252 files changed, 37082 insertions, 0 deletions
diff --git a/plugins/CMakeL10n.txt b/plugins/CMakeL10n.txt
new file mode 100644
index 0000000..b585ce4
--- /dev/null
+++ b/plugins/CMakeL10n.txt
@@ -0,0 +1,3 @@
+##### create translation templates ##############
+
+tde_l10n_auto_add_subdirectories( )
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
new file mode 100644
index 0000000..3e9e46f
--- /dev/null
+++ b/plugins/Makefile.am
@@ -0,0 +1,4 @@
+INCLUDES =
+METASOURCES = AUTO
+SUBDIRS = gui-docking-menu gui-error-log gui-quickbar gui-standard-display $(PLUGIN_LIRC) \
+ radio timecontrol v4lradio $(PLUGIN_OSS) soundserver recording timeshifter $(PLUGIN_ALSA) streaming
diff --git a/plugins/alsa-sound/CMakeL10n.txt b/plugins/alsa-sound/CMakeL10n.txt
new file mode 100644
index 0000000..cf48935
--- /dev/null
+++ b/plugins/alsa-sound/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-alsa-sound"
+ DESTINATION "po"
+)
diff --git a/plugins/alsa-sound/Makefile.am b/plugins/alsa-sound/Makefile.am
new file mode 100644
index 0000000..dfc2b0b
--- /dev/null
+++ b/plugins/alsa-sound/Makefile.am
@@ -0,0 +1,20 @@
+SUBDIRS = po icons .
+
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = libalsa-sound.la
+libalsa_sound_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+noinst_HEADERS = alsa-sound.h alsa-sound-configuration.h alsa-mixer-element.h \
+ alsa-config-mixer-setting.h
+libalsa_sound_la_SOURCES = alsa-sound.cpp alsa-sound-configuration-ui.ui \
+ alsa-sound-configuration.cpp alsa-mixer-element-ui.ui alsa-mixer-element.cpp \
+ alsa-config-mixer-setting.cpp
+libalsa_sound_la_LIBADD = $(LIB_ALSA)
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-alsa-sound.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-alsa-sound.pot
diff --git a/plugins/alsa-sound/alsa-config-mixer-setting.cpp b/plugins/alsa-sound/alsa-config-mixer-setting.cpp
new file mode 100644
index 0000000..4c39ff9
--- /dev/null
+++ b/plugins/alsa-sound/alsa-config-mixer-setting.cpp
@@ -0,0 +1,67 @@
+/***************************************************************************
+ alsa-config-mixer-setting.cpp - description
+ -------------------
+ begin : Mon Aug 15 2005
+ copyright : (C) 2005 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 "alsa-config-mixer-setting.h"
+
+#include <tdeconfig.h>
+
+AlsaConfigMixerSetting::AlsaConfigMixerSetting()
+ : m_card(-1),
+ m_name(TQString()),
+ m_use(false),
+ m_active(false),
+ m_volume(-1)
+{
+}
+
+AlsaConfigMixerSetting::AlsaConfigMixerSetting(TDEConfig *c, const TQString &prefix)
+{
+ m_card = c->readNumEntry (prefix+"card", -1);
+ m_name = c->readEntry (prefix+"name", TQString());
+ m_use = c->readBoolEntry (prefix+"use", false);
+ m_active = c->readBoolEntry (prefix+"active", false);
+ m_volume = c->readDoubleNumEntry(prefix+"volume", 0);
+}
+
+AlsaConfigMixerSetting::AlsaConfigMixerSetting(int card, const TQString &name, bool use, bool active, float volume)
+ : m_card(card),
+ m_name(name),
+ m_use(use),
+ m_active(active),
+ m_volume(volume)
+{
+}
+
+AlsaConfigMixerSetting::~AlsaConfigMixerSetting()
+{
+}
+
+TQString AlsaConfigMixerSetting::getIDString(int card, const TQString &name)
+{
+ return TQString::number(card) + "-" + name;
+}
+
+void AlsaConfigMixerSetting::saveState(TDEConfig *c, const TQString &prefix) const
+{
+ c->writeEntry(prefix+"card", m_card);
+ c->writeEntry(prefix+"name", m_name);
+ c->writeEntry(prefix+"use", m_use);
+ c->writeEntry(prefix+"active", m_active);
+ c->writeEntry(prefix+"volume", m_volume);
+}
+
+
diff --git a/plugins/alsa-sound/alsa-config-mixer-setting.h b/plugins/alsa-sound/alsa-config-mixer-setting.h
new file mode 100644
index 0000000..94a995f
--- /dev/null
+++ b/plugins/alsa-sound/alsa-config-mixer-setting.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ alsa-config-mixer-setting.h - description
+ -------------------
+ begin : Mon Aug 15 2005
+ copyright : (C) 2005 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_ALSA_CONFIG_MIXER_SETTING_H
+#define __KRADIO_ALSA_CONFIG_MIXER_SETTING_H
+
+#include <tqstring.h>
+
+class TDEConfig;
+
+class AlsaConfigMixerSetting
+{
+public:
+ AlsaConfigMixerSetting();
+ AlsaConfigMixerSetting(TDEConfig *c, const TQString &prefix);
+ AlsaConfigMixerSetting(int card, const TQString &name, bool use, bool active, float volume);
+ ~AlsaConfigMixerSetting();
+
+ TQString getIDString() const { return getIDString(m_card, m_name); }
+ static TQString getIDString(int card, const TQString &m_name);
+
+ void saveState(TDEConfig *c, const TQString &prefix) const;
+
+ int m_card;
+ TQString m_name;
+ bool m_use;
+ bool m_active;
+ float m_volume;
+};
+
+#endif
diff --git a/plugins/alsa-sound/alsa-mixer-element-ui.ui b/plugins/alsa-sound/alsa-mixer-element-ui.ui
new file mode 100644
index 0000000..87cdfa5
--- /dev/null
+++ b/plugins/alsa-sound/alsa-mixer-element-ui.ui
@@ -0,0 +1,270 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>AlsaMixerElementUI</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>AlsaMixerElementUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>124</width>
+ <height>153</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Form1</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout16</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer>
+ <property name="name">
+ <cstring>spacer23</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>1</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQSlider">
+ <property name="name">
+ <cstring>m_sliderVolume</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer23_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>1</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>11</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>m_spinboxVolume</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3_4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>11</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>m_checkboxActive</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>O&amp;n</string>
+ </property>
+ <property name="accel">
+ <string>Alt+N</string>
+ </property>
+ </widget>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>m_checkboxOverride</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Use</string>
+ </property>
+ <property name="accel">
+ <string>Alt+U</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>m_labelMixerElementName</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>MixerName</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="2"/>
+<includes>
+ <include location="global" impldecl="in implementation">knuminput.h</include>
+</includes>
+</UI>
diff --git a/plugins/alsa-sound/alsa-mixer-element.cpp b/plugins/alsa-sound/alsa-mixer-element.cpp
new file mode 100644
index 0000000..53a7216
--- /dev/null
+++ b/plugins/alsa-sound/alsa-mixer-element.cpp
@@ -0,0 +1,139 @@
+/***************************************************************************
+ alsa-mixer-element.cpp - description
+ -------------------
+ begin : Mon Aug 15 2005
+ copyright : (C) 2005 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 "alsa-mixer-element.h"
+
+#include <knuminput.h>
+#include <tqslider.h>
+#include <tqlabel.h>
+#include <tqcheckbox.h>
+
+#include <math.h>
+
+QAlsaMixerElement::QAlsaMixerElement(TQWidget *parent, const TQString &label, bool has_switch, bool has_volume)
+ : AlsaMixerElementUI(parent),
+ m_HasVolume(has_volume),
+ m_HasSwitch(has_switch),
+ m_dirty(false),
+ m_ignore_updates(false)
+{
+ setLabel(label);
+ setVolume(0);
+
+ TQObject::connect(m_spinboxVolume, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT (slotSpinboxValueChanged(int)));
+ TQObject::connect(m_sliderVolume, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT (slotSliderValueChanged(int)));
+
+ if (m_HasVolume) {
+ TQObject::connect(m_checkboxOverride, TQT_SIGNAL(toggled(bool)),
+ m_spinboxVolume, TQT_SLOT (setEnabled(bool)));
+ TQObject::connect(m_checkboxOverride, TQT_SIGNAL(toggled(bool)),
+ m_sliderVolume, TQT_SLOT (setEnabled(bool)));
+ } else {
+ m_spinboxVolume->hide();
+ m_sliderVolume->hide();
+ }
+ if (m_HasSwitch) {
+ TQObject::connect(m_checkboxOverride, TQT_SIGNAL(toggled(bool)),
+ m_checkboxActive, TQT_SLOT (setEnabled(bool)));
+ } else {
+ //m_checkboxActive->hide();
+ m_checkboxActive->setEnabled(false);
+ m_checkboxActive->setChecked(true);
+ }
+
+ connect(m_checkboxOverride, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotSetDirty()));
+ connect(m_checkboxActive, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotSetDirty()));
+ connect(m_spinboxVolume, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotSetDirty()));
+ connect(m_sliderVolume, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotSetDirty()));
+}
+
+
+QAlsaMixerElement::~QAlsaMixerElement()
+{
+}
+
+float QAlsaMixerElement::getVolume() const
+{
+ return ((float)m_spinboxVolume->value())/100.0;
+}
+
+bool QAlsaMixerElement::getActive() const
+{
+ return m_checkboxActive->isChecked();
+}
+
+bool QAlsaMixerElement::getOverride() const
+{
+ return m_checkboxOverride->isChecked();
+}
+
+void QAlsaMixerElement::setLabel(const TQString &label)
+{
+ m_labelMixerElementName->setText(label);
+}
+
+void QAlsaMixerElement::setOverride(bool ov)
+{
+ m_ignore_updates = true;
+ m_checkboxOverride->setChecked(ov);
+ m_ignore_updates = false;
+}
+
+void QAlsaMixerElement::setActive(bool active)
+{
+ m_ignore_updates = true;
+ m_checkboxActive->setChecked(active);
+ m_ignore_updates = false;
+}
+
+void QAlsaMixerElement::setVolume(float vol)
+{
+ m_ignore_updates = true;
+ int v = (int)rint(vol*100 + 0.5);
+ m_sliderVolume->setValue(100 - v);
+ m_spinboxVolume->setValue(v);
+ m_ignore_updates = false;
+}
+
+void QAlsaMixerElement::slotSpinboxValueChanged(int v)
+{
+ m_sliderVolume->setValue(100-v);
+}
+
+void QAlsaMixerElement::slotSliderValueChanged(int v)
+{
+ m_spinboxVolume->setValue(100-v);
+}
+
+
+void QAlsaMixerElement::slotSetDirty()
+{
+ if (!m_dirty && !m_ignore_updates) {
+ m_dirty = true;
+ emit sigDirty();
+ }
+}
+
+
+void QAlsaMixerElement::slotResetDirty()
+{
+ m_dirty = false;
+}
+
+#include "alsa-mixer-element.moc"
diff --git a/plugins/alsa-sound/alsa-mixer-element.h b/plugins/alsa-sound/alsa-mixer-element.h
new file mode 100644
index 0000000..f72e78e
--- /dev/null
+++ b/plugins/alsa-sound/alsa-mixer-element.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+ alsa-mixer-element.h - description
+ -------------------
+ begin : Mon Aug 15 2005
+ copyright : (C) 2005 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_ALSA_MIXER_ELEMENT_H
+#define __KRADIO_ALSA_MIXER_ELEMENT_H
+
+#include "alsa-mixer-element-ui.h"
+
+class QAlsaMixerElement : public AlsaMixerElementUI
+{
+Q_OBJECT
+
+public:
+ QAlsaMixerElement(TQWidget *parent, const TQString &label, bool has_switch, bool has_volume);
+ ~QAlsaMixerElement();
+
+
+ float getVolume() const;
+ bool getActive() const;
+ bool getOverride() const;
+
+ bool isDirty() const { return m_dirty; }
+
+public slots:
+
+ void setLabel(const TQString &label);
+ void setOverride(bool ov);
+ void setActive(bool active);
+ void setVolume(float vol);
+ void slotResetDirty();
+ void slotSetDirty();
+
+protected slots:
+ void slotSpinboxValueChanged(int v);
+ void slotSliderValueChanged(int v);
+
+signals:
+
+ void sigDirty();
+
+protected:
+
+ bool m_HasVolume;
+ bool m_HasSwitch;
+ bool m_dirty;
+ bool m_ignore_updates;
+};
+
+#endif
diff --git a/plugins/alsa-sound/alsa-sound-configuration-ui.ui b/plugins/alsa-sound/alsa-sound-configuration-ui.ui
new file mode 100644
index 0000000..9484f18
--- /dev/null
+++ b/plugins/alsa-sound/alsa-sound-configuration-ui.ui
@@ -0,0 +1,319 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>AlsaSoundConfigurationUI</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>AlsaSoundConfigurationUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>475</width>
+ <height>260</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>AlsaSoundConfigurationUI</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>kTabWidget8</cstring>
+ </property>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Devices</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer114</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout58</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>PCM Capture Card</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="2" column="1">
+ <property name="name">
+ <cstring>m_comboCaptureCard</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="4" column="0">
+ <property name="name">
+ <cstring>textLabel2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Hardware Buffer Size</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="3" column="1">
+ <property name="name">
+ <cstring>m_comboCaptureDevice</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="5" column="1">
+ <property name="name">
+ <cstring>editBufferSize</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> kB</string>
+ </property>
+ <property name="maxValue">
+ <number>1024</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="4" column="1">
+ <property name="name">
+ <cstring>editHWBufferSize</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> kB</string>
+ </property>
+ <property name="maxValue">
+ <number>1024</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="0" column="1">
+ <property name="name">
+ <cstring>m_comboPlaybackCard</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="5" column="0">
+ <property name="name">
+ <cstring>textLabel2_2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Buffer Size</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="1">
+ <property name="name">
+ <cstring>m_comboPlaybackDevice</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2_3</cstring>
+ </property>
+ <property name="text">
+ <string>PCM Playback Device</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel2_4</cstring>
+ </property>
+ <property name="text">
+ <string>PCM Capture Device</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>PCM Playback Card</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>E&amp;xtended Options</string>
+ </attribute>
+ <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 Pla&amp;yback</string>
+ </property>
+ <property name="accel">
+ <string>Alt+Y</string>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>chkDisableCapture</cstring>
+ </property>
+ <property name="text">
+ <string>Disa&amp;ble Capture</string>
+ </property>
+ <property name="accel">
+ <string>Alt+B</string>
+ </property>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer113</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Capture Mixer Settings</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="TQGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>m_groupMixer</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="0"/>
+<includes>
+ <include location="global" impldecl="in implementation">kcombobox.h</include>
+ <include location="global" impldecl="in implementation">knuminput.h</include>
+</includes>
+</UI>
diff --git a/plugins/alsa-sound/alsa-sound-configuration.cpp b/plugins/alsa-sound/alsa-sound-configuration.cpp
new file mode 100644
index 0000000..9a29e43
--- /dev/null
+++ b/plugins/alsa-sound/alsa-sound-configuration.cpp
@@ -0,0 +1,353 @@
+/***************************************************************************
+ alsa-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 <tqgroupbox.h>
+#include <tqlayout.h>
+#include <tqscrollview.h>
+
+#include <kurlrequester.h>
+#include <knuminput.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+#include <ktabwidget.h>
+#include <tdelocale.h>
+
+#include "alsa-mixer-element.h"
+#include "alsa-sound-configuration.h"
+#include "alsa-sound.h"
+
+
+AlsaSoundConfiguration::AlsaSoundConfiguration (TQWidget *parent, AlsaSoundDevice *dev)
+ : AlsaSoundConfigurationUI(parent),
+ m_SoundDevice (dev),
+ m_groupMixerLayout(NULL),
+ m_groupMixerScrollView(NULL),
+ m_groupMixerSubFrame(NULL),
+ m_dirty(true),
+ m_ignore_updates(false)
+{
+ TQObject::connect(m_comboPlaybackCard, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(m_comboCaptureCard, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(m_comboPlaybackDevice, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(m_comboCaptureDevice, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(editHWBufferSize, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(editBufferSize, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(chkDisablePlayback, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(chkDisableCapture, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotSetDirty()));
+
+ TQObject::connect(m_comboPlaybackCard, TQT_SIGNAL(activated(const TQString &)),
+ this, TQT_SLOT(slotPlaybackCardSelected(const TQString &)));
+ TQObject::connect(m_comboCaptureCard, TQT_SIGNAL(activated(const TQString &)),
+ this, TQT_SLOT(slotCaptureCardSelected(const TQString &)));
+
+ m_groupMixer->setColumnLayout(0, Qt::Horizontal );
+
+ TQHBoxLayout *tmp_layout = new TQHBoxLayout( m_groupMixer->layout() );
+
+ m_groupMixerScrollView = new TQScrollView (m_groupMixer);
+ m_groupMixerScrollView->setFrameShape(TQFrame::NoFrame);
+ m_groupMixerScrollView->setFrameShadow(TQFrame::Plain);
+ m_groupMixerScrollView->enableClipper(true);
+ m_groupMixerScrollView->setResizePolicy(TQScrollView::AutoOneFit);
+ //m_groupMixerScrollView->setHScrollBarMode(TQScrollView::AlwaysOn);
+
+ tmp_layout->addWidget(m_groupMixerScrollView);
+
+
+ int card = -1;
+ int ret = 0;
+ int idx_playback = 0;
+ int idx_capture = 0;
+ while ((ret = snd_card_next(&card)) == 0) {
+ char *name = NULL;
+ if (card >= 0 && snd_card_get_longname(card, &name) == 0) {
+ if (name) {
+ m_name2card[name] = card;
+ m_card2name[card] = name;
+ if (listSoundDevices(NULL, NULL, NULL, NULL, card, SND_PCM_STREAM_PLAYBACK)) {
+ m_comboPlaybackCard->insertItem(name);
+ m_playbackCard2idx[card] = idx_playback++;
+ }
+ if (listSoundDevices(NULL, NULL, NULL, NULL, card, SND_PCM_STREAM_CAPTURE)) {
+ m_comboCaptureCard->insertItem(name);
+ m_captureCard2idx[card] = idx_capture++;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+
+ slotCancel();
+}
+
+
+AlsaSoundConfiguration::~AlsaSoundConfiguration ()
+{
+}
+
+
+void AlsaSoundConfiguration::slotPlaybackCardSelected(const TQString &cardname)
+{
+ if (!m_name2card.contains(cardname))
+ return;
+
+ listSoundDevices(m_comboPlaybackDevice, &m_playbackDeviceName2dev, &m_dev2playbackDeviceName, &m_playbackDevice2idx, m_name2card[cardname], SND_PCM_STREAM_PLAYBACK);
+}
+
+
+void AlsaSoundConfiguration::slotCaptureCardSelected(const TQString &cardname)
+{
+ if (!m_name2card.contains(cardname))
+ return;
+
+ saveCaptureMixerSettings();
+
+ listSoundDevices(m_comboCaptureDevice, &m_captureDeviceName2dev, &m_dev2captureDeviceName, &m_captureDevice2idx, m_name2card[cardname], SND_PCM_STREAM_CAPTURE);
+
+ m_currentCaptureCard = m_name2card[cardname];
+
+ TQStringList vol_list, sw_list, all_list;
+ TQMap<TQString, AlsaMixerElement> vol_ch2id, sw_ch2id;
+ AlsaSoundDevice::getCaptureMixerChannels(m_name2card[cardname], NULL, vol_list, vol_ch2id, sw_list, sw_ch2id, &all_list);
+
+ for (TQMapIterator<TQString, QAlsaMixerElement*> it = m_MixerElements.begin(); it != m_MixerElements.end(); ++it) {
+ delete *it;
+ }
+ m_MixerElements.clear();
+
+ if (m_groupMixerSubFrame)
+ delete m_groupMixerSubFrame;
+
+ m_groupMixerSubFrame = new TQFrame(m_groupMixerScrollView->viewport());
+ m_groupMixerSubFrame->setSizePolicy(TQSizePolicy::Maximum, TQSizePolicy::Maximum);
+ m_groupMixerScrollView->addChild(m_groupMixerSubFrame);
+
+ int rows = 1;
+ int cols = (all_list.count()+rows-1)/rows;
+ m_groupMixerLayout = new TQGridLayout( m_groupMixerSubFrame, rows, cols, 0, 0 );
+ m_groupMixerLayout->setAlignment( TQt::AlignBottom );
+
+ int idx = 0;
+ for (TQValueListConstIterator<TQString> it = all_list.begin(); it != all_list.end(); ++it, ++idx) {
+ QAlsaMixerElement *e = new QAlsaMixerElement(m_groupMixerSubFrame, *it,
+ sw_list.contains(*it), vol_list.contains(*it));
+ TQObject::connect(e, TQT_SIGNAL(sigDirty()), this, TQT_SLOT(slotSetDirty()));
+ m_groupMixerLayout->addWidget(e, idx > cols, idx % cols);
+ e->show();
+ m_MixerElements.insert(*it, e);
+ }
+ restoreCaptureMixerSettings();
+ m_groupMixerSubFrame->show();
+}
+
+void AlsaSoundConfiguration::saveCaptureMixerSettings()
+{
+ for (TQMapIterator<TQString, QAlsaMixerElement*> it = m_MixerElements.begin(); it != m_MixerElements.end(); ++it) {
+ const TQString &name = it.key();
+ int card = m_currentCaptureCard;
+ TQString id = AlsaConfigMixerSetting::getIDString(card, name);
+ QAlsaMixerElement *e = *it;
+ float vol = e->getVolume();
+ bool use = e->getOverride();
+ bool active = e->getActive();
+ e->slotResetDirty();
+ m_MixerSettings[id] = AlsaConfigMixerSetting(card,name,use,active,vol);
+ }
+}
+
+void AlsaSoundConfiguration::restoreCaptureMixerSettings()
+{
+ for (TQMapIterator<TQString, QAlsaMixerElement*> it = m_MixerElements.begin(); it != m_MixerElements.end(); ++it) {
+ const TQString &name = it.key();
+ int card = m_currentCaptureCard;
+ TQString id = AlsaConfigMixerSetting::getIDString(card, name);
+ QAlsaMixerElement *e = *it;
+
+ if (m_MixerSettings.contains(id)) {
+ const AlsaConfigMixerSetting &s = m_MixerSettings[id];
+ e->setVolume(s.m_volume);
+ e->setOverride(s.m_use);
+ e->setActive(s.m_active);
+ e->slotResetDirty();
+ } else {
+ if (name == "ADC") {
+ e->setOverride(true);
+ e->setActive(true);
+ e->setVolume(1.0);
+ }
+ else if (name == "Digital") {
+ e->setOverride(true);
+ e->setActive(true);
+ e->setVolume(1.0);
+ }
+ else if (name == "Wave") {
+ e->setOverride(true);
+ e->setActive(false);
+ e->setVolume(0);
+ }
+ else if (name == "Capture") {
+ e->setOverride(true);
+ e->setActive(true);
+ e->setVolume(0.01);
+ }
+ e->slotSetDirty();
+ }
+ }
+}
+
+int AlsaSoundConfiguration::listSoundDevices(KComboBox *combobox, TQMap<TQString, int> *devname2dev, TQMap<int, TQString> *dev2devname, TQMap<int, int> *dev2idx, int card, snd_pcm_stream_t stream)
+{
+ snd_ctl_t *handle = NULL;
+ int dev = -1;
+ snd_ctl_card_info_t *info = NULL;
+ snd_pcm_info_t *pcminfo = NULL;
+
+ snd_ctl_card_info_alloca(&info);
+ snd_pcm_info_alloca (&pcminfo);
+
+ TQString ctlname = "hw:"+TQString::number(card);
+
+ if (combobox)
+ combobox->clear();
+ if (devname2dev)
+ devname2dev->clear();
+ if (dev2devname)
+ dev2devname->clear();
+ if (dev2idx)
+ dev2idx->clear();
+
+ int count = 0;
+
+ if (snd_ctl_open (&handle, ctlname.ascii(), 0) == 0) {
+ if (snd_ctl_card_info(handle, info) == 0) {
+
+ dev = -1;
+ while (1) {
+ if (snd_ctl_pcm_next_device(handle, &dev) < 0) {
+ //logError("snd_ctl_pcm_next_device");
+ }
+ if (dev < 0)
+ break;
+ snd_pcm_info_set_device(pcminfo, dev);
+ snd_pcm_info_set_subdevice(pcminfo, 0);
+ snd_pcm_info_set_stream(pcminfo, stream);
+ int err = 0;
+ if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
+ if (err != -ENOENT) {
+ //logError(TQString("control digital audio info (%1): %2").arg(card).arg(snd_strerror(err)));
+ }
+ continue;
+ }
+ const char *dev_name = snd_pcm_info_get_name(pcminfo);
+ TQString devname = i18n("context-card-plus-device-number", "%1 device %2").arg(dev_name).arg(dev);
+ if (combobox)
+ combobox->insertItem(devname);
+ if (devname2dev)
+ (*devname2dev)[devname] = dev;
+ if (dev2devname)
+ (*dev2devname)[dev] = devname;
+ if (dev2idx)
+ (*dev2idx)[dev] = count;
+ ++count;
+ }
+ }
+ snd_ctl_close(handle);
+ }
+ return count;
+}
+
+void AlsaSoundConfiguration::slotOK()
+{
+ if (!m_dirty)
+ return;
+
+ if (m_SoundDevice) {
+ m_SoundDevice->setHWBufferSize ( editHWBufferSize ->value() * 1024);
+ m_SoundDevice->setBufferSize ( editBufferSize ->value() * 1024);
+ m_SoundDevice->enablePlayback (!chkDisablePlayback->isChecked());
+ m_SoundDevice->enableCapture (!chkDisableCapture ->isChecked());
+
+ int card = m_name2card[m_comboPlaybackCard->currentText()];
+ int device = m_playbackDeviceName2dev[m_comboPlaybackDevice->currentText()];
+ m_SoundDevice->setPlaybackDevice( card, device);
+ card = m_name2card[m_comboCaptureCard->currentText()];
+ device = m_captureDeviceName2dev[m_comboCaptureDevice->currentText()];
+ m_SoundDevice->setCaptureDevice ( card, device);
+
+ saveCaptureMixerSettings();
+ m_SoundDevice->setCaptureMixerSettings(m_MixerSettings);
+ }
+ m_dirty = false;
+}
+
+
+void AlsaSoundConfiguration::slotCancel()
+{
+ if (!m_dirty)
+ return;
+ m_ignore_updates = true;
+
+ int card = m_SoundDevice ? m_SoundDevice->getPlaybackCard() : 0;
+ int dev = m_SoundDevice ? m_SoundDevice->getPlaybackDevice() : 0;
+ m_comboPlaybackCard ->setCurrentItem(m_playbackCard2idx[card]);
+ slotPlaybackCardSelected(m_comboPlaybackCard->currentText());
+ m_comboPlaybackDevice->setCurrentItem(m_playbackDevice2idx[dev]);
+
+ card = m_SoundDevice ? m_SoundDevice->getCaptureCard() : 0;
+ dev = m_SoundDevice ? m_SoundDevice->getCaptureDevice() : 0;
+ m_comboCaptureCard ->setCurrentItem(m_captureCard2idx[card]);
+ slotCaptureCardSelected(m_comboCaptureCard->currentText());
+ m_comboCaptureDevice->setCurrentItem(m_captureDevice2idx[dev]);
+
+ //IErrorLogClient::staticLogDebug(TQString("capture: card = %1(%2), dev = %3").arg(card).arg(m_captureCard2idx[card]).arg(dev));
+
+ editHWBufferSize ->setValue (m_SoundDevice ? m_SoundDevice->getHWBufferSize()/1024 : 4);
+ 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);
+
+ //IErrorLogClient::staticLogDebug(TQString("capture: card = %1").arg(m_comboCaptureCard->currentText()));
+
+
+ if (m_SoundDevice)
+ m_MixerSettings = m_SoundDevice->getCaptureMixerSettings();
+ else
+ m_MixerSettings.clear();
+ restoreCaptureMixerSettings();
+
+ m_ignore_updates = false;
+ m_dirty = false;
+}
+
+
+void AlsaSoundConfiguration::slotUpdateConfig()
+{
+ slotSetDirty();
+ slotCancel();
+}
+
+void AlsaSoundConfiguration::slotSetDirty()
+{
+ if (!m_dirty && !m_ignore_updates) {
+ m_dirty = true;
+ //emit sigDirty();
+ }
+}
+
+#include "alsa-sound-configuration.moc"
diff --git a/plugins/alsa-sound/alsa-sound-configuration.h b/plugins/alsa-sound/alsa-sound-configuration.h
new file mode 100644
index 0000000..a626544
--- /dev/null
+++ b/plugins/alsa-sound/alsa-sound-configuration.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+ alsa-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_ALSA_SOUND_CONFIGURATION_H
+#define KRADIO_ALSA_SOUND_CONFIGURATION_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "alsa-sound-configuration-ui.h"
+#include "alsa-sound.h"
+#include "alsa-config-mixer-setting.h"
+
+class TQHBoxLayout;
+class TQGridLayout;
+class QAlsaMixerElement;
+class TQScrollView;
+class TQFrame;
+
+class AlsaSoundConfiguration : public AlsaSoundConfigurationUI
+{
+Q_OBJECT
+
+public :
+ AlsaSoundConfiguration (TQWidget *parent, AlsaSoundDevice *);
+ ~AlsaSoundConfiguration ();
+
+protected slots:
+
+ void slotOK();
+ void slotCancel();
+
+ void slotSetDirty();
+
+ void slotUpdateConfig();
+
+ void slotPlaybackCardSelected(const TQString &cardname);
+ void slotCaptureCardSelected(const TQString &cardname);
+
+protected:
+ int listSoundDevices(KComboBox *combobox, TQMap<TQString, int> *devname2dev, TQMap<int, TQString> *dev2devname, TQMap<int, int> *dev2idx, int card, snd_pcm_stream_t stream);
+ void saveCaptureMixerSettings();
+ void restoreCaptureMixerSettings();
+
+ AlsaSoundDevice *m_SoundDevice;
+ int m_currentCaptureCard;
+ TQMap<TQString, int> m_name2card,
+ m_name2capturedevice,
+ m_playbackDeviceName2dev,
+ m_captureDeviceName2dev;
+ TQMap<int, TQString> m_card2name,
+ m_dev2playbackDeviceName,
+ m_dev2captureDeviceName;
+ TQMap<int, int> m_captureCard2idx,
+ m_captureDevice2idx,
+ m_playbackCard2idx,
+ m_playbackDevice2idx;
+ TQGridLayout *m_groupMixerLayout;
+ TQScrollView *m_groupMixerScrollView;
+ TQFrame *m_groupMixerSubFrame;
+ TQMap<TQString, QAlsaMixerElement*> m_MixerElements;
+
+ TQMap<TQString, AlsaConfigMixerSetting> m_MixerSettings;
+
+ bool m_dirty;
+ bool m_ignore_updates;
+};
+
+#endif
diff --git a/plugins/alsa-sound/alsa-sound.cpp b/plugins/alsa-sound/alsa-sound.cpp
new file mode 100644
index 0000000..746eacf
--- /dev/null
+++ b/plugins/alsa-sound/alsa-sound.cpp
@@ -0,0 +1,1562 @@
+/***************************************************************************
+ alsa-sound.cpp - description
+ -------------------
+ begin : Thu May 26 2005
+ copyright : (C) 2005 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 <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <math.h>
+#include <errno.h>
+
+#include <sys/soundcard.h>
+#include <alsa/asoundlib.h>
+
+#include "alsa-sound.h"
+#include "alsa-sound-configuration.h"
+// #include "capture-thread.h"
+#include "../../src/include/aboutwidget.h"
+#include "../../src/include/utils.h"
+
+///////////////////////////////////////////////////////////////////////
+//// plugin library functions
+
+PLUGIN_LIBRARY_FUNCTIONS(AlsaSoundDevice, "tderadio-alsa-sound", i18n("Advanced Linux Sound Architecture (ALSA) Support"));
+
+/////////////////////////////////////////////////////////////////////////////
+
+struct _lrvol { unsigned char l, r; short dummy; };
+
+AlsaSoundDevice::AlsaSoundDevice(const TQString &name)
+ : TQObject(NULL, NULL),
+ PluginBase(name, i18n("TDERadio ALSA Sound Plugin")),
+ m_hPlayback(NULL),
+ m_hCapture(NULL),
+ m_hPlaybackMixer(NULL),
+ m_hCaptureMixer(NULL),
+ m_PlaybackFormat(),
+ m_CaptureFormat(),
+ m_PlaybackCard(-1),
+ m_PlaybackDevice(-1),
+ m_CaptureCard(-1),
+ m_CaptureDevice(-1),
+ m_PlaybackLatency(50),
+ m_CaptureLatency(50),
+ m_PassivePlaybackStreams(),
+ m_PlaybackStreamID(),
+ m_CaptureStreamID(),
+ m_HWBufferSize(2048),
+ m_BufferSize(16384),
+ 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)//,
+// m_captureThread(NULL)
+{
+ TQObject::connect(&m_PlaybackPollingTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotPollPlayback()));
+ TQObject::connect(&m_CapturePollingTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotPollCapture()));
+}
+
+
+AlsaSoundDevice::~AlsaSoundDevice()
+{
+ stopCapture(m_CaptureStreamID);
+ stopPlayback(m_PlaybackStreamID);
+ closePlaybackDevice();
+ closeCaptureDevice();
+ closePlaybackMixerDevice();
+ closeCaptureMixerDevice();
+}
+
+
+bool AlsaSoundDevice::connectI(Interface *i)
+{
+ bool a = PluginBase::connectI(i);
+ bool b = ISoundStreamClient::connectI(i);
+ return a || b;
+}
+
+
+bool AlsaSoundDevice::disconnectI(Interface *i)
+{
+ bool a = PluginBase::disconnectI(i);
+ bool b = ISoundStreamClient::disconnectI(i);
+ return a || b;
+}
+
+void AlsaSoundDevice::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_sendMute(this);
+ s->register4_sendUnmute(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 AlsaSoundDevice::saveState (TDEConfig *c) const
+{
+ c->setGroup(TQString("alsa-sound-") + PluginBase::name());
+
+ c->writeEntry("playback-card", m_PlaybackCard);
+ c->writeEntry("playback-device", m_PlaybackDevice);
+ c->writeEntry("capture-card", m_CaptureCard);
+ c->writeEntry("capture-device", m_CaptureDevice);
+ c->writeEntry("enable-playback", m_EnablePlayback);
+ c->writeEntry("enable-capture", m_EnableCapture);
+ c->writeEntry("hwbuffer-size", m_HWBufferSize);
+ c->writeEntry("buffer-size", m_BufferSize);
+ c->writeEntry("soundstreamclient-id", m_SoundStreamClientID);
+
+ c->writeEntry("mixer-settings", m_CaptureMixerSettings.count());
+ int i = 0;
+ for (TQMapConstIterator<TQString, AlsaConfigMixerSetting> it = m_CaptureMixerSettings.begin(); it != m_CaptureMixerSettings.end(); ++it, ++i) {
+
+ TQString prefix = TQString("mixer-setting-%1-").arg(i);
+ (*it).saveState(c, prefix);
+ }
+
+}
+
+
+void AlsaSoundDevice::restoreState (TDEConfig *c)
+{
+ c->setGroup(TQString("alsa-sound-") + PluginBase::name());
+
+ m_EnablePlayback = c->readBoolEntry("enable-playback", true);
+ m_EnableCapture = c->readBoolEntry("enable-capture", true);
+ m_HWBufferSize = c->readNumEntry ("hwbuffer-size", 2048);
+ m_BufferSize = c->readNumEntry ("buffer-size", 16384);
+ int card = c->readNumEntry ("playback-card", 0);
+ int dev = c->readNumEntry ("playback-device", 0);
+ setPlaybackDevice(card, dev);
+ card = c->readNumEntry ("capture-card", 0);
+ dev = c->readNumEntry ("capture-device", 0);
+ setCaptureDevice(card, dev);
+
+ m_PlaybackBuffer.resize(m_BufferSize);
+ m_CaptureBuffer.resize(m_BufferSize);
+
+ setSoundStreamClientID(c->readEntry("soundstreamclient-id", getSoundStreamClientID()));
+
+ int n = c->readNumEntry("mixer-settings", 0);
+ for (int i = 0; i < n; ++i) {
+ TQString prefix = TQString("mixer-setting-%1-").arg(i);
+ AlsaConfigMixerSetting s(c, prefix);
+ m_CaptureMixerSettings.insert(s.getIDString(), s);
+ }
+
+ emit sigUpdateConfig();
+}
+
+
+ConfigPageInfo AlsaSoundDevice::createConfigurationPage()
+{
+ AlsaSoundConfiguration *conf = new AlsaSoundConfiguration(NULL, this);
+ TQObject::connect(this, TQT_SIGNAL(sigUpdateConfig()), conf, TQT_SLOT(slotUpdateConfig()));
+ return ConfigPageInfo (conf,
+ i18n("ALSA Sound"),
+ i18n("ALSA Sound Device Options"),
+ "tderadio_alsa2");
+}
+
+
+AboutPageInfo AlsaSoundDevice::createAboutPage()
+{
+/* TDEAboutData aboutData("tderadio",
+ NULL,
+ NULL,
+ I18N_NOOP("ALSA Sound Plugin for TDERadio"),
+ TDEAboutData::License_GPL,
+ "(c) 2005 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("ALSA Sound"),
+ i18n("ALSA Sound"),
+ "tderadio_alsa_sound"
+ );
+*/
+ return AboutPageInfo();
+}
+
+
+
+bool AlsaSoundDevice::preparePlayback(SoundStreamID id, const TQString &channel, bool active_mode, bool start_immediately)
+{
+ if (id.isValid()) {
+ m_PlaybackStreams.insert(id, SoundStreamConfig(channel, active_mode));
+ if (start_immediately)
+ startPlayback(id);
+ return true;
+ // FIXME: what to do if stream is already playing?
+ }
+ return false;
+}
+
+bool AlsaSoundDevice::prepareCapture(SoundStreamID id, const TQString &channel)
+{
+ if (id.isValid()) {
+ m_CaptureStreams.insert(id, SoundStreamConfig(channel));
+ return true;
+ // FIXME: what to do if stream is already playing?
+ }
+ return false;
+}
+
+bool AlsaSoundDevice::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 AlsaSoundDevice::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 AlsaSoundDevice::supportsPlayback() const
+{
+ return m_EnablePlayback;
+}
+
+
+bool AlsaSoundDevice::supportsCapture() const
+{
+ return m_EnableCapture;
+}
+
+
+bool AlsaSoundDevice::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) {
+ openPlaybackMixerDevice();
+ if (cfg.m_Volume >= 0 && writePlaybackMixerVolume(cfg.m_Channel, cfg.m_Volume, cfg.m_Muted)) {
+ notifyPlaybackVolumeChanged(id, cfg.m_Volume);
+ notifyMuted(id, cfg.m_Volume);
+ }
+ m_PlaybackPollingTimer.start(m_PlaybackLatency);
+ }
+
+ // error handling?
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool AlsaSoundDevice::pausePlayback(SoundStreamID /*id*/)
+{
+ //return stopPlayback(id);
+ return false;
+}
+
+
+bool AlsaSoundDevice::stopPlayback(SoundStreamID id)
+{
+ if (id.isValid() && m_PlaybackStreams.contains(id)) {
+
+ SoundStreamConfig &cfg = m_PlaybackStreams[id];
+
+ if (!cfg.m_ActiveMode) {
+ if (m_PassivePlaybackStreams.contains(id)) {
+/* float tmp = 0;
+ writePlaybackMixerVolume(cfg.m_Channel, tmp, true);*/
+ m_PassivePlaybackStreams.remove(id);
+ }
+ } else if (m_PlaybackStreamID == id) {
+ m_PlaybackStreamID = SoundStreamID::InvalidID;
+ m_PlaybackBuffer.clear();
+ closePlaybackDevice();
+ }
+
+ closePlaybackMixerDevice();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool AlsaSoundDevice::isPlaybackRunning(SoundStreamID id, bool &b) const
+{
+ if (id.isValid() && m_PlaybackStreamID == id || m_PassivePlaybackStreams.contains(id)) {
+ b = true;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool AlsaSoundDevice::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 && proposed_format != m_CaptureFormat)) {
+
+ m_CaptureStreamID = id;
+ SoundStreamConfig &cfg = m_CaptureStreams[id];
+
+ openCaptureMixerDevice();
+ selectCaptureChannel(cfg.m_Channel);
+ if (cfg.m_Volume >= 0 && writeCaptureMixerVolume(cfg.m_Channel, cfg.m_Volume)) {
+ notifyCaptureVolumeChanged(m_CaptureStreamID, cfg.m_Volume);
+ }
+
+ openCaptureDevice(proposed_format);
+
+ // FIXME: error handling?
+ }
+
+ real_format = m_CaptureFormat;
+ m_CaptureRequestCounter++;
+
+// m_captureThread = new AlsaCaptureThread(this, m_hCapture, m_CaptureFormat, 5, m_BufferSize);
+// m_captureThread->start();
+
+ slotPollCapture();
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool AlsaSoundDevice::stopCapture(SoundStreamID id)
+{
+ if (id.isValid() && m_CaptureStreamID == id) {
+
+ if (--m_CaptureRequestCounter == 0) {
+
+// m_captureThread->setDone();
+// if (!m_captureThread->wait(4000)) { //wait at maximum 4 seconds
+// logError("AlsaPlugin: capture thread did not terminate. Killing it.");
+// m_captureThread->terminate();
+// m_captureThread->wait();
+// }
+
+ slotPollCapture();
+
+// if (m_captureThread->error()) {
+// logError(i18n("ALSA Plugin, device plughw:%1,%2: %3").arg(m_CaptureCard)
+// .arg(m_CaptureDevice)
+// .arg(i18n("unknown error")));
+// }
+//
+// delete m_captureThread;
+// m_captureThread = NULL;
+
+ m_CaptureStreamID = SoundStreamID::InvalidID;
+ m_CaptureBuffer.clear();
+
+ closeCaptureMixerDevice();
+ closeCaptureDevice();
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool AlsaSoundDevice::isCaptureRunning(SoundStreamID id, bool &b, SoundFormat &sf) const
+{
+ if (id.isValid() && m_CaptureStreamID == id) {
+ b = true;
+ sf = m_CaptureFormat;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool AlsaSoundDevice::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 AlsaSoundDevice::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 AlsaSoundDevice::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_hPlayback) {
+ openPlaybackDevice(format);
+ } else if (format != m_PlaybackFormat) {
+ // flush playback buffer
+ size_t buffersize = 0;
+ char *buffer = m_PlaybackBuffer.getData(buffersize);
+
+ snd_pcm_writei(m_hPlayback, buffer, buffersize / m_PlaybackFormat.sampleSize());
+
+ // if not all could be written, it must be discarded
+ m_PlaybackBuffer.clear();
+ closePlaybackDevice();
+ openPlaybackDevice(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("plughw:%1,%2: Playback buffer overflow. Skipped %3 bytes").arg(m_PlaybackCard).arg(m_PlaybackDevice).arg(TQString::number(m_PlaybackSkipCount)));
+ m_PlaybackSkipCount = 0;
+ }
+ return m_PlaybackSkipCount == 0;*/
+ return true;
+}
+
+
+
+void AlsaSoundDevice::slotPollPlayback()
+{
+ if (m_PlaybackStreamID.isValid()) {
+
+ if (m_PlaybackBuffer.getFillSize() > 0 && m_hPlayback) {
+
+ size_t buffersize = 0;
+ int frameSize = m_CaptureFormat.frameSize();
+ char *buffer = m_PlaybackBuffer.getData(buffersize);
+ int framesWritten = snd_pcm_writei(m_hPlayback, buffer, buffersize / frameSize);
+ int bytesWritten = framesWritten * frameSize;
+
+ if (framesWritten > 0) {
+ m_PlaybackBuffer.removeData(bytesWritten);
+ } else if (framesWritten == 0) {
+ logError(i18n("ALSA Plugin: cannot write data for device plughw:%1,%2").arg(m_PlaybackCard).arg(m_PlaybackDevice));
+ } else if (framesWritten == -EAGAIN) {
+ // do nothing
+ } else {
+ snd_pcm_prepare(m_hPlayback);
+ logWarning(i18n("ALSA Plugin: buffer underrun for device plughw:%1,%2").arg(m_PlaybackCard).arg(m_PlaybackDevice));
+ }
+ }
+
+ if (m_PlaybackBuffer.getFreeSize() > m_PlaybackBuffer.getSize() / 3) {
+ notifyReadyForPlaybackData(m_PlaybackStreamID, m_PlaybackBuffer.getFreeSize());
+ }
+
+ checkMixerVolume(m_PlaybackStreamID);
+ }
+
+ TQValueListConstIterator<SoundStreamID> end = m_PassivePlaybackStreams.end();
+ for (TQValueListConstIterator<SoundStreamID> it = m_PassivePlaybackStreams.begin(); it != end; ++it)
+ checkMixerVolume(*it);
+}
+
+
+void AlsaSoundDevice::slotPollCapture()
+{
+ if (m_CaptureStreamID.isValid() && m_hCapture) {
+
+// while (m_captureThread && m_captureThread->getAvailableReadBuffers()) {
+// TQString dev = TQString("alsa://plughw:%1,%2").arg(m_CaptureCard).arg(m_CaptureDevice);
+// size_t size = 0;
+// char *buffer = m_captureThread->getReadBuffer(size);
+// time_t cur_time = time(NULL);
+// notifySoundStreamData(m_CaptureStreamID, m_CaptureFormat, buffer, size, SoundMetaData(m_CapturePos, cur_time - m_CaptureStartTime, cur_time, dev));
+// m_CapturePos += size;
+// }
+
+ size_t bufferSize = 0;
+ char *buffer = m_CaptureBuffer.getFreeSpace(bufferSize);
+
+ if (bufferSize) {
+
+ size_t frameSize = m_CaptureFormat.frameSize();
+ int framesRead = snd_pcm_readi(m_hCapture, buffer, bufferSize / frameSize);
+ size_t bytesRead = framesRead > 0 ? framesRead * frameSize : 0;
+
+// //BEGIN DEBUG
+// static unsigned int debug_val = 0;
+// short *debug_buf = (short*)buffer;
+// for (int i = 0; i < bytesRead / 2 / sizeof(short); ++i) {
+// debug_buf[2*i] = debug_val >> 10;
+// debug_buf[2*i+1] = debug_val >> 10;
+// ++debug_val;
+// }
+// //END DEBUG
+
+ if (framesRead > 0) {
+ m_CaptureBuffer.removeFreeSpace(bytesRead);
+ } else if (framesRead == 0) {
+ snd_pcm_prepare(m_hCapture);
+ logError(i18n("ALSA Plugin: cannot read data from device plughw:%1,%2").arg(m_CaptureCard).arg(m_CaptureDevice));
+ } else if (framesRead == -EAGAIN) {
+ // do nothing
+ } else {
+ snd_pcm_prepare(m_hCapture);
+ logWarning(i18n("ALSA Plugin: buffer overrun for device plughw:%1,%2 (buffersize=%3, buffer=%4)").arg(m_CaptureCard).arg(m_CaptureDevice).arg(bufferSize).arg((long long unsigned)buffer));
+ }
+
+ TQString dev = TQString("alsa://plughw:%1,%2").arg(m_CaptureCard).arg(m_CaptureDevice);
+ 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_CaptureFormat, buffer, size, consumed_size, SoundMetaData(m_CapturePos, cur_time - m_CaptureStartTime, cur_time, i18n("internal stream, not stored (%1)").arg(dev)));
+
+ 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_CaptureStreamID.isValid())
+ checkMixerVolume(m_CaptureStreamID);
+}
+
+
+bool AlsaSoundDevice::openPlaybackDevice(const SoundFormat &format, bool reopen)
+{
+ if (m_PlaybackCard < 0 || m_PlaybackDevice < 0)
+ return false;
+
+ if (m_hPlayback) {
+
+ if (reopen) {
+
+ closePlaybackDevice ( /* force = */ true);
+
+ } else {
+
+ if (format != m_PlaybackFormat)
+ return false;
+
+ return true;
+ }
+ } else {
+ if (reopen) // FIXME: emw: please check if this makes sense !?!?
+ return true;
+ }
+
+ m_PlaybackFormat = format;
+
+ TQString dev = TQString("plughw:%1,%2").arg(m_PlaybackCard).arg(m_PlaybackDevice);
+ bool error = !openAlsaDevice(m_hPlayback, m_PlaybackFormat, dev.ascii(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK, m_PlaybackLatency);
+
+ if (!error) {
+ m_PlaybackPollingTimer.start(m_PlaybackLatency);
+ } else {
+ closePlaybackDevice();
+ }
+
+// m_PlaybackSkipCount = 0;
+
+ return !error;
+}
+
+
+bool AlsaSoundDevice::openCaptureDevice(const SoundFormat &format, bool reopen)
+{
+ if (m_PlaybackCard < 0 || m_PlaybackDevice < 0)
+ return false;
+
+ if (m_hCapture) {
+
+ if (reopen) {
+
+ closeCaptureDevice ( /* force = */ true);
+
+ } else {
+
+ if (format != m_CaptureFormat)
+ return false;
+
+ return true;
+ }
+ } else {
+ if (reopen) // FIXME: emw: please check if this makes sense !?!?
+ return true;
+ }
+
+ m_CaptureFormat = format;
+
+ TQString dev = TQString("plughw:%1,%2").arg(m_CaptureCard).arg(m_CaptureDevice);
+// bool error = !openAlsaDevice(m_hCapture, m_CaptureFormat, dev.ascii(), SND_PCM_STREAM_CAPTURE, /*flags = block*/0, m_CaptureLatency);
+ bool error = !openAlsaDevice(m_hCapture, m_CaptureFormat, dev.ascii(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK, m_CaptureLatency);
+
+ if (!error) {
+ m_CapturePollingTimer.start(m_CaptureLatency);
+ } else {
+ closeCaptureDevice();
+ }
+
+ m_CaptureSkipCount = 0;
+
+ return !error;
+}
+
+
+bool AlsaSoundDevice::openAlsaDevice(snd_pcm_t *&alsa_handle, SoundFormat &format, const char *pcm_name, snd_pcm_stream_t stream, int flags, unsigned &latency)
+{
+ bool error = false;
+ int dir = 0;
+
+ snd_pcm_hw_params_t *hwparams = NULL;
+
+ snd_pcm_hw_params_alloca(&hwparams);
+
+
+ /* OPEN */
+
+ if (!error && snd_pcm_open(&alsa_handle, pcm_name, stream, flags) < 0) {
+ logError(i18n("ALSA Plugin: Error opening PCM device %1").arg(pcm_name));
+ error = true;
+ }
+
+ if (!error && snd_pcm_hw_params_any(alsa_handle, hwparams) < 0) {
+ logError(i18n("ALSA Plugin: Can not configure PCM device %1").arg(pcm_name));
+ error = true;
+ }
+
+ /* interleaved access type */
+
+ if (!error && snd_pcm_hw_params_set_access(alsa_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
+ logError(i18n("ALSA Plugin: Error setting access for %1").arg(pcm_name));
+ error = true;
+ }
+
+ /* sample format */
+ snd_pcm_format_t sample_format = snd_pcm_build_linear_format(format.m_SampleBits,
+ format.m_SampleBits,
+ !format.m_IsSigned,
+ format.m_Endianess == BIG_ENDIAN);
+ if (!error && snd_pcm_hw_params_set_format(alsa_handle, hwparams, sample_format) < 0) {
+ logError(i18n("ALSA Plugin: Error setting sample format for %1").arg(pcm_name));
+ error = true;
+ }
+
+ /* channels */
+ if (!error && snd_pcm_hw_params_set_channels(alsa_handle, hwparams, format.m_Channels) < 0) {
+ logError(i18n("ALSA Plugin: Error setting channels for %1").arg(pcm_name));
+ error = true;
+ }
+
+ /* sample rate */
+ int rate = format.m_SampleRate;
+ if (!error && snd_pcm_hw_params_set_rate_near(alsa_handle, hwparams, &format.m_SampleRate, &dir) < 0) {
+ logError(i18n("ALSA Plugin: Error setting rate for %1").arg(pcm_name));
+ error = true;
+ }
+ if (!error && format.m_SampleRate != format.m_SampleRate) {
+ logWarning(i18n("ALSA Plugin: The rate %1 Hz is not supported by your hardware %2. Using %3 Hz instead").arg(rate).arg(pcm_name).arg(format.m_SampleRate));
+ }
+
+
+ snd_pcm_uframes_t period_size = m_HWBufferSize / format.frameSize();
+ if (!error && snd_pcm_hw_params_set_period_size_near(alsa_handle, hwparams, &period_size, &dir) < 0) {
+ logError(i18n("ALSA Plugin: Error setting period size for %1").arg(pcm_name));
+ error = true;
+ }
+
+// size_t buffersize_frames = m_HWBufferSize / format.frameSize();
+// int periods = 4;
+// //int period_size = m_BufferSize / periods;
+//
+// /* fragments */
+// if (!error && snd_pcm_hw_params_set_periods(alsa_handle, hwparams, periods, 0) < 0) {
+// logError(i18n("ALSA Plugin: Error setting periods for %1").arg(pcm_name));
+// error = true;
+// }
+
+// /* Set buffer size (in frames). */
+//
+// snd_pcm_uframes_t exact_buffersize_frames = buffersize_frames;
+// if (!error && snd_pcm_hw_params_set_buffer_size_near(alsa_handle, hwparams, &exact_buffersize_frames) < 0) {
+// exact_buffersize_frames = 4096;
+// if (!error && snd_pcm_hw_params_set_buffer_size_near(alsa_handle, hwparams, &exact_buffersize_frames) < 0) {
+// logError(i18n("ALSA Plugin: Error setting buffersize for %1").arg(pcm_name));
+// error = true;
+// }
+// }
+
+// size_t exact_buffersize = exact_buffersize_frames * format.frameSize();
+// if (!error && m_HWBufferSize != exact_buffersize) {
+// logWarning(i18n("ALSA Plugin: Hardware %1 does not support buffer size of %2. Using buffer size of %3 instead.").arg(pcm_name).arg(m_HWBufferSize).arg(exact_buffersize));
+// size_t tmp = (((m_HWBufferSize - 1) / exact_buffersize) + 1) * exact_buffersize;
+// setHWBufferSize(tmp);
+// logInfo(i18n("ALSA Plugin: adjusted buffer size for %1 to %2 bytes").arg(pcm_name).arg(TQString::number(tmp)));
+// }
+
+ /* set all params */
+
+ if (!error && snd_pcm_hw_params(alsa_handle, hwparams) < 0) {
+ logError(i18n("ALSA Plugin: Error setting HW params"));
+ error = true;
+ }
+
+ if (!error && snd_pcm_hw_params_get_period_size(hwparams, &period_size, &dir) < 0) {
+ logError(i18n("ALSA Plugin: Error getting period size for %1").arg(pcm_name));
+ error = true;
+ }
+
+// latency = (exact_buffersize_frames * 1000) / format.m_SampleRate / periods; /* in milli seconds */
+ latency = (period_size * format.frameSize() * 1000) / format.m_SampleRate; /* in milli seconds */
+
+ if (!error) {
+ snd_pcm_prepare(alsa_handle);
+ }
+
+ return !error;
+}
+
+
+bool AlsaSoundDevice::closePlaybackDevice(bool force)
+{
+ if (!m_PlaybackStreamID.isValid() || force) {
+
+ if (!m_hPlaybackMixer)
+ m_PlaybackPollingTimer.stop();
+
+ if (m_hPlayback) {
+ snd_pcm_drop(m_hPlayback);
+ snd_pcm_close(m_hPlayback);
+ }
+
+ m_hPlayback = NULL;
+
+ m_PlaybackBuffer.clear();
+ return true;
+ }
+ return false;
+}
+
+
+bool AlsaSoundDevice::closeCaptureDevice(bool force)
+{
+ if (!m_CaptureStreamID.isValid() || force) {
+
+ if (!m_hCaptureMixer)
+ m_CapturePollingTimer.stop();
+
+ if (m_hCapture) {
+ snd_pcm_drop(m_hCapture);
+ snd_pcm_close(m_hCapture);
+ }
+
+ m_hCapture = NULL;
+
+ m_CaptureBuffer.clear();
+ return true;
+ }
+ return false;
+}
+
+
+bool AlsaSoundDevice::openPlaybackMixerDevice(bool reopen)
+{
+ return openMixerDevice(m_hPlaybackMixer, m_PlaybackCard, reopen, &m_PlaybackPollingTimer, m_PlaybackLatency);
+}
+
+
+bool AlsaSoundDevice::openCaptureMixerDevice(bool reopen)
+{
+// logDebug("AlsaSoundDevice::openCaptureMixerDevice: card == " + TQString::number(m_CaptureCard));
+ return openMixerDevice(m_hCaptureMixer, m_CaptureCard, reopen, &m_CapturePollingTimer, m_CaptureLatency);
+}
+
+
+bool AlsaSoundDevice::closePlaybackMixerDevice(bool force)
+{
+ return closeMixerDevice(m_hPlaybackMixer, m_PlaybackCard, m_PlaybackStreamID, m_hPlayback, force, &m_PlaybackPollingTimer);
+}
+
+bool AlsaSoundDevice::closeCaptureMixerDevice(bool force)
+{
+ return closeMixerDevice(m_hCaptureMixer, m_CaptureCard, m_CaptureStreamID, m_hCapture, force, &m_CapturePollingTimer);
+}
+
+
+static int mixer_dummy_callback(snd_mixer_t *, unsigned int /*mask*/, snd_mixer_elem_t */*elem*/)
+{
+ return 0;
+}
+
+bool AlsaSoundDevice::openMixerDevice(snd_mixer_t *&mixer_handle, int card, bool reopen, TQTimer *timer, int timer_latency)
+{
+ if (reopen) {
+ if (mixer_handle != NULL)
+ closeMixerDevice(mixer_handle, card, SoundStreamID::InvalidID, NULL, /* force = */ true, timer);
+ else
+ return true;
+ }
+
+ if (!mixer_handle) {
+ bool error = false;
+ if (snd_mixer_open (&mixer_handle, 0) < 0) {
+ staticLogError(i18n("ALSA Plugin: Error opening mixer"));
+ error = true;
+ }
+ TQString cardid = "hw:" + TQString::number(card);
+ bool attached = false;
+ if (!error) {
+ if (snd_mixer_attach (mixer_handle, cardid.ascii()) < 0) {
+ staticLogError(i18n("ALSA Plugin: ERROR: snd_mixer_attach for card %1").arg(card));
+ error = true;
+ } else {
+ attached = true;
+ }
+ }
+ if (!error && snd_mixer_selem_register(mixer_handle, NULL, NULL) < 0) {
+ staticLogError(i18n("ALSA Plugin: Error: snd_mixer_selem_register for card %1").arg(card));
+ error = true;
+ }
+ if (!error && snd_mixer_load (mixer_handle) < 0) {
+ staticLogError(i18n("ALSA Plugin: Error: snd_mixer_load for card %1").arg(card));
+ error = true;
+ }
+ if (mixer_handle) {
+ snd_mixer_set_callback (mixer_handle, mixer_dummy_callback);
+ }
+
+ if (error) {
+ if (attached) {
+ snd_mixer_detach(mixer_handle, cardid.ascii());
+ }
+ snd_mixer_close(mixer_handle);
+ mixer_handle = NULL;
+ }
+ }
+
+ if (mixer_handle && timer) {
+ timer->start(timer_latency);
+ }
+ return mixer_handle != NULL;
+}
+
+
+bool AlsaSoundDevice::closeMixerDevice(snd_mixer_t *&mixer_handle, int card, SoundStreamID id, snd_pcm_t *pcm_handle, bool force, TQTimer *timer)
+{
+ if (!id.isValid() || force) {
+
+ if (!pcm_handle && timer)
+ timer->stop();
+
+ if (mixer_handle) {
+ TQString cardid = "hw:" + TQString::number(card);
+ snd_mixer_free(mixer_handle);
+ snd_mixer_detach(mixer_handle, cardid.ascii());
+ snd_mixer_close (mixer_handle);
+ }
+ mixer_handle = NULL;
+ }
+ return mixer_handle == NULL;
+}
+
+void AlsaSoundDevice::getPlaybackMixerChannels(
+ int card,
+ snd_mixer_t *__mixer_handle,
+ TQStringList &retval, TQMap<TQString, AlsaMixerElement> &ch2id)
+{
+ retval.clear();
+ ch2id.clear();
+
+ snd_mixer_t *mixer_handle = __mixer_handle/*m_hPlaybackMixer*/;
+ bool use_tmp_handle = false;
+
+ if (!mixer_handle) {
+ openMixerDevice(mixer_handle, card/*m_PlaybackCard*/, false, NULL, 0);
+ use_tmp_handle = true;
+ }
+
+ if (mixer_handle) {
+ snd_mixer_elem_t *elem = NULL;
+
+ for (elem = snd_mixer_first_elem(mixer_handle); elem; elem = snd_mixer_elem_next(elem)) {
+ AlsaMixerElement sid;
+ if (!snd_mixer_selem_is_active(elem))
+ continue;
+ snd_mixer_selem_get_id(elem, sid);
+ TQString name = snd_mixer_selem_id_get_name(sid);
+ int idx = snd_mixer_selem_id_get_index(sid);
+ if (idx)
+ name = i18n("context-mixername-number", "%1 %2").arg(name).arg(idx);
+ if (snd_mixer_selem_has_playback_volume(elem)) {
+ ch2id[name] = sid;
+ retval.append(name);
+ }
+ }
+ }
+
+ if (use_tmp_handle && mixer_handle) {
+ closeMixerDevice(mixer_handle, card /*m_PlaybackCard*/, SoundStreamID::InvalidID, NULL, true, NULL);
+ }
+}
+
+void AlsaSoundDevice::getCaptureMixerChannels(
+ int card,
+ snd_mixer_t *__mixer_handle,
+ TQStringList &vol_list, TQMap<TQString, AlsaMixerElement> &vol_ch2id,
+ TQStringList &sw_list, TQMap<TQString, AlsaMixerElement> &sw_ch2id,
+ TQStringList *all_list
+)
+{
+ vol_list.clear();
+ sw_list.clear();
+ if (all_list) all_list->clear();
+ vol_ch2id.clear();
+ sw_ch2id.clear();
+
+ snd_mixer_t *mixer_handle = __mixer_handle /*m_hCaptureMixer*/;
+ bool use_tmp_handle = false;
+
+ if (!mixer_handle) {
+// staticLogDebug("AlsaSoundDevice::getCaptureMixerChannels: card == " + TQString::number(card/*m_CaptureCard*/));
+ openMixerDevice(mixer_handle, card /*m_CaptureCard*/, false, NULL, 0);
+ use_tmp_handle = true;
+ }
+
+ if (mixer_handle) {
+ snd_mixer_elem_t *elem = NULL;
+
+ for (elem = snd_mixer_first_elem(mixer_handle); elem; elem = snd_mixer_elem_next(elem)) {
+ AlsaMixerElement sid;
+ if (!snd_mixer_selem_is_active(elem))
+ continue;
+ snd_mixer_selem_get_id(elem, sid);
+ TQString name = snd_mixer_selem_id_get_name(sid);
+ int idx = snd_mixer_selem_id_get_index(sid);
+ if (idx)
+ name = i18n("context-mixerelement-name-number", "%1 %2").arg(name).arg(idx);
+
+ bool add2all = false;
+ if (snd_mixer_selem_has_capture_switch(elem)) {
+ sw_ch2id[name] = sid;
+ sw_list.append(name);
+ add2all = true;
+ }
+ if (snd_mixer_selem_has_capture_volume(elem)) {
+ vol_ch2id[name] = sid;
+ vol_list.append(name);
+ add2all = true;
+ }
+ if (add2all && all_list) {
+ all_list->append(name);
+ }
+ }
+ }
+
+ if (use_tmp_handle && mixer_handle) {
+ closeMixerDevice(mixer_handle, card /*m_CaptureCard*/, SoundStreamID::InvalidID, NULL, true, NULL);
+ }
+}
+
+const TQStringList &AlsaSoundDevice::getPlaybackChannels() const
+{
+ return m_PlaybackChannels;
+}
+
+
+const TQStringList &AlsaSoundDevice::getCaptureChannels() const
+{
+ return m_CaptureChannelsSwitch;
+}
+
+
+bool AlsaSoundDevice::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)) {
+ if (writePlaybackMixerVolume(cfg.m_Channel, cfg.m_Volume = volume, cfg.m_Muted)) {
+ notifyPlaybackVolumeChanged(id, cfg.m_Volume);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+
+bool AlsaSoundDevice::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)) {
+ if (writeCaptureMixerVolume(cfg.m_Channel, cfg.m_Volume = volume)) {
+ notifyCaptureVolumeChanged(id, cfg.m_Volume);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+
+bool AlsaSoundDevice::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 AlsaSoundDevice::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 AlsaSoundDevice::checkMixerVolume(SoundStreamID id)
+{
+ if (id.isValid()) {
+
+ if (m_hPlaybackMixer && m_PassivePlaybackStreams.contains(id) || m_PlaybackStreamID == id) {
+ snd_mixer_handle_events(m_hPlaybackMixer);
+ SoundStreamConfig &cfg = m_PlaybackStreams[id];
+
+ bool m = false;
+ float v = readPlaybackMixerVolume(cfg.m_Channel, m);
+ if (rint(100*cfg.m_Volume) != rint(100*v)) {
+ cfg.m_Volume = v;
+ notifyPlaybackVolumeChanged(id, v);
+ }
+ if (m != cfg.m_Muted) {
+ cfg.m_Muted = m;
+ notifyMuted(id, m);
+ }
+ }
+
+ if (m_hCaptureMixer && m_CaptureStreamID == id) {
+ snd_mixer_handle_events(m_hCaptureMixer);
+ SoundStreamConfig &cfg = m_CaptureStreams[id];
+
+ if (m_CaptureChannels2ID.contains(cfg.m_Channel)) {
+ float v = readCaptureMixerVolume(cfg.m_Channel);
+ if (rint(100*cfg.m_Volume) != rint(100*v)) {
+ cfg.m_Volume = v;
+ notifyCaptureVolumeChanged(id, v);
+ }
+ }
+ }
+ }
+}
+
+
+float AlsaSoundDevice::readPlaybackMixerVolume(const TQString &channel, bool &muted) const
+{
+ if (!m_hPlaybackMixer)
+ return 0; // without error
+
+ if (m_PlaybackChannels2ID.contains(channel) && m_hPlaybackMixer) {
+ AlsaMixerElement sid = m_PlaybackChannels2ID[channel];
+ snd_mixer_elem_t *elem = snd_mixer_find_selem(m_hPlaybackMixer, sid);
+ if (elem) {
+ long min = 0;
+ long max = 0;
+ snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
+ if (min != max) {
+ long val = min;
+
+ muted = false;
+ int m = false;
+ if (snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, &m) == 0) {
+ muted = !m;
+ }
+ if (snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &val) == 0) {
+ return ((float)(val - min)) / (float)(max - min);
+ }
+ }
+ }
+ }
+ logError("AlsaSound::readPlaybackMixerVolume: " +
+ i18n("error while reading volume from hwplug:%1,%2")
+ .arg(m_PlaybackCard)
+ .arg(m_PlaybackDevice));
+ return 0;
+}
+
+
+float AlsaSoundDevice::readCaptureMixerVolume(const TQString &channel) const
+{
+ if (!m_hCaptureMixer)
+ return 0; // without error
+
+ if (m_CaptureChannels2ID.contains(channel) && m_hCaptureMixer) {
+ AlsaMixerElement sid = m_CaptureChannels2ID[channel];
+ snd_mixer_elem_t *elem = snd_mixer_find_selem(m_hCaptureMixer, sid);
+ if (elem) {
+ if (!snd_mixer_selem_has_capture_volume(elem))
+ return 0;
+ long min = 0;
+ long max = 0;
+ snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
+ if (min != max) {
+ long val = min;
+ if (snd_mixer_selem_get_capture_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &val) == 0) {
+ return ((float)(val - min)) / (float)(max - min);
+ }
+ }
+ }
+ }
+ logError("AlsaSound::readCaptureMixerVolume: " +
+ i18n("error while reading volume from hwplug:%1,%2")
+ .arg(m_CaptureCard)
+ .arg(m_CaptureDevice));
+ return 0;
+}
+
+
+bool AlsaSoundDevice::writePlaybackMixerVolume (const TQString &channel, float &vol, bool muted)
+{
+ if (vol > 1.0) vol = 1.0;
+ if (vol < 0) vol = 0.0;
+
+ if (!m_hPlaybackMixer)
+ return false;
+
+ if (m_PlaybackChannels2ID.contains(channel) && m_hPlaybackMixer) {
+ AlsaMixerElement sid = m_PlaybackChannels2ID[channel];
+ snd_mixer_elem_t *elem = snd_mixer_find_selem(m_hPlaybackMixer, sid);
+ if (elem) {
+ long min = 0;
+ long max = 0;
+ snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
+ if (min != max) {
+ long val = (int)rint(min + (max - min) * vol);
+ vol = (float)(val - min) / (float)(max - min);
+ snd_mixer_selem_set_playback_switch_all(elem, !muted);
+ if (snd_mixer_selem_set_playback_volume_all(elem, val) == 0) {
+ return true;
+ }
+ }
+ }
+ }
+ logError("AlsaSound::writePlaybackMixerVolume: " +
+ i18n("error while writing volume %1 to hwplug:%2,%3")
+ .arg(vol)
+ .arg(m_PlaybackCard)
+ .arg(m_PlaybackDevice));
+ return false;
+}
+
+
+
+
+bool AlsaSoundDevice::writeCaptureMixerVolume (const TQString &channel, float &vol)
+{
+ if (vol > 1.0) vol = 1.0;
+ if (vol < 0) vol = 0.0;
+
+ if (!m_hCaptureMixer)
+ return false;
+
+ if (m_CaptureChannels2ID.contains(channel) && m_hCaptureMixer) {
+ AlsaMixerElement sid = m_CaptureChannels2ID[channel];
+ snd_mixer_elem_t *elem = snd_mixer_find_selem(m_hCaptureMixer, sid);
+ if (elem) {
+ long min = 0;
+ long max = 0;
+ snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
+ if (min != max) {
+ long val = (int)rint(min + (max - min) * vol);
+ vol = (float)(val - min) / (float)(max - min);
+ if (snd_mixer_selem_set_capture_volume_all(elem, val) == 0) {
+ return true;
+ }
+ }
+ }
+ }
+ logError("AlsaSound::writeCaptureMixerVolume: " +
+ i18n("error while writing volume %1 to hwplug:%2,%3")
+ .arg(vol)
+ .arg(m_CaptureCard)
+ .arg(m_CaptureDevice));
+ return false;
+}
+
+
+bool AlsaSoundDevice::writeCaptureMixerSwitch (const TQString &channel, bool capture)
+{
+ if (!m_hCaptureMixer)
+ return false;
+
+ if (m_CaptureChannelsSwitch2ID.contains(channel) && m_hCaptureMixer) {
+ AlsaMixerElement sid = m_CaptureChannelsSwitch2ID[channel];
+ snd_mixer_elem_t *elem = snd_mixer_find_selem(m_hCaptureMixer, sid);
+ if (elem) {
+ if (snd_mixer_selem_set_capture_switch_all(elem, capture) == 0) {
+ return true;
+ }
+ }
+ }
+ logError("AlsaSound::writeCaptureMixerSwitch: " +
+ i18n("error while setting capture switch %1 for hwplug:%2,%3")
+ .arg(channel)
+ .arg(m_CaptureCard)
+ .arg(m_CaptureDevice));
+ return false;
+}
+
+
+void AlsaSoundDevice::selectCaptureChannel (const TQString &channel)
+{
+ writeCaptureMixerSwitch(channel, true);
+
+ const TQString ADC = "ADC";
+ if (m_CaptureChannels2ID.contains(ADC)) {
+ float v = readCaptureMixerVolume(ADC);
+ if (rint(v*100) == 0) {
+ float tmp_vol = 1.0;
+ writeCaptureMixerVolume(ADC, tmp_vol);
+ }
+ }
+ const TQString Digital = "Digital";
+ if (m_CaptureChannels2ID.contains(Digital)) {
+ float v = readCaptureMixerVolume(Digital);
+ if (rint(v*100) == 0) {
+ float tmp_vol = 1.0;
+ writeCaptureMixerVolume(Digital, tmp_vol);
+ }
+ }
+ const TQString WAVE = "Wave";
+ if (m_CaptureChannels2ID.contains(WAVE)) {
+ float x = 0;
+ writeCaptureMixerVolume(WAVE, x);
+ }
+ const TQString Capture = "Capture";
+ if (m_CaptureChannelsSwitch2ID.contains(Capture)) {
+ writeCaptureMixerSwitch(Capture, true);
+ }
+
+ for (TQMapConstIterator<TQString, AlsaConfigMixerSetting> it = m_CaptureMixerSettings.begin(); it != m_CaptureMixerSettings.end(); ++it) {
+ const AlsaConfigMixerSetting &s = *it;
+ if (s.m_card == m_CaptureCard && s.m_use) {
+ float vol = s.m_volume;
+ if (m_CaptureChannels2ID.contains(s.m_name))
+ writeCaptureMixerVolume(s.m_name, vol);
+ if (m_CaptureChannelsSwitch2ID.contains(s.m_name))
+ writeCaptureMixerSwitch(s.m_name, s.m_active);
+ }
+ }
+}
+
+
+void AlsaSoundDevice::setHWBufferSize(int s)
+{
+ m_HWBufferSize = s;
+}
+
+
+void AlsaSoundDevice::setBufferSize(int s)
+{
+ m_BufferSize = s;
+ m_PlaybackBuffer.resize(m_BufferSize);
+ m_CaptureBuffer.resize(m_BufferSize);
+}
+
+
+void AlsaSoundDevice::enablePlayback(bool on)
+{
+ m_EnablePlayback = on;
+}
+
+
+void AlsaSoundDevice::enableCapture(bool on)
+{
+ m_EnableCapture = on;
+}
+
+
+void AlsaSoundDevice::setPlaybackDevice(int card, int dev)
+{
+ if (m_PlaybackCard == card && m_PlaybackDevice == dev)
+ return;
+
+ m_PlaybackCard = card;
+ m_PlaybackDevice = dev;
+ SoundFormat f = m_PlaybackFormat;
+ if (m_hPlayback)
+ openPlaybackDevice(f, /* reopen = */ true);
+ if (m_hPlaybackMixer)
+ openPlaybackMixerDevice(/* reopen = */ true);
+
+ getPlaybackMixerChannels(m_PlaybackCard,
+ m_hPlaybackMixer,
+ m_PlaybackChannels, m_PlaybackChannels2ID);
+ notifyPlaybackChannelsChanged(m_SoundStreamClientID, m_PlaybackChannels);
+}
+
+
+void AlsaSoundDevice::setCaptureDevice(int card, int dev)
+{
+// logDebug("AlsaSoundDevice::setCaptureDevice-1: m_CaptureCard == " + TQString::number(m_CaptureCard) + ", card == " + TQString::number(card));
+ if (m_CaptureCard == card && m_CaptureDevice == dev)
+ return;
+// logDebug("AlsaSoundDevice::setCaptureDevice-2: m_CaptureCard == " + TQString::number(m_CaptureCard) + ", card == " + TQString::number(card));
+
+ m_CaptureCard = card;
+ m_CaptureDevice = dev;
+ SoundFormat f = m_CaptureFormat;
+ if (m_hCapture)
+ openCaptureDevice(f, /* reopen = */ true);
+ if (m_hCaptureMixer)
+ openCaptureMixerDevice(/* reopen = */ true);
+
+ getCaptureMixerChannels(m_CaptureCard,
+ m_hCaptureMixer,
+ m_CaptureChannels, m_CaptureChannels2ID, m_CaptureChannelsSwitch, m_CaptureChannelsSwitch2ID);
+ notifyCaptureChannelsChanged(m_SoundStreamClientID, m_CaptureChannels);
+}
+
+
+TQString AlsaSoundDevice::getSoundStreamClientDescription() const
+{
+ return i18n("ALSA Sound Device %1").arg(PluginBase::name());
+}
+
+
+bool AlsaSoundDevice::mute (SoundStreamID id, bool mute)
+{
+ if (id.isValid() && (m_PlaybackStreamID == id || m_PassivePlaybackStreams.contains(id))) {
+ SoundStreamConfig &cfg = m_PlaybackStreams[id];
+ if (mute != cfg.m_Muted) {
+ if (writePlaybackMixerVolume(cfg.m_Channel, cfg.m_Volume, cfg.m_Muted = mute)) {
+ notifyMuted(id, cfg.m_Muted);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+bool AlsaSoundDevice::unmute (SoundStreamID id, bool unmute)
+{
+ if (id.isValid() && (m_PlaybackStreamID == id || m_PassivePlaybackStreams.contains(id))) {
+ SoundStreamConfig &cfg = m_PlaybackStreams[id];
+ bool mute = !unmute;
+ if (mute != cfg.m_Muted) {
+ if (writePlaybackMixerVolume(cfg.m_Channel, cfg.m_Volume, cfg.m_Muted = mute)) {
+ notifyMuted(id, cfg.m_Muted);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+bool AlsaSoundDevice::isMuted(SoundStreamID id, bool &m) const
+{
+ if (id.isValid() && (m_PlaybackStreamID == id || m_PassivePlaybackStreams.contains(id))) {
+ const SoundStreamConfig &cfg = m_PlaybackStreams[id];
+ m = cfg.m_Muted;
+ return true;
+ }
+ return false;
+}
+
+
+void AlsaSoundDevice::setCaptureMixerSettings(const TQMap<TQString, AlsaConfigMixerSetting> &map)
+{
+ m_CaptureMixerSettings = map;
+}
+
+
+
+// bool AlsaSoundDevice::event(TQEvent *_e)
+// {
+// bool retval = false;
+//
+// switch (_e->type()) {
+//
+// case CaptureTerminated :
+// retval = true;
+// break;
+//
+// case CaptureStep :
+//
+// slotPollCapture();
+//
+// retval = true;
+// break;
+//
+// case CaptureError :
+// case CaptureWarning :
+// case CaptureInfo :
+// case CaptureDebug :
+// if (m_captureThread) {
+// AlsaCaptureEvent *e = static_cast<AlsaCaptureEvent*>(_e);
+// TQString msg = i18n("ALSA Plugin, device plughw:%1,%2: %3")
+// .arg(m_CaptureCard)
+// .arg(m_CaptureDevice)
+// .arg(e->message());
+// switch (_e->type()) {
+// case CaptureError :
+// logError(msg);
+// m_captureThread->resetError();
+// break;
+// case CaptureWarning :
+// logWarning(msg);
+// break;
+// case CaptureInfo :
+// logInfo(msg);
+// break;
+// case CaptureDebug :
+// logDebug(msg);
+// break;
+// default:
+// break;
+// }
+// }
+// retval = true;
+// break;
+//
+// default:
+// retval = TQObject::event(_e);
+// break;
+// }
+//
+// return retval;
+// }
+
+
+
+
+
+
+
+
+#include "alsa-sound.moc"
diff --git a/plugins/alsa-sound/alsa-sound.h b/plugins/alsa-sound/alsa-sound.h
new file mode 100644
index 0000000..4a79832
--- /dev/null
+++ b/plugins/alsa-sound/alsa-sound.h
@@ -0,0 +1,297 @@
+/***************************************************************************
+ alsa-sound.h - description
+ -------------------
+ begin : Thu May 26 2005
+ copyright : (C) 2005 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_ALSA_SOUND_H
+#define _KRADIO_ALSA_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 "alsa-config-mixer-setting.h"
+
+#include <tqobject.h>
+#include <tqtimer.h>
+#include <alsa/asoundlib.h>
+
+enum DUPLEX_MODE { DUPLEX_UNKNOWN, DUPLEX_FULL, DUPLEX_HALF };
+
+
+struct SoundStreamConfig
+{
+ SoundStreamConfig()
+ : m_ActiveMode(false),
+ m_Channel(TQString()),
+ m_Volume(-1),
+ m_Muted(false)
+ {}
+
+ SoundStreamConfig(const TQString &_channel, bool active_mode = true)
+ : m_ActiveMode(active_mode),
+ m_Channel(_channel),
+ m_Volume(-1),
+ m_Muted(false)
+ {}
+
+ SoundStreamConfig(const SoundStreamConfig &c)
+ : m_ActiveMode(c.m_ActiveMode),
+ m_Channel(c.m_Channel),
+ m_Volume(c.m_Volume),
+ m_Muted(c.m_Muted)
+ {}
+
+ bool m_ActiveMode;
+ TQString m_Channel;
+ float m_Volume;
+ bool m_Muted;
+};
+
+
+class AlsaCaptureThread;
+
+class AlsaMixerElement
+{
+public:
+ AlsaMixerElement() { snd_mixer_selem_id_malloc(&m_ID); }
+ AlsaMixerElement(snd_mixer_selem_id_t *id) { snd_mixer_selem_id_malloc(&m_ID); snd_mixer_selem_id_copy(m_ID, id) ; }
+ AlsaMixerElement(const AlsaMixerElement &x) { snd_mixer_selem_id_malloc(&m_ID); snd_mixer_selem_id_copy(m_ID, x.m_ID); }
+ ~AlsaMixerElement() { snd_mixer_selem_id_free (m_ID); }
+
+ operator snd_mixer_selem_id_t *&() { return m_ID; }
+
+ AlsaMixerElement &operator = (const AlsaMixerElement &x) { snd_mixer_selem_id_copy(m_ID, x.m_ID); return *this; }
+
+protected:
+ snd_mixer_selem_id_t *m_ID;
+};
+
+
+class AlsaSoundDevice : public TQObject,
+ public PluginBase,
+ public ISoundStreamClient
+{
+Q_OBJECT
+
+
+public:
+ AlsaSoundDevice (const TQString &name);
+ virtual ~AlsaSoundDevice ();
+
+ 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 "AlsaSoundDevice"; }
+
+ 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
+
+public:
+ static
+ void getPlaybackMixerChannels(int card, snd_mixer_t *mixer_handle,
+ TQStringList &retval, TQMap<TQString, AlsaMixerElement> &int2id);
+ static
+ void getCaptureMixerChannels (int card, snd_mixer_t *mixer_handle,
+ TQStringList &vol_list, TQMap<TQString, AlsaMixerElement> &vol_ch2id,
+ TQStringList &sw_list, TQMap<TQString, AlsaMixerElement> &sw_ch2id,
+ TQStringList *all_list = NULL);
+
+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;
+
+ bool mute (SoundStreamID id, bool mute);
+ bool unmute (SoundStreamID id, bool unmute);
+ bool isMuted(SoundStreamID id, bool &m) 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 getHWBufferSize() const { return m_HWBufferSize; }
+ int getBufferSize() const { return m_BufferSize; }
+ bool isPlaybackEnabled() const { return m_EnablePlayback; }
+ bool isCaptureEnabled() const { return m_EnableCapture; }
+ int getPlaybackCard() const { return m_PlaybackCard; }
+ int getPlaybackDevice() const { return m_PlaybackDevice; }
+ int getCaptureCard() const { return m_CaptureCard; }
+ int getCaptureDevice() const { return m_CaptureDevice; }
+ const TQMap<TQString, AlsaConfigMixerSetting> &
+ getCaptureMixerSettings() const { return m_CaptureMixerSettings; }
+
+ void setHWBufferSize(int s);
+ void setBufferSize(int s);
+ void enablePlayback(bool on);
+ void enableCapture(bool on);
+ void setPlaybackDevice(int card, int device);
+ void setCaptureDevice(int card, int device);
+ void setCaptureMixerSettings(const TQMap<TQString, AlsaConfigMixerSetting> &map);
+
+protected slots:
+
+ void slotPollPlayback();
+ void slotPollCapture();
+
+signals:
+
+ void sigUpdateConfig();
+
+protected:
+// bool event(TQEvent *_e);
+
+ bool openAlsaDevice(snd_pcm_t *&alsa_handle, SoundFormat &format, const char *pcm_name, snd_pcm_stream_t stream, int flags, unsigned &latency);
+
+ bool openPlaybackDevice (const SoundFormat &format, bool reopen = false);
+ bool openCaptureDevice (const SoundFormat &format, bool reopen = false);
+ bool closePlaybackDevice(bool force = false);
+ bool closeCaptureDevice (bool force = false);
+
+ bool openPlaybackMixerDevice (bool reopen = false);
+ bool openCaptureMixerDevice (bool reopen = false);
+ static bool openMixerDevice(snd_mixer_t *&mixer_handle, int card, bool reopen, TQTimer *timer, int timer_latency);
+ bool closeCaptureMixerDevice (bool force = false);
+ bool closePlaybackMixerDevice(bool force = false);
+ static bool closeMixerDevice(snd_mixer_t *&mixer_handle, int card, SoundStreamID id, snd_pcm_t *pcm_handle, bool force, TQTimer *timer);
+
+ void checkMixerVolume(SoundStreamID id);
+ float readPlaybackMixerVolume(const TQString &channel, bool &muted) const;
+ float readCaptureMixerVolume(const TQString &channel) const;
+ bool writePlaybackMixerVolume(const TQString &channel, float &vol, bool muted);
+ bool writeCaptureMixerVolume(const TQString &channel, float &vol);
+ bool writeCaptureMixerSwitch(const TQString &channel, bool capture);
+
+ void selectCaptureChannel (const TQString &channel);
+
+ /* ALSA HANDLES */
+ snd_pcm_t *m_hPlayback;
+ snd_pcm_t *m_hCapture;
+ snd_mixer_t *m_hPlaybackMixer;
+ snd_mixer_t *m_hCaptureMixer;
+
+ SoundFormat m_PlaybackFormat;
+ SoundFormat m_CaptureFormat;
+ int m_PlaybackCard;
+ int m_PlaybackDevice;
+ int m_CaptureCard;
+ int m_CaptureDevice;
+
+ unsigned m_PlaybackLatency;
+ unsigned m_CaptureLatency;
+
+ TQStringList m_PlaybackChannels,
+ m_CaptureChannels,
+ m_CaptureChannelsSwitch;
+
+ TQMap<TQString, AlsaMixerElement> m_PlaybackChannels2ID,
+ m_CaptureChannels2ID,
+ m_CaptureChannelsSwitch2ID;
+
+ TQMap<SoundStreamID, SoundStreamConfig>
+ m_PlaybackStreams,
+ m_CaptureStreams;
+
+ TQValueList<SoundStreamID>
+ m_PassivePlaybackStreams;
+ SoundStreamID m_PlaybackStreamID,
+ m_CaptureStreamID;
+
+ size_t m_HWBufferSize;
+ 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_PlaybackPollingTimer;
+ TQTimer m_CapturePollingTimer;
+
+// AlsaCaptureThread *m_captureThread;
+
+ TQMap<TQString, AlsaConfigMixerSetting> m_CaptureMixerSettings;
+
+};
+
+
+
+#endif
diff --git a/plugins/alsa-sound/icons/Makefile.am b/plugins/alsa-sound/icons/Makefile.am
new file mode 100644
index 0000000..c9577fb
--- /dev/null
+++ b/plugins/alsa-sound/icons/Makefile.am
@@ -0,0 +1,7 @@
+# icons_ICON = tderadio_alsa*
+# iconsdir = $(datadir)/icons
+
+KDE_ICON = alsa alsa2
+
+icons_ICON = tderadio_alsa tderadio_alsa2
+iconsdir = $(datadir)/icons
diff --git a/plugins/alsa-sound/icons/alsa.png b/plugins/alsa-sound/icons/alsa.png
new file mode 100644
index 0000000..151f9b1
--- /dev/null
+++ b/plugins/alsa-sound/icons/alsa.png
Binary files differ
diff --git a/plugins/alsa-sound/icons/alsa2.png b/plugins/alsa-sound/icons/alsa2.png
new file mode 100644
index 0000000..524f16f
--- /dev/null
+++ b/plugins/alsa-sound/icons/alsa2.png
Binary files differ
diff --git a/plugins/alsa-sound/icons/hi16-action-tderadio_alsa.png b/plugins/alsa-sound/icons/hi16-action-tderadio_alsa.png
new file mode 100644
index 0000000..5272859
--- /dev/null
+++ b/plugins/alsa-sound/icons/hi16-action-tderadio_alsa.png
Binary files differ
diff --git a/plugins/alsa-sound/icons/hi16-action-tderadio_alsa2.png b/plugins/alsa-sound/icons/hi16-action-tderadio_alsa2.png
new file mode 100644
index 0000000..e521ea0
--- /dev/null
+++ b/plugins/alsa-sound/icons/hi16-action-tderadio_alsa2.png
Binary files differ
diff --git a/plugins/alsa-sound/icons/hi22-action-tderadio_alsa.png b/plugins/alsa-sound/icons/hi22-action-tderadio_alsa.png
new file mode 100644
index 0000000..f0c3906
--- /dev/null
+++ b/plugins/alsa-sound/icons/hi22-action-tderadio_alsa.png
Binary files differ
diff --git a/plugins/alsa-sound/icons/hi22-action-tderadio_alsa2.png b/plugins/alsa-sound/icons/hi22-action-tderadio_alsa2.png
new file mode 100644
index 0000000..0e7adfa
--- /dev/null
+++ b/plugins/alsa-sound/icons/hi22-action-tderadio_alsa2.png
Binary files differ
diff --git a/plugins/alsa-sound/icons/hi32-action-tderadio_alsa.png b/plugins/alsa-sound/icons/hi32-action-tderadio_alsa.png
new file mode 100644
index 0000000..2eebb0d
--- /dev/null
+++ b/plugins/alsa-sound/icons/hi32-action-tderadio_alsa.png
Binary files differ
diff --git a/plugins/alsa-sound/icons/hi32-action-tderadio_alsa2.png b/plugins/alsa-sound/icons/hi32-action-tderadio_alsa2.png
new file mode 100644
index 0000000..47ff4b0
--- /dev/null
+++ b/plugins/alsa-sound/icons/hi32-action-tderadio_alsa2.png
Binary files differ
diff --git a/plugins/alsa-sound/icons/hi48-action-tderadio_alsa.png b/plugins/alsa-sound/icons/hi48-action-tderadio_alsa.png
new file mode 100644
index 0000000..afaa77a
--- /dev/null
+++ b/plugins/alsa-sound/icons/hi48-action-tderadio_alsa.png
Binary files differ
diff --git a/plugins/alsa-sound/icons/hi48-action-tderadio_alsa2.png b/plugins/alsa-sound/icons/hi48-action-tderadio_alsa2.png
new file mode 100644
index 0000000..c638081
--- /dev/null
+++ b/plugins/alsa-sound/icons/hi48-action-tderadio_alsa2.png
Binary files differ
diff --git a/plugins/alsa-sound/icons/hi64-action-tderadio_alsa.png b/plugins/alsa-sound/icons/hi64-action-tderadio_alsa.png
new file mode 100644
index 0000000..971528b
--- /dev/null
+++ b/plugins/alsa-sound/icons/hi64-action-tderadio_alsa.png
Binary files differ
diff --git a/plugins/alsa-sound/icons/hi64-action-tderadio_alsa2.png b/plugins/alsa-sound/icons/hi64-action-tderadio_alsa2.png
new file mode 100644
index 0000000..60467b3
--- /dev/null
+++ b/plugins/alsa-sound/icons/hi64-action-tderadio_alsa2.png
Binary files differ
diff --git a/plugins/alsa-sound/po/Makefile.am b/plugins/alsa-sound/po/Makefile.am
new file mode 100644
index 0000000..ca0f4d9
--- /dev/null
+++ b/plugins/alsa-sound/po/Makefile.am
@@ -0,0 +1,3 @@
+
+PACKAGE = tderadio-alsa-sound
+POFILES = AUTO
diff --git a/plugins/alsa-sound/po/de.po b/plugins/alsa-sound/po/de.po
new file mode 100644
index 0000000..03af16f
--- /dev/null
+++ b/plugins/alsa-sound/po/de.po
@@ -0,0 +1,285 @@
+# translation of de.po to
+# translation of tderadio-alsa-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: 2021-07-07 18:28+0000\n"
+"PO-Revision-Date: 2019-11-27 16:56+0000\n"
+"Last-Translator: Chris <xchrisx@uber.space>\n"
+"Language-Team: German <https://mirror.git.trinitydesktop.org/weblate/"
+"projects/applications/tderadio-alsa-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"
+
+#: alsa-sound-configuration.cpp:258
+msgid ""
+"_: context-card-plus-device-number\n"
+"%1 device %2"
+msgstr "%1 Gerät %2"
+
+#: alsa-sound.cpp:40
+msgid "Advanced Linux Sound Architecture (ALSA) Support"
+msgstr "Unterstützung für die \"Advanced Linux Sound Architecture\" (ALSA)"
+
+#: alsa-sound.cpp:48
+msgid "TDERadio ALSA Sound Plugin"
+msgstr "TDERadio ALSA Sound Modul"
+
+#: alsa-sound.cpp:196
+msgid "ALSA Sound"
+msgstr "ALSA Sound"
+
+#: alsa-sound.cpp:197
+msgid "ALSA Sound Device Options"
+msgstr "Optionen für die ALSA-Sound-Geräte"
+
+#: alsa-sound.cpp:553
+msgid "ALSA Plugin: cannot write data for device plughw:%1,%2"
+msgstr "ALSA Plugin: Das schreiben auf das Gerät plughw:%1,%2 schlug fehl"
+
+#: alsa-sound.cpp:558
+msgid "ALSA Plugin: buffer underrun for device plughw:%1,%2"
+msgstr "ALSA Plugin: Pufferunterlauf im Gerät plughw:%1,%2"
+
+#: alsa-sound.cpp:611
+msgid "ALSA Plugin: cannot read data from device plughw:%1,%2"
+msgstr "ALSA Plugin: Das Lesen vom Gerät plughw:%1,%2 schlug fehl"
+
+#: alsa-sound.cpp:616
+msgid ""
+"ALSA Plugin: buffer overrun for device plughw:%1,%2 (buffersize=%3, buffer="
+"%4)"
+msgstr ""
+"ALSA Plugin: Pufferüberlauf im Gerät plughw:%1,%2 (Puffergröße=%3, buffer=%4)"
+
+#: alsa-sound.cpp:626
+msgid "internal stream, not stored (%1)"
+msgstr "interner, nicht aufgezeichneter Datenstrom (%1)"
+
+#: alsa-sound.cpp:736
+#, c-format
+msgid "ALSA Plugin: Error opening PCM device %1"
+msgstr "ALSA Plugin: Fehler beim Öffnen des Gerätes %1"
+
+#: alsa-sound.cpp:741
+#, c-format
+msgid "ALSA Plugin: Can not configure PCM device %1"
+msgstr "ALSA Plugin: Die Einrichtung des Gerätes %1 schlug fehl"
+
+#: alsa-sound.cpp:748
+#, c-format
+msgid "ALSA Plugin: Error setting access for %1"
+msgstr "ALSA Plugin: Fehler beim einrichten des Zugriffsmodus auf Gerät %1"
+
+#: alsa-sound.cpp:758
+#, c-format
+msgid "ALSA Plugin: Error setting sample format for %1"
+msgstr "ALSA Plugin: Fehler beim Einstellen des Abtastformats für Gerät %1"
+
+#: alsa-sound.cpp:764
+#, c-format
+msgid "ALSA Plugin: Error setting channels for %1"
+msgstr "ALSA Plugin: Fehler beim Einstellen der Kanäle für Gerät %1"
+
+#: alsa-sound.cpp:771
+#, c-format
+msgid "ALSA Plugin: Error setting rate for %1"
+msgstr "ALSA Plugin: Fehler beim Einstellen der Abtastrate für Gerät %1"
+
+#: alsa-sound.cpp:775
+msgid ""
+"ALSA Plugin: The rate %1 Hz is not supported by your hardware %2. Using %3 "
+"Hz instead"
+msgstr ""
+"ALSA Plugin: Die Abtastrate von %1 Hz wird von Ihrer Soundkarte %2 nicht "
+"unterstützt. Es werden stattdessen %3 Hz verwendet"
+
+#: alsa-sound.cpp:781
+#, c-format
+msgid "ALSA Plugin: Error setting period size for %1"
+msgstr ""
+"ALSA Plugin: Fehler beim Einstellen der Puffer-Periodengröße für Gerät %1"
+
+#: alsa-sound.cpp:817
+msgid "ALSA Plugin: Error setting HW params"
+msgstr "ALSA Plugin: Fehler beim Einstellen der Hardwareparameter"
+
+#: alsa-sound.cpp:822
+#, c-format
+msgid "ALSA Plugin: Error getting period size for %1"
+msgstr "ALSA Plugin: Fehler beim Lesen der Puffer-Periodengröße von Gerät %1"
+
+#: alsa-sound.cpp:920
+msgid "ALSA Plugin: Error opening mixer"
+msgstr "ALSA Plugin: Fehler beim Öffnen des Mixers"
+
+#: alsa-sound.cpp:927
+#, c-format
+msgid "ALSA Plugin: ERROR: snd_mixer_attach for card %1"
+msgstr "ALSA Plugin: Fehler in Funktion snd_mixer_attach bei Soundkarte %1"
+
+#: alsa-sound.cpp:934
+#, c-format
+msgid "ALSA Plugin: Error: snd_mixer_selem_register for card %1"
+msgstr ""
+"ALSA Plugin: Fehler in Funktion snd_mixer_selem_register bei Soundkarte %1"
+
+#: alsa-sound.cpp:938
+#, c-format
+msgid "ALSA Plugin: Error: snd_mixer_load for card %1"
+msgstr "ALSA Plugin: Fehler in Funktion snd_mixer_load bei Soundkarte %1"
+
+#: alsa-sound.cpp:1006
+msgid ""
+"_: context-mixername-number\n"
+"%1 %2"
+msgstr "%1 %2"
+
+#: alsa-sound.cpp:1053
+msgid ""
+"_: context-mixerelement-name-number\n"
+"%1 %2"
+msgstr "%1 %2"
+
+#: alsa-sound.cpp:1206 alsa-sound.cpp:1236
+msgid "error while reading volume from hwplug:%1,%2"
+msgstr "Fehler beim Lesen der Lautstärke von Gerät hwplug:%1,%2"
+
+#: alsa-sound.cpp:1269 alsa-sound.cpp:1304
+msgid "error while writing volume %1 to hwplug:%2,%3"
+msgstr "Fehler beim Setzen der Lautstärke von Gerät hwplug:%1,%2"
+
+#: alsa-sound.cpp:1327
+msgid "error while setting capture switch %1 for hwplug:%2,%3"
+msgstr ""
+"Fehler beim Einstellen des Aufnahmeauswahlschalters %1 für Gerät hwplug:%2,%3"
+
+#: alsa-sound.cpp:1448
+#, c-format
+msgid "ALSA Sound Device %1"
+msgstr "ALSA Soundkarte %1"
+
+#: alsa-mixer-element-ui.ui:16
+#, no-c-format
+msgid "Form1"
+msgstr "Form1"
+
+#: alsa-mixer-element-ui.ui:210
+#, no-c-format
+msgid "O&n"
+msgstr "A&n"
+
+#: alsa-mixer-element-ui.ui:213
+#, no-c-format
+msgid "Alt+N"
+msgstr "Alt+N"
+
+#: alsa-mixer-element-ui.ui:221
+#, no-c-format
+msgid "&Use"
+msgstr "&Verwenden"
+
+#: alsa-mixer-element-ui.ui:224
+#, no-c-format
+msgid "Alt+U"
+msgstr "Alt+U"
+
+#: alsa-mixer-element-ui.ui:256
+#, no-c-format
+msgid "MixerName"
+msgstr "MixerName"
+
+#: alsa-sound-configuration-ui.ui:16
+#, no-c-format
+msgid "AlsaSoundConfigurationUI"
+msgstr "AlsaSoundConfigurationUI"
+
+#: alsa-sound-configuration-ui.ui:34
+#, no-c-format
+msgid "Devices"
+msgstr "Geräte"
+
+#: alsa-sound-configuration-ui.ui:73
+#, no-c-format
+msgid "PCM Capture Card"
+msgstr "Soundkarte für die Aufnahme"
+
+#: alsa-sound-configuration-ui.ui:94
+#, no-c-format
+msgid "Hardware Buffer Size"
+msgstr "Hardware-Puffergröße"
+
+#: alsa-sound-configuration-ui.ui:123 alsa-sound-configuration-ui.ui:145
+#, no-c-format
+msgid " kB"
+msgstr " kB"
+
+#: alsa-sound-configuration-ui.ui:172
+#, no-c-format
+msgid "Buffer Size"
+msgstr "Puffergröße"
+
+#: alsa-sound-configuration-ui.ui:193
+#, no-c-format
+msgid "PCM Playback Device"
+msgstr "Gerät für die Wiedergabe"
+
+#: alsa-sound-configuration-ui.ui:201
+#, no-c-format
+msgid "PCM Capture Device"
+msgstr "Gerät für die Aufnahme"
+
+#: alsa-sound-configuration-ui.ui:209
+#, no-c-format
+msgid "PCM Playback Card"
+msgstr "Soundkarte für die Wiedergabe"
+
+#: alsa-sound-configuration-ui.ui:221
+#, no-c-format
+msgid "E&xtended Options"
+msgstr "Erweiterte Optionen"
+
+#: alsa-sound-configuration-ui.ui:235
+#, no-c-format
+msgid "Disable Pla&yback"
+msgstr "Wiedergabe abschalten"
+
+#: alsa-sound-configuration-ui.ui:238
+#, no-c-format
+msgid "Alt+Y"
+msgstr "Alt+Y"
+
+#: alsa-sound-configuration-ui.ui:246
+#, no-c-format
+msgid "Disa&ble Capture"
+msgstr "Aufnahme abschalten"
+
+#: alsa-sound-configuration-ui.ui:249
+#, no-c-format
+msgid "Alt+B"
+msgstr "Alt+B"
+
+#: alsa-sound-configuration-ui.ui:276
+#, no-c-format
+msgid "Capture Mixer Settings"
+msgstr "Mixereinstellungen für die Aufnahme"
diff --git a/plugins/alsa-sound/po/ru.po b/plugins/alsa-sound/po/ru.po
new file mode 100644
index 0000000..d226310
--- /dev/null
+++ b/plugins/alsa-sound/po/ru.po
@@ -0,0 +1,284 @@
+# translation of ru.po to
+# translation of tderadio-alsa-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: 2021-07-07 18:28+0000\n"
+"PO-Revision-Date: 2006-11-08 12:15+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"
+
+#: alsa-sound-configuration.cpp:258
+msgid ""
+"_: context-card-plus-device-number\n"
+"%1 device %2"
+msgstr ""
+
+#: alsa-sound.cpp:40
+msgid "Advanced Linux Sound Architecture (ALSA) Support"
+msgstr "Поддержка Расширенной звуковой архитектуры Linux (ALSA)"
+
+#: alsa-sound.cpp:48
+msgid "TDERadio ALSA Sound Plugin"
+msgstr "Модуль ALSA для TDERadio"
+
+#: alsa-sound.cpp:196
+msgid "ALSA Sound"
+msgstr "ALSA"
+
+#: alsa-sound.cpp:197
+msgid "ALSA Sound Device Options"
+msgstr "Параметры звука для драйвера ALSA"
+
+#: alsa-sound.cpp:553
+msgid "ALSA Plugin: cannot write data for device plughw:%1,%2"
+msgstr "Модуль ALSA: не могу записать данные в устройство plughw:%1,%2"
+
+#: alsa-sound.cpp:558
+msgid "ALSA Plugin: buffer underrun for device plughw:%1,%2"
+msgstr "Модуль ALSA: нехватка данных в буфере устройства plughw:%1,%2"
+
+#: alsa-sound.cpp:611
+msgid "ALSA Plugin: cannot read data from device plughw:%1,%2"
+msgstr "Модуль ALSA: не могу прочесть данные с устройства plughw:%1,%2"
+
+#: alsa-sound.cpp:616
+msgid ""
+"ALSA Plugin: buffer overrun for device plughw:%1,%2 (buffersize=%3, buffer="
+"%4)"
+msgstr ""
+"Модуль ALSA: переполнение буфера устройства plughw:%1,%2 (размер буфера=%3, "
+"буфер=%4)"
+
+#: alsa-sound.cpp:626
+msgid "internal stream, not stored (%1)"
+msgstr ""
+
+#: alsa-sound.cpp:736
+#, c-format
+msgid "ALSA Plugin: Error opening PCM device %1"
+msgstr "Модуль ALSA: Ошибка при открытии устройства PCM: %1"
+
+#: alsa-sound.cpp:741
+#, c-format
+msgid "ALSA Plugin: Can not configure PCM device %1"
+msgstr "Модуль ALSA: не могу настроить устройство PCM %1"
+
+#: alsa-sound.cpp:748
+#, c-format
+msgid "ALSA Plugin: Error setting access for %1"
+msgstr ""
+
+#: alsa-sound.cpp:758
+#, c-format
+msgid "ALSA Plugin: Error setting sample format for %1"
+msgstr "Модуль ALSA: ошибка при установке формата данных для %1"
+
+#: alsa-sound.cpp:764
+#, c-format
+msgid "ALSA Plugin: Error setting channels for %1"
+msgstr "Модуль ALSA: ошибка при установке числа каналов для %1"
+
+#: alsa-sound.cpp:771
+#, c-format
+msgid "ALSA Plugin: Error setting rate for %1"
+msgstr "Модуль ALSA: ошибка при установке частоты дискретизации для %1"
+
+#: alsa-sound.cpp:775
+msgid ""
+"ALSA Plugin: The rate %1 Hz is not supported by your hardware %2. Using %3 "
+"Hz instead"
+msgstr ""
+"Модуль ALSA: частота дискретизации %1 Гц не поддерживается Вашим "
+"оборудованием %2. Вместо неё использую %3 Гц."
+
+#: alsa-sound.cpp:781
+#, c-format
+msgid "ALSA Plugin: Error setting period size for %1"
+msgstr ""
+
+#: alsa-sound.cpp:817
+msgid "ALSA Plugin: Error setting HW params"
+msgstr "Модуль ALSA: ошибка при установке параметров оборудоания"
+
+#: alsa-sound.cpp:822
+#, c-format
+msgid "ALSA Plugin: Error getting period size for %1"
+msgstr ""
+
+#: alsa-sound.cpp:920
+msgid "ALSA Plugin: Error opening mixer"
+msgstr "Модуль ALSA: ошибка при открытии микшера"
+
+#: alsa-sound.cpp:927
+#, c-format
+msgid "ALSA Plugin: ERROR: snd_mixer_attach for card %1"
+msgstr "Модуль ALSA: ошибка при вызове функции snd_mixer_attach для платы %1"
+
+#: alsa-sound.cpp:934
+#, c-format
+msgid "ALSA Plugin: Error: snd_mixer_selem_register for card %1"
+msgstr ""
+"Модуль ALSA: ошибка при вызове функции snd_mixer_selem_register для платы %1"
+
+#: alsa-sound.cpp:938
+#, c-format
+msgid "ALSA Plugin: Error: snd_mixer_load for card %1"
+msgstr "Модуль ALSA: ошибка при вызове функции snd_mixer_load для платы %1"
+
+#: alsa-sound.cpp:1006
+#, fuzzy
+msgid ""
+"_: context-mixername-number\n"
+"%1 %2"
+msgstr "context-mixername-number"
+
+#: alsa-sound.cpp:1053
+#, fuzzy
+msgid ""
+"_: context-mixerelement-name-number\n"
+"%1 %2"
+msgstr "context-mixerelement-name-number"
+
+#: alsa-sound.cpp:1206 alsa-sound.cpp:1236
+msgid "error while reading volume from hwplug:%1,%2"
+msgstr "Ошибка считывания громкости устройства hwplug:%1,%2"
+
+#: alsa-sound.cpp:1269 alsa-sound.cpp:1304
+msgid "error while writing volume %1 to hwplug:%2,%3"
+msgstr "Ошибка при записи громкости %1 в устройство hwplug:%2,%3"
+
+#: alsa-sound.cpp:1327
+msgid "error while setting capture switch %1 for hwplug:%2,%3"
+msgstr "Ошибка при установке флажка записи %1 для устройства hwplug:%2,%3"
+
+#: alsa-sound.cpp:1448
+#, c-format
+msgid "ALSA Sound Device %1"
+msgstr "Устройство ALSA: %1"
+
+#: alsa-mixer-element-ui.ui:16
+#, no-c-format
+msgid "Form1"
+msgstr "Form1"
+
+#: alsa-mixer-element-ui.ui:210
+#, no-c-format
+msgid "O&n"
+msgstr "&Вкл."
+
+#: alsa-mixer-element-ui.ui:213
+#, no-c-format
+msgid "Alt+N"
+msgstr "Alt+N"
+
+#: alsa-mixer-element-ui.ui:221
+#, no-c-format
+msgid "&Use"
+msgstr "&Исп."
+
+#: alsa-mixer-element-ui.ui:224
+#, no-c-format
+msgid "Alt+U"
+msgstr "Alt+U"
+
+#: alsa-mixer-element-ui.ui:256
+#, no-c-format
+msgid "MixerName"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:16
+#, no-c-format
+msgid "AlsaSoundConfigurationUI"
+msgstr "AlsaSoundConfigurationUI"
+
+#: alsa-sound-configuration-ui.ui:34
+#, no-c-format
+msgid "Devices"
+msgstr "Устройства"
+
+#: alsa-sound-configuration-ui.ui:73
+#, no-c-format
+msgid "PCM Capture Card"
+msgstr "Плата для захвата"
+
+#: alsa-sound-configuration-ui.ui:94
+#, no-c-format
+msgid "Hardware Buffer Size"
+msgstr "Аппаратный размер буфера"
+
+#: alsa-sound-configuration-ui.ui:123 alsa-sound-configuration-ui.ui:145
+#, no-c-format
+msgid " kB"
+msgstr " кБ"
+
+#: alsa-sound-configuration-ui.ui:172
+#, no-c-format
+msgid "Buffer Size"
+msgstr "Размер буфера"
+
+#: alsa-sound-configuration-ui.ui:193
+#, no-c-format
+msgid "PCM Playback Device"
+msgstr "Устройство воспроизведения"
+
+#: alsa-sound-configuration-ui.ui:201
+#, no-c-format
+msgid "PCM Capture Device"
+msgstr "Устройство записи"
+
+#: alsa-sound-configuration-ui.ui:209
+#, no-c-format
+msgid "PCM Playback Card"
+msgstr "Плата для проигрывания"
+
+#: alsa-sound-configuration-ui.ui:221
+#, no-c-format
+msgid "E&xtended Options"
+msgstr "&Дополнительные параметры"
+
+#: alsa-sound-configuration-ui.ui:235
+#, no-c-format
+msgid "Disable Pla&yback"
+msgstr "Запретить &воспроизведение"
+
+#: alsa-sound-configuration-ui.ui:238
+#, no-c-format
+msgid "Alt+Y"
+msgstr "Alt+Y"
+
+#: alsa-sound-configuration-ui.ui:246
+#, no-c-format
+msgid "Disa&ble Capture"
+msgstr "Запретить &запись"
+
+#: alsa-sound-configuration-ui.ui:249
+#, no-c-format
+msgid "Alt+B"
+msgstr "Alt+B"
+
+#: alsa-sound-configuration-ui.ui:276
+#, no-c-format
+msgid "Capture Mixer Settings"
+msgstr "&Параметры микшера для записи"
diff --git a/plugins/alsa-sound/po/tderadio-alsa-sound.pot b/plugins/alsa-sound/po/tderadio-alsa-sound.pot
new file mode 100644
index 0000000..6554981
--- /dev/null
+++ b/plugins/alsa-sound/po/tderadio-alsa-sound.pot
@@ -0,0 +1,275 @@
+# SOME DESCRIPTIVE TITLE.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2021-07-07 18:28+0000\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 ""
+
+#: alsa-sound-configuration.cpp:258
+msgid ""
+"_: context-card-plus-device-number\n"
+"%1 device %2"
+msgstr ""
+
+#: alsa-sound.cpp:40
+msgid "Advanced Linux Sound Architecture (ALSA) Support"
+msgstr ""
+
+#: alsa-sound.cpp:48
+msgid "TDERadio ALSA Sound Plugin"
+msgstr ""
+
+#: alsa-sound.cpp:196
+msgid "ALSA Sound"
+msgstr ""
+
+#: alsa-sound.cpp:197
+msgid "ALSA Sound Device Options"
+msgstr ""
+
+#: alsa-sound.cpp:553
+msgid "ALSA Plugin: cannot write data for device plughw:%1,%2"
+msgstr ""
+
+#: alsa-sound.cpp:558
+msgid "ALSA Plugin: buffer underrun for device plughw:%1,%2"
+msgstr ""
+
+#: alsa-sound.cpp:611
+msgid "ALSA Plugin: cannot read data from device plughw:%1,%2"
+msgstr ""
+
+#: alsa-sound.cpp:616
+msgid ""
+"ALSA Plugin: buffer overrun for device plughw:%1,%2 (buffersize=%3, buffer="
+"%4)"
+msgstr ""
+
+#: alsa-sound.cpp:626
+msgid "internal stream, not stored (%1)"
+msgstr ""
+
+#: alsa-sound.cpp:736
+#, c-format
+msgid "ALSA Plugin: Error opening PCM device %1"
+msgstr ""
+
+#: alsa-sound.cpp:741
+#, c-format
+msgid "ALSA Plugin: Can not configure PCM device %1"
+msgstr ""
+
+#: alsa-sound.cpp:748
+#, c-format
+msgid "ALSA Plugin: Error setting access for %1"
+msgstr ""
+
+#: alsa-sound.cpp:758
+#, c-format
+msgid "ALSA Plugin: Error setting sample format for %1"
+msgstr ""
+
+#: alsa-sound.cpp:764
+#, c-format
+msgid "ALSA Plugin: Error setting channels for %1"
+msgstr ""
+
+#: alsa-sound.cpp:771
+#, c-format
+msgid "ALSA Plugin: Error setting rate for %1"
+msgstr ""
+
+#: alsa-sound.cpp:775
+msgid ""
+"ALSA Plugin: The rate %1 Hz is not supported by your hardware %2. Using %3 "
+"Hz instead"
+msgstr ""
+
+#: alsa-sound.cpp:781
+#, c-format
+msgid "ALSA Plugin: Error setting period size for %1"
+msgstr ""
+
+#: alsa-sound.cpp:817
+msgid "ALSA Plugin: Error setting HW params"
+msgstr ""
+
+#: alsa-sound.cpp:822
+#, c-format
+msgid "ALSA Plugin: Error getting period size for %1"
+msgstr ""
+
+#: alsa-sound.cpp:920
+msgid "ALSA Plugin: Error opening mixer"
+msgstr ""
+
+#: alsa-sound.cpp:927
+#, c-format
+msgid "ALSA Plugin: ERROR: snd_mixer_attach for card %1"
+msgstr ""
+
+#: alsa-sound.cpp:934
+#, c-format
+msgid "ALSA Plugin: Error: snd_mixer_selem_register for card %1"
+msgstr ""
+
+#: alsa-sound.cpp:938
+#, c-format
+msgid "ALSA Plugin: Error: snd_mixer_load for card %1"
+msgstr ""
+
+#: alsa-sound.cpp:1006
+msgid ""
+"_: context-mixername-number\n"
+"%1 %2"
+msgstr ""
+
+#: alsa-sound.cpp:1053
+msgid ""
+"_: context-mixerelement-name-number\n"
+"%1 %2"
+msgstr ""
+
+#: alsa-sound.cpp:1206 alsa-sound.cpp:1236
+msgid "error while reading volume from hwplug:%1,%2"
+msgstr ""
+
+#: alsa-sound.cpp:1269 alsa-sound.cpp:1304
+msgid "error while writing volume %1 to hwplug:%2,%3"
+msgstr ""
+
+#: alsa-sound.cpp:1327
+msgid "error while setting capture switch %1 for hwplug:%2,%3"
+msgstr ""
+
+#: alsa-sound.cpp:1448
+#, c-format
+msgid "ALSA Sound Device %1"
+msgstr ""
+
+#: alsa-mixer-element-ui.ui:16
+#, no-c-format
+msgid "Form1"
+msgstr ""
+
+#: alsa-mixer-element-ui.ui:210
+#, no-c-format
+msgid "O&n"
+msgstr ""
+
+#: alsa-mixer-element-ui.ui:213
+#, no-c-format
+msgid "Alt+N"
+msgstr ""
+
+#: alsa-mixer-element-ui.ui:221
+#, no-c-format
+msgid "&Use"
+msgstr ""
+
+#: alsa-mixer-element-ui.ui:224
+#, no-c-format
+msgid "Alt+U"
+msgstr ""
+
+#: alsa-mixer-element-ui.ui:256
+#, no-c-format
+msgid "MixerName"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:16
+#, no-c-format
+msgid "AlsaSoundConfigurationUI"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:34
+#, no-c-format
+msgid "Devices"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:73
+#, no-c-format
+msgid "PCM Capture Card"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:94
+#, no-c-format
+msgid "Hardware Buffer Size"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:123 alsa-sound-configuration-ui.ui:145
+#, no-c-format
+msgid " kB"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:172
+#, no-c-format
+msgid "Buffer Size"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:193
+#, no-c-format
+msgid "PCM Playback Device"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:201
+#, no-c-format
+msgid "PCM Capture Device"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:209
+#, no-c-format
+msgid "PCM Playback Card"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:221
+#, no-c-format
+msgid "E&xtended Options"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:235
+#, no-c-format
+msgid "Disable Pla&yback"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:238
+#, no-c-format
+msgid "Alt+Y"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:246
+#, no-c-format
+msgid "Disa&ble Capture"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:249
+#, no-c-format
+msgid "Alt+B"
+msgstr ""
+
+#: alsa-sound-configuration-ui.ui:276
+#, no-c-format
+msgid "Capture Mixer Settings"
+msgstr ""
diff --git a/plugins/gui-docking-menu/CMakeL10n.txt b/plugins/gui-docking-menu/CMakeL10n.txt
new file mode 100644
index 0000000..a6da2f2
--- /dev/null
+++ b/plugins/gui-docking-menu/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-gui-docking-menu"
+ DESTINATION "po"
+)
diff --git a/plugins/gui-docking-menu/Makefile.am b/plugins/gui-docking-menu/Makefile.am
new file mode 100644
index 0000000..3c72711
--- /dev/null
+++ b/plugins/gui-docking-menu/Makefile.am
@@ -0,0 +1,18 @@
+SUBDIRS = po .
+
+INCLUDES = -I$(top_builddir)/src $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = libdocking-menu.la
+libdocking_menu_la_SOURCES = docking-configuration.cpp docking.cpp
+libdocking_menu_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+
+noinst_HEADERS = docking-configuration.h docking.h
+
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-gui-docking-menu.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-gui-docking-menu.pot
diff --git a/plugins/gui-docking-menu/docking-configuration.cpp b/plugins/gui-docking-menu/docking-configuration.cpp
new file mode 100644
index 0000000..dd1a18c
--- /dev/null
+++ b/plugins/gui-docking-menu/docking-configuration.cpp
@@ -0,0 +1,114 @@
+/***************************************************************************
+ docking-configuration.cpp - description
+ -------------------
+ begin : Son Aug 3 2003
+ copyright : (C) 2003 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 "docking-configuration.h"
+
+#include <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+
+#include <tdelocale.h>
+
+using namespace std;
+
+DockingConfiguration::DockingConfiguration (RadioDocking *docking, TQWidget *parent)
+ : StationSelector(parent),
+ m_docking(docking),
+ m_disableGUIUpdates(false)
+{
+ TQHBoxLayout *layout = new TQHBoxLayout();
+ TQHBoxLayout *layout2 = new TQHBoxLayout();
+
+ m_labelClickMode = new TQLabel(this);
+ layout->addWidget(m_labelClickMode);
+
+ m_comboClickMode = new TQComboBox(this);
+ layout->addWidget(m_comboClickMode);
+
+ TQSpacerItem *spacer = new TQSpacerItem( 20, 2, TQSizePolicy::Expanding, TQSizePolicy::Minimum);
+ layout->addItem(spacer);
+
+ TQFrame *line = new TQFrame(this);
+ line->setFrameShape ( TQFrame::HLine );
+ line->setFrameShadow( TQFrame::Sunken );
+ layout2->addWidget(line);
+
+ StationSelectorUILayout->expand(2,0);
+ StationSelectorUILayout->addMultiCellLayout(layout2, 2, 2, 0, 2);
+ StationSelectorUILayout->addMultiCellLayout(layout, 3, 3, 0, 2);
+
+ connect(m_comboClickMode, TQT_SIGNAL(activated( int )), this, TQT_SLOT(slotSetDirty()));
+
+ languageChange();
+ slotCancel();
+}
+
+
+DockingConfiguration::~DockingConfiguration ()
+{
+}
+
+
+void DockingConfiguration::languageChange()
+{
+ StationSelector::languageChange();
+ m_labelClickMode->setText( i18n( "Left Mouse Click on Tray" ) );
+
+ m_comboClickMode->clear();
+ m_comboClickMode->insertItem(i18n("Show/Hide all GUI Elements"));
+ m_comboClickMode->insertItem(i18n("Power On/Off"));
+}
+
+void DockingConfiguration::slotOK()
+{
+ if (m_dirty) {
+ StationSelector::slotOK();
+ bool old = m_disableGUIUpdates;
+ m_disableGUIUpdates = true;
+ if (m_docking)
+ m_docking->setLeftClickAction((LeftClickAction)m_comboClickMode->currentItem());
+ m_disableGUIUpdates = old;
+ m_dirty = false;
+ }
+}
+
+void DockingConfiguration::slotCancel()
+{
+ if (m_dirty) {
+ StationSelector::slotCancel();
+ if (m_docking)
+ m_comboClickMode->setCurrentItem(m_docking->getLeftClickAction());
+ m_dirty = false;
+ }
+}
+
+void DockingConfiguration::slotLeftClickActionChanged(LeftClickAction action)
+{
+ if (!m_disableGUIUpdates) {
+ if (m_docking)
+ m_comboClickMode->setCurrentItem(action);
+ }
+}
+
+void DockingConfiguration::slotSetDirty()
+{
+ m_dirty = true;
+}
+
+
+#include "docking-configuration.moc"
diff --git a/plugins/gui-docking-menu/docking-configuration.h b/plugins/gui-docking-menu/docking-configuration.h
new file mode 100644
index 0000000..61133c3
--- /dev/null
+++ b/plugins/gui-docking-menu/docking-configuration.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ docking-configuration.h - description
+ -------------------
+ begin : Son Aug 3 2003
+ copyright : (C) 2003 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_DOCKING_CONFIGURATION_H
+#define KRADIO_DOCKING_CONFIGURATION_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/stationselector.h"
+#include "docking.h"
+
+class TQComboBox;
+class TQLabel;
+
+class DockingConfiguration : public StationSelector
+{
+Q_OBJECT
+
+public :
+ DockingConfiguration (RadioDocking *docking, TQWidget *parent);
+ ~DockingConfiguration ();
+
+protected slots:
+
+ void slotOK();
+ void slotCancel();
+ void slotSetDirty();
+
+ void slotLeftClickActionChanged(LeftClickAction action);
+ void languageChange();
+
+protected:
+ RadioDocking *m_docking;
+ TQComboBox *m_comboClickMode;
+ TQLabel *m_labelClickMode;
+ bool m_disableGUIUpdates;
+};
+
+#endif
diff --git a/plugins/gui-docking-menu/docking.cpp b/plugins/gui-docking-menu/docking.cpp
new file mode 100644
index 0000000..aae4f3f
--- /dev/null
+++ b/plugins/gui-docking-menu/docking.cpp
@@ -0,0 +1,674 @@
+/***************************************************************************
+ docking.cpp - description
+ -------------------
+ begin : Don M�r 8 21:57:17 CET 2001
+ copyright : (C) 2002 by Ernst 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 <kiconloader.h>
+#include <tqtooltip.h>
+#include <tdepopupmenu.h>
+#include <tdeapplication.h>
+#include <tdeaction.h>
+#include <kdialogbase.h>
+#include <tdeaboutdata.h>
+#include <tdeconfig.h>
+#include <twin.h>
+
+#include "../../src/include/radiodevice_interfaces.h"
+#include "../../src/include/stationlist.h"
+#include "../../src/include/pluginmanager.h"
+#include "../../src/include/widgetplugins.h"
+#include "../../src/include/radiostation.h"
+#include "../../src/include/aboutwidget.h"
+#include "../../src/include/station-drag-object.h"
+
+#include "docking.h"
+#include "docking-configuration.h"
+
+#define POPUP_ID_START_RECORDING_DEFAULT 0
+#define POPUP_ID_STOP_RECORDING_BASE 100
+
+///////////////////////////////////////////////////////////////////////
+
+PLUGIN_LIBRARY_FUNCTIONS(RadioDocking, "tderadio-gui-docking-menu", i18n("Tray Menu for TDERadio"));
+
+/////////////////////////////////////////////////////////////////////////////
+
+RadioDocking::RadioDocking(const TQString &name)
+ : KSystemTray (NULL, name.ascii()),
+ PluginBase(name, i18n("Docking Plugin")),
+ m_pluginMenu(NULL),
+ m_recordingMenu(NULL),
+ m_NextRecordingMenuID(POPUP_ID_STOP_RECORDING_BASE),
+ m_leftClickAction(lcaShowHide)
+{
+ setPixmap(BarIcon("tderadio"));
+
+ m_menu = contextMenu();
+ TQObject::connect(m_menu, TQT_SIGNAL(activated(int)),
+ this, TQT_SLOT(slotMenuItemActivated(int)));
+
+ buildContextMenu ();
+ show();
+ setAcceptDrops(true);
+}
+
+RadioDocking::~RadioDocking()
+{
+}
+
+
+bool RadioDocking::connectI (Interface *i)
+{
+ bool a = IRadioClient::connectI(i);
+ bool b = ITimeControlClient::connectI(i);
+ bool c = IRadioDevicePoolClient::connectI(i);
+ bool d = IStationSelection::connectI(i);
+ bool e = ISoundStreamClient::connectI(i);
+ bool f = PluginBase::connectI(i);
+ return a || b || c || d || e || f;
+}
+
+
+bool RadioDocking::disconnectI (Interface *i)
+{
+ bool a = IRadioClient::disconnectI(i);
+ bool b = ITimeControlClient::disconnectI(i);
+ bool c = IRadioDevicePoolClient::disconnectI(i);
+ bool d = IStationSelection::disconnectI(i);
+ bool e = ISoundStreamClient::disconnectI(i);
+ bool f = PluginBase::disconnectI(i);
+ return a || b || c || d || e || f;
+}
+
+
+void RadioDocking::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid)
+{
+ ISoundStreamClient::noticeConnectedI(s, pointer_valid);
+ if (s && pointer_valid) {
+ s->register4_sendStartRecordingWithFormat(this);
+ s->register4_sendStopRecording (this);
+ s->register4_notifySoundStreamChanged (this);
+ }
+}
+
+
+
+bool RadioDocking::setStationSelection(const TQStringList &sl)
+{
+ if (m_stationIDs != sl) {
+ m_stationIDs = sl;
+ buildContextMenu();
+ notifyStationSelectionChanged(m_stationIDs);
+ }
+ return true;
+}
+
+
+// PluginBase
+
+void RadioDocking::restoreState (TDEConfig *config)
+{
+ config->setGroup(TQString("radiodocking-") + name());
+
+ m_stationIDs.clear();
+ int nStations = config->readNumEntry("nStations", 0);
+ for (int i = 1; i <= nStations; ++i) {
+ TQString s = config->readEntry(TQString("stationID-") + TQString().setNum(i), TQString());
+ if (s.length())
+ m_stationIDs += s;
+ }
+
+ m_leftClickAction = (LeftClickAction)config->readNumEntry("left_click_action", lcaShowHide);
+
+ buildContextMenu();
+ notifyStationSelectionChanged(m_stationIDs);
+
+ int n = config->readNumEntry("show_hide_cache_entries", 0);
+ for (int i = 1; i <= n; ++i) {
+ TQString s = config->readEntry(TQString("show_hide_cache_id_%1").arg(i), TQString());
+ bool b = config->readBoolEntry(TQString("show_hide_cache_value_%1").arg(i), false);
+ if (!s.isNull()) {
+ m_widgetsShownCache.insert(s,b);
+ }
+ }
+}
+
+
+void RadioDocking::saveState (TDEConfig *config) const
+{
+ config->setGroup(TQString("radiodocking-") + name());
+
+ config->writeEntry("nStations", m_stationIDs.size());
+ int i = 1;
+ TQStringList::const_iterator end = m_stationIDs.end();
+ for (TQStringList::const_iterator it = m_stationIDs.begin(); it != end; ++it, ++i) {
+ config->writeEntry(TQString("stationID-") + TQString().setNum(i), *it);
+ }
+ config->writeEntry("left_click_action", (int)m_leftClickAction);
+
+ config->writeEntry("show_hide_cache_entries", m_widgetsShownCache.count());
+ i = 1;
+ for (TQMapConstIterator<TQString, bool> it = m_widgetsShownCache.begin(); it != m_widgetsShownCache.end(); ++it, ++i) {
+ config->writeEntry(TQString("show_hide_cache_id_%1").arg(i), it.key());
+ config->writeEntry(TQString("show_hide_cache_value_%1").arg(i), *it);
+ }
+}
+
+
+ConfigPageInfo RadioDocking::createConfigurationPage()
+{
+ DockingConfiguration *conf = new DockingConfiguration(this, NULL);
+ connectI (conf);
+
+ TQObject::connect(this, TQT_SIGNAL(sigLeftClickActionChanged(LeftClickAction)),
+ conf, TQT_SLOT(slotLeftClickActionChanged(LeftClickAction)));
+
+ return ConfigPageInfo(
+ conf,
+ i18n("Docking Menu"),
+ i18n("Docking Menu Configuration"),
+ "kmenuedit"
+ );
+}
+
+AboutPageInfo RadioDocking::createAboutPage()
+{
+/* TDEAboutData aboutData("tderadio",
+ NULL,
+ NULL,
+ I18N_NOOP("Docking Menu for TDERadio"),
+ TDEAboutData::License_GPL,
+ "(c) 2002-2005 Martin Witte, Klas Kalass",
+ 0,
+ "http://sourceforge.net/projects/tderadio",
+ 0);
+ aboutData.addAuthor("Martin Witte", "", "witte@kawo1.rwth-aachen.de");
+ aboutData.addAuthor("Klas Kalass", "", "klas.kalass@gmx.de");
+
+ return AboutPageInfo(
+ new TDERadioAboutWidget(aboutData, TDERadioAboutWidget::AbtTabbed),
+ i18n("Docking Menu"),
+ i18n("Docking Menu Plugin"),
+ "kmenuedit"
+ );*/
+ return AboutPageInfo();
+}
+
+
+
+void RadioDocking::buildContextMenu()
+{
+ m_menu->clear();
+ m_pluginMenu = NULL;
+ m_recordingMenu = NULL;
+
+ m_titleID = m_menu->insertTitle ("title-dummy");
+
+ buildStationList();
+
+ m_alarmID = m_menu->insertTitle ("alarm-dummy");
+ noticeNextAlarmChanged(queryNextAlarm());
+
+ m_sleepID = m_menu->insertItem(SmallIcon("tderadio_zzz"), "sleep-dummy",
+ this, TQT_SLOT(slotSleepCountdown()));
+ noticeCountdownStarted(queryCountdownEnd());
+
+ m_seekfwID = m_menu->insertItem(SmallIcon("forward"), i18n("Search Next Station"),
+ this, TQT_SLOT(slotSeekFwd()));
+ m_seekbwID = m_menu->insertItem(SmallIcon("back"), i18n("Search Previous Station"),
+ this, TQT_SLOT(slotSeekBkwd()));
+
+ // recording menu
+ buildRecordingMenu();
+ m_menu->insertItem(i18n("Recording"), m_recordingMenu);
+
+
+ m_powerID = m_menu->insertItem(SmallIcon("tderadio_muteoff"), "power-dummy",
+ this, TQT_SLOT(slotPower()));
+ m_pauseID = m_menu->insertItem(SmallIcon("tderadio_pause"), i18n("Pause Radio"),
+ this, TQT_SLOT(slotPause()));
+ noticePowerChanged(queryIsPowerOn());
+
+ m_menu->insertSeparator();
+
+ m_menu->insertItem(SmallIcon("tderadio"), i18n("&About"), this, TQT_SLOT(slotShowAbout()));
+
+ // build list of widgets for hide/show items
+ m_pluginMenu = new TDEPopupMenu(m_menu);
+ if (m_manager) {
+ m_manager->addWidgetPluginMenuItems(m_pluginMenu, m_widgetPluginIDs);
+ m_menu->insertItem(SmallIcon("tderadio_plugins"), i18n("Show/Hide Plugins"), m_pluginMenu);
+ }
+
+ m_menu->insertSeparator();
+ m_menu->insertItem( SmallIcon("system-log-out"), i18n("&Quit" ), kapp, TQT_SLOT(quit()) );
+
+
+ noticeStationChanged(queryCurrentStation(), -1);
+
+}
+
+
+void RadioDocking::buildStationList()
+{
+ m_stationMenuIDs.clear();
+
+ const RawStationList &sl = queryStations().all();
+ const RadioStation &crs = queryCurrentStation();
+
+ int k = 0;
+ TQStringList::iterator end = m_stationIDs.end();
+ for (TQStringList::iterator it = m_stationIDs.begin(); it != end; ++it) {
+ const RadioStation &rs = sl.stationWithID(*it);
+
+ if (rs.isValid()) {
+
+ ++k;
+ TQString shortcut = k < 10 ? "&"+TQString().setNum(k) : k == 10 ? "1&0" : TQString().setNum(k);
+ TQString name = rs.longName().replace("&", "&&");
+ TQString item = shortcut + " " + name;
+ int id = m_menu->insertItem(item);
+
+ m_stationMenuIDs.push_back(id);
+ m_menu->setItemChecked (id, rs.compare(crs) == 0);
+
+ } else {
+ m_stationMenuIDs.push_back(-1);
+ }
+ }
+}
+
+
+void RadioDocking::slotSeekFwd()
+{
+ ISeekRadio *seeker = dynamic_cast<ISeekRadio*>(queryActiveDevice());
+ if (seeker)
+ seeker->startSeekUp();
+}
+
+
+void RadioDocking::slotSeekBkwd()
+{
+ ISeekRadio *seeker = dynamic_cast<ISeekRadio*>(queryActiveDevice());
+ if (seeker)
+ seeker->startSeekUp();
+}
+
+
+
+void RadioDocking::slotShowAbout()
+{
+ if (m_manager) {
+ KDialogBase *d = m_manager->getAboutDialog();
+ if (d) d->show();
+ }
+}
+
+
+void RadioDocking::slotPower()
+{
+ if (queryIsPowerOn()) {
+ sendPowerOff();
+ } else {
+ sendPowerOn();
+ }
+}
+
+
+void RadioDocking::slotPause()
+{
+ if (queryIsPowerOn()) {
+ sendPausePlayback(queryCurrentSoundStreamID());
+ }
+}
+
+
+void RadioDocking::slotSleepCountdown()
+{
+ if (queryCountdownEnd().isValid()) {
+ sendStopCountdown();
+ } else {
+ sendStartCountdown();
+ }
+}
+
+
+bool RadioDocking::noticeNextAlarmChanged(const Alarm *a)
+{
+ TQDateTime d;
+ if (a) d = a->nextAlarm();
+
+ if (d.isValid())
+ m_menu->changeTitle (m_alarmID, i18n("next alarm: %1").arg(d.toString()));
+ else
+ m_menu->changeTitle (m_alarmID, i18n("<no alarm pending>"));
+ return true;
+}
+
+
+bool RadioDocking::noticeCountdownStarted(const TQDateTime &end)
+{
+ if (end.isValid())
+ m_menu->changeItem (m_sleepID, SmallIcon("tderadio_zzz"), i18n("Stop Sleep Countdown (running until %1)").arg(end.toString()));
+ else
+ m_menu->changeItem (m_sleepID, SmallIcon("tderadio_zzz"), i18n("Start Sleep Countdown"));
+ return true;
+}
+
+
+bool RadioDocking::noticeCountdownStopped()
+{
+ m_menu->changeItem (m_sleepID, SmallIcon("tderadio_zzz"), i18n("Start Sleep Countdown"));
+ return true;
+}
+
+
+bool RadioDocking::noticeCountdownZero()
+{
+ m_menu->changeItem (m_sleepID, SmallIcon("tderadio_zzz"), i18n("Start Sleep Countdown"));
+ return true;
+}
+
+
+bool RadioDocking::noticePowerChanged(bool on)
+{
+ m_menu->changeItem(m_powerID, SmallIcon(on ? "tderadio_muteon" : "tderadio_muteoff"),
+ on ? i18n("Power Off") : i18n("Power On"));
+ m_menu->setItemEnabled(m_pauseID, on);
+ return true;
+}
+
+bool RadioDocking::noticeCountdownSecondsChanged(int /*n*/)
+{
+ return false;
+}
+
+
+
+bool RadioDocking::noticeStationChanged (const RadioStation &rs, int /*idx*/)
+{
+ TQString s = i18n("invalid station");
+ if (rs.isValid())
+ s = rs.longName();
+
+ TQToolTip::add(this, s);
+ m_menu->changeTitle (m_titleID, i18n("TDERadio: %1").arg(s));
+ // FIXME: title does not change in opened popupmenu
+
+ TQValueList<int>::iterator iit = m_stationMenuIDs.begin();
+ TQValueList<int>::iterator end = m_stationMenuIDs.end();
+ TQStringList::iterator sit = m_stationIDs.begin();
+ for (; iit != end; ++iit, ++sit) {
+ if (*iit != -1) {
+ bool on = rs.stationID() == *sit;
+ m_menu->setItemChecked (*iit, on);
+ }
+ }
+
+ bool r = false;
+ SoundFormat sf;
+ queryIsRecordingRunning(queryCurrentSoundStreamID(), r, sf);
+ m_recordingMenu->setItemEnabled(m_recordingID, !r);
+ return true;
+}
+
+
+bool RadioDocking::noticeStationsChanged(const StationList &/*sl*/)
+{
+ buildContextMenu();
+ return true;
+}
+
+
+void RadioDocking::mousePressEvent( TQMouseEvent *e )
+{
+ KSystemTray::mousePressEvent(e);
+
+ switch ( e->button() ) {
+ case Qt::LeftButton:
+ switch (m_leftClickAction) {
+ case lcaShowHide :
+ ShowHideWidgetPlugins();
+ // FIXME: [mcamen] According the KDE usability guidelines a left
+ // click on the systray icon should show/hide the
+ // application window
+ // TODO: [mcamen] Use KSystemtray::toggleActive and friends once we
+ // depend on KDE 3.3
+ break;
+ case lcaPowerOnOff :
+ if (queryIsPowerOn())
+ sendPowerOff();
+ else
+ sendPowerOn();
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ // nothing
+ break;
+ }
+}
+
+void RadioDocking::ShowHideWidgetPlugins()
+{
+ // nothing in cache => hide everything
+ if (!m_widgetsShownCache.count()) {
+ for (TQMapIterator<WidgetPluginBase*, int> it = m_widgetPluginIDs.begin(); it != m_widgetPluginIDs.end(); ++it) {
+ WidgetPluginBase *p = it.key();
+ if (p) {
+ bool visible = p->isAnywhereVisible();
+ TQString name = p->name();
+ logDebug(TQString("visibility of %1: %2").arg(name).arg(visible));
+ m_widgetsShownCache.insert(name, visible);
+ p->getWidget()->hide();
+ }
+ }
+ }
+ else {
+ TQMap<TQString, bool> tmpCache = m_widgetsShownCache;
+ int d = KWin::currentDesktop();
+ for (TQMapIterator<WidgetPluginBase*, int> it = m_widgetPluginIDs.begin(); it != m_widgetPluginIDs.end(); ++it) {
+ WidgetPluginBase *p = it.key();
+ TQString name = p ? p->name() : TQString();
+ if (p && tmpCache.contains(name) && tmpCache[name]) {
+ p->showOnOrgDesktop();
+ }
+ }
+ m_widgetsShownCache.clear();
+ KWin::setCurrentDesktop(d);
+ }
+}
+
+void RadioDocking::slotMenuItemActivated(int id)
+{
+ const StationList &sl = queryStations();
+ TQValueList<int>::iterator iit = m_stationMenuIDs.begin();
+ TQValueList<int>::iterator end = m_stationMenuIDs.end();
+ TQStringList::iterator sit = m_stationIDs.begin();
+ for (; iit != end; ++iit, ++sit) {
+ if (*iit == id) {
+ const RadioStation &rs = sl.stationWithID(*sit);
+ if (rs.isValid())
+ sendActivateStation(rs);
+ }
+ }
+}
+
+
+void RadioDocking::noticeWidgetPluginShown(WidgetPluginBase *b, bool shown)
+{
+ if (!m_manager || !b || !m_widgetPluginIDs.contains(b))
+ return;
+ m_manager->updateWidgetPluginMenuItem(b, m_pluginMenu, m_widgetPluginIDs, shown);
+
+ if (shown)
+ m_widgetsShownCache.clear();
+}
+
+
+void RadioDocking::noticePluginsChanged(const PluginList &/*l*/)
+{
+ buildContextMenu();
+}
+
+
+// ISoundStreamClient
+
+bool RadioDocking::startRecordingWithFormat(
+ SoundStreamID id,
+ const SoundFormat &/*proposed_format*/,
+ SoundFormat &/*real_format*/)
+{
+ if (!id.isValid() || id != queryCurrentSoundStreamID() || m_StreamID2MenuID.contains(id))
+ return false;
+
+ TQString descr;
+ querySoundStreamDescription(id, descr);
+ int menu_id = m_NextRecordingMenuID++;
+ m_recordingMenu->insertItem(SmallIcon("tderadio_record"),
+ i18n("Stop Recording of %1").arg(descr),
+ menu_id);
+ m_MenuID2StreamID.insert(menu_id, id);
+ m_StreamID2MenuID.insert(id, menu_id);
+
+ if (id == queryCurrentSoundStreamID())
+ m_recordingMenu->setItemEnabled(m_recordingID, false);
+
+ setPixmap(BarIcon("tderadio_plus_rec"));
+ return false; // this is only a "hook" that does not initiate the recording so don't say that we handled the event
+}
+
+
+bool RadioDocking::stopRecording (SoundStreamID id)
+{
+ if (!id.isValid() || !m_StreamID2MenuID.contains(id))
+ return false;
+
+ int menu_id = m_StreamID2MenuID[id];
+ m_recordingMenu->removeItem(menu_id);
+ m_MenuID2StreamID.remove(menu_id);
+ m_StreamID2MenuID.remove(id);
+
+ if (id == queryCurrentSoundStreamID())
+ m_recordingMenu->setItemEnabled(m_recordingID, true);
+
+ setPixmap(BarIcon("tderadio"));
+
+ return false;
+}
+
+
+void RadioDocking::slotRecordingMenu(int i)
+{
+ if (i == POPUP_ID_START_RECORDING_DEFAULT) {
+ SoundStreamID id = queryCurrentSoundStreamID();
+ bool r = false;
+ SoundFormat sf;
+ queryIsRecordingRunning(id, r, sf);
+ if (!r) {
+ if (!queryIsPowerOn())
+ sendPowerOn();
+ sendStartRecording(id);
+ }
+ } else if (m_MenuID2StreamID.contains(i)) {
+ sendStopRecording(m_MenuID2StreamID[i]);
+ }
+}
+
+void RadioDocking::buildRecordingMenu()
+{
+ TQMap<TQString, SoundStreamID> streams;
+ queryEnumerateSoundStreams(streams);
+
+ TDEPopupMenu *m = new TDEPopupMenu(m_menu);
+
+ m_recordingID = m->insertItem(SmallIcon("tderadio_record"), i18n("Start Recording"),
+ POPUP_ID_START_RECORDING_DEFAULT);
+ TQObject::connect(m, TQT_SIGNAL(activated(int)),
+ this, TQT_SLOT(slotRecordingMenu(int)));
+ SoundStreamID currentID = queryCurrentSoundStreamID();
+
+ TQMapIterator<TQString, SoundStreamID> end = streams.end();
+ for (TQMapIterator<TQString, SoundStreamID> it = streams.begin(); it != end; ++it) {
+
+ SoundStreamID id = *it;
+ TQString descr = it.key();
+ bool r = false;
+ SoundFormat sf;
+ queryIsRecordingRunning(id, r, sf);
+ if (r) {
+ int menu_id = m_NextRecordingMenuID++;
+ m->insertItem(SmallIcon("tderadio_record"),
+ i18n("Stop Recording of %1").arg(descr),
+ menu_id);
+ m_MenuID2StreamID.insert(menu_id, id);
+ m_StreamID2MenuID.insert(id, menu_id);
+
+ if (id == currentID)
+ m_recordingMenu->setItemEnabled(m_recordingID, false);
+ }
+ }
+ m_recordingMenu = m;
+}
+
+
+bool RadioDocking::noticeSoundStreamChanged(SoundStreamID id)
+{
+ if (m_StreamID2MenuID.contains(id)) {
+ TQString descr;
+ querySoundStreamDescription(id, descr);
+ m_recordingMenu->changeItem(m_StreamID2MenuID[id],
+ SmallIcon("tderadio_record"),
+ i18n("Stop Recording of %1").arg(descr));
+ return true;
+ }
+ return false;
+}
+
+
+void RadioDocking::setLeftClickAction(LeftClickAction action)
+{
+ if (m_leftClickAction != action) {
+ m_leftClickAction = action;
+ emit sigLeftClickActionChanged(m_leftClickAction);
+ }
+}
+
+void RadioDocking::dragEnterEvent(TQDragEnterEvent* event)
+{
+ bool a = StationDragObject::canDecode(event);
+ if (a)
+ IErrorLogClient::staticLogDebug("contentsDragEnterEvent accepted");
+ else
+ IErrorLogClient::staticLogDebug("contentsDragEnterEvent rejected");
+ event->accept(a);
+}
+
+void RadioDocking::dropEvent(TQDropEvent* event)
+{
+ TQStringList list;
+
+ if ( StationDragObject::decode(event, list) ) {
+ TQStringList l = getStationSelection();
+ for (TQValueListConstIterator<TQString> it = list.begin(); it != list.end(); ++it)
+ if (!l.contains(*it))
+ l.append(*it);
+ setStationSelection(l);
+ }
+}
+
+#include "docking.moc"
diff --git a/plugins/gui-docking-menu/docking.h b/plugins/gui-docking-menu/docking.h
new file mode 100644
index 0000000..c4e5f6d
--- /dev/null
+++ b/plugins/gui-docking-menu/docking.h
@@ -0,0 +1,190 @@
+/***************************************************************************
+ docking.h - description
+ -------------------
+ begin : Mon Jan 14 2002
+ copyright : (C) 2001, 2002 by Frank Schwanz, Ernst Martin Witte
+ email : schwanz@fh-brandenburg.de, 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_DOCKING_H
+#define KRADIO_DOCKING_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ksystemtray.h>
+#include <tqpixmap.h>
+#include <tqptrdict.h>
+
+#include "../../src/include/timecontrol_interfaces.h"
+#include "../../src/include/radio_interfaces.h"
+#include "../../src/include/radiodevicepool_interfaces.h"
+#include "../../src/include/stationselection_interfaces.h"
+#include "../../src/include/plugins.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+
+enum LeftClickAction { lcaShowHide = 0, lcaPowerOnOff = 1 };
+
+class RadioDocking : public KSystemTray,
+ public PluginBase,
+ public IRadioClient,
+ public ITimeControlClient,
+ public IRadioDevicePoolClient,
+ public IStationSelection,
+ public ISoundStreamClient
+{
+Q_OBJECT
+
+public:
+ RadioDocking (const TQString &name);
+ virtual ~RadioDocking();
+
+ virtual bool connectI (Interface *);
+ virtual bool disconnectI (Interface *);
+
+ virtual TQString pluginClassName() const { return "RadioDocking"; }
+
+ virtual const TQString &name() const { return PluginBase::name(); }
+ virtual TQString &name() { return PluginBase::name(); }
+
+
+ // PluginBase
+
+public:
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+ virtual ConfigPageInfo createConfigurationPage();
+ virtual AboutPageInfo createAboutPage();
+
+
+ // IStationSelection
+
+RECEIVERS:
+ bool setStationSelection(const TQStringList &sl);
+
+ANSWERS:
+ const TQStringList & getStationSelection () const { return m_stationIDs; }
+
+
+ // IRadioDevicePoolClient
+
+RECEIVERS:
+ bool noticeActiveDeviceChanged(IRadioDevice *) { return false; }
+ bool noticeDevicesChanged(const TQPtrList<IRadioDevice> &) { return false; }
+ bool noticeDeviceDescriptionChanged(const TQString &) { return false; }
+
+ // ITimeControlClient
+
+RECEIVERS:
+ bool noticeAlarmsChanged(const AlarmVector &) { return false; }
+ bool noticeAlarm(const Alarm &) { return false; }
+ bool noticeNextAlarmChanged(const Alarm *);
+ bool noticeCountdownStarted(const TQDateTime &/*end*/);
+ bool noticeCountdownStopped();
+ bool noticeCountdownZero();
+ bool noticeCountdownSecondsChanged(int n);
+
+
+ // IRadioClient
+
+RECEIVERS:
+ bool noticePowerChanged(bool on);
+ bool noticeStationChanged (const RadioStation &, int idx);
+ bool noticeStationsChanged(const StationList &sl);
+ bool noticePresetFileChanged(const TQString &/*f*/) { return false; }
+
+ bool noticeCurrentSoundStreamIDChanged(SoundStreamID /*id*/) { return false; }
+
+ // ISoundStreamClient
+
+RECEIVERS:
+ void noticeConnectedI (ISoundStreamServer *s, bool pointer_valid);
+
+ bool startRecordingWithFormat(SoundStreamID /*id*/,
+ const SoundFormat &/*proposed_format*/,
+ SoundFormat &/*real_format*/);
+ bool stopRecording(SoundStreamID /*id*/);
+
+ bool noticeSoundStreamChanged(SoundStreamID id);
+
+
+protected slots:
+
+ void slotSeekFwd();
+ void slotSeekBkwd();
+
+ void slotPower();
+ void slotPause();
+ void slotSleepCountdown();
+ void slotShowAbout();
+
+ void slotMenuItemActivated(int id);
+ void slotRecordingMenu(int i);
+
+protected:
+ void mousePressEvent( TQMouseEvent *e );
+
+ void buildContextMenu();
+ void buildRecordingMenu();
+ void buildStationList();
+
+ void noticeWidgetPluginShown(WidgetPluginBase *, bool shown);
+ void noticePluginsChanged(const PluginList &);
+
+ void showEvent(TQShowEvent *) {} // do nothing, original implementation adds "Quit" menu item
+
+ void ShowHideWidgetPlugins();
+
+ void dragEnterEvent(TQDragEnterEvent* event);
+ void dropEvent(TQDropEvent* event);
+
+public:
+
+ LeftClickAction getLeftClickAction() const { return m_leftClickAction; }
+ void setLeftClickAction(LeftClickAction action);
+
+signals:
+ void sigLeftClickActionChanged(LeftClickAction action);
+
+protected:
+
+ TDEPopupMenu *m_menu;
+ TDEPopupMenu *m_pluginMenu;
+ TDEPopupMenu *m_recordingMenu;
+ TQStringList m_stationIDs;
+
+ // menu Item IDs
+ int m_titleID;
+ int m_alarmID;
+ int m_recordingID;
+ int m_powerID;
+ int m_pauseID;
+ int m_sleepID;
+ int m_seekfwID;
+ int m_seekbwID;
+ TQValueList<int> m_stationMenuIDs;
+
+ TQMap<WidgetPluginBase *, int> m_widgetPluginIDs;
+
+ int m_NextRecordingMenuID;
+ TQMap<int, SoundStreamID> m_MenuID2StreamID;
+ TQMap<SoundStreamID, int> m_StreamID2MenuID;
+
+ LeftClickAction m_leftClickAction;
+
+ TQMap<TQString, bool> m_widgetsShownCache;
+};
+
+
+#endif
diff --git a/plugins/gui-docking-menu/po/Makefile.am b/plugins/gui-docking-menu/po/Makefile.am
new file mode 100644
index 0000000..075b9c1
--- /dev/null
+++ b/plugins/gui-docking-menu/po/Makefile.am
@@ -0,0 +1,2 @@
+PACKAGE = tderadio-gui-docking-menu
+POFILES = AUTO
diff --git a/plugins/gui-docking-menu/po/de.po b/plugins/gui-docking-menu/po/de.po
new file mode 100644
index 0000000..81b9f3a
--- /dev/null
+++ b/plugins/gui-docking-menu/po/de.po
@@ -0,0 +1,123 @@
+# translation of de.po to
+# translation of tderadio-gui-docking-menu.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-27 16:56+0000\n"
+"Last-Translator: Chris <xchrisx@uber.space>\n"
+"Language-Team: German <https://mirror.git.trinitydesktop.org/weblate/"
+"projects/applications/tderadio-gui-docking-menu/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"
+
+#: docking-configuration.cpp:70
+msgid "Left Mouse Click on Tray"
+msgstr "Linker Mausklick auf Kontrolleistensymbol"
+
+#: docking-configuration.cpp:73
+msgid "Show/Hide all GUI Elements"
+msgstr "Alle Fenster anzeigen/verstecken"
+
+#: docking-configuration.cpp:74
+msgid "Power On/Off"
+msgstr "Ein/Ausschalten"
+
+#: docking.cpp:44
+msgid "Tray Menu for TDERadio"
+msgstr "Kontrollleistenmenü für TDERadio"
+
+#: docking.cpp:50
+msgid "Docking Plugin"
+msgstr "Plugin für die Kontrolleiste"
+
+#: docking.cpp:180
+msgid "Docking Menu"
+msgstr "Kontrolleisten-Menü"
+
+#: docking.cpp:181
+msgid "Docking Menu Configuration"
+msgstr "Einrichtung des Kontrollleisten-Menüs"
+
+#: docking.cpp:228
+msgid "Search Next Station"
+msgstr "Suche nächsten Sender"
+
+#: docking.cpp:230
+msgid "Search Previous Station"
+msgstr "Suche vorherigen Sender"
+
+#: docking.cpp:235
+msgid "Recording"
+msgstr "Aufnahme"
+
+#: docking.cpp:240
+msgid "Pause Radio"
+msgstr "Radiowiedergabe pausieren"
+
+#: docking.cpp:252
+msgid "Show/Hide Plugins"
+msgstr "Plugins anzeigen/verstecken"
+
+#: docking.cpp:354
+#, c-format
+msgid "next alarm: %1"
+msgstr "Nächstes Wecken: %1"
+
+#: docking.cpp:356
+msgid "<no alarm pending>"
+msgstr "<Wecker nicht aktiv>"
+
+#: docking.cpp:364
+msgid "Stop Sleep Countdown (running until %1)"
+msgstr "Schlummermodus abbrechen (liefe bis %1)"
+
+#: docking.cpp:366 docking.cpp:373 docking.cpp:380
+msgid "Start Sleep Countdown"
+msgstr "Schlummermodus einschalten"
+
+#: docking.cpp:388
+msgid "Power Off"
+msgstr "Ausschalten"
+
+#: docking.cpp:388
+msgid "Power On"
+msgstr "Einschalten"
+
+#: docking.cpp:402
+msgid "invalid station"
+msgstr "ungültiger Sender"
+
+#: docking.cpp:407
+#, c-format
+msgid "TDERadio: %1"
+msgstr "TDERadio: %1"
+
+#: docking.cpp:543 docking.cpp:616 docking.cpp:636
+#, c-format
+msgid "Stop Recording of %1"
+msgstr "Aufnahme %1 abbrechen"
+
+#: docking.cpp:599
+msgid "Start Recording"
+msgstr "Aufnahme starten"
diff --git a/plugins/gui-docking-menu/po/ru.po b/plugins/gui-docking-menu/po/ru.po
new file mode 100644
index 0000000..2cfe6cf
--- /dev/null
+++ b/plugins/gui-docking-menu/po/ru.po
@@ -0,0 +1,121 @@
+# translation of ru.po to
+# translation of tderadio-gui-docking-menu.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:16+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"
+
+#: docking-configuration.cpp:70
+msgid "Left Mouse Click on Tray"
+msgstr "По щелчку левой кнопкой мыши"
+
+#: docking-configuration.cpp:73
+msgid "Show/Hide all GUI Elements"
+msgstr "Показать/скрыть все окна"
+
+#: docking-configuration.cpp:74
+msgid "Power On/Off"
+msgstr "Включить/выключить"
+
+#: docking.cpp:44
+msgid "Tray Menu for TDERadio"
+msgstr "Меню лотка для TDERadio"
+
+#: docking.cpp:50
+msgid "Docking Plugin"
+msgstr "Модуль системного лотка"
+
+#: docking.cpp:180
+msgid "Docking Menu"
+msgstr "Меню лотка"
+
+#: docking.cpp:181
+msgid "Docking Menu Configuration"
+msgstr "Конфигурация меню лотка"
+
+#: docking.cpp:228
+msgid "Search Next Station"
+msgstr "Искать следующую станцию"
+
+#: docking.cpp:230
+msgid "Search Previous Station"
+msgstr "Искать предыдущую станцию"
+
+#: docking.cpp:235
+msgid "Recording"
+msgstr "Запись"
+
+#: docking.cpp:240
+msgid "Pause Radio"
+msgstr "Приостановить"
+
+#: docking.cpp:252
+msgid "Show/Hide Plugins"
+msgstr "Показать/скрыть"
+
+#: docking.cpp:354
+#, c-format
+msgid "next alarm: %1"
+msgstr "След. действие: %1"
+
+#: docking.cpp:356
+msgid "<no alarm pending>"
+msgstr "<Расписание пусто>"
+
+#: docking.cpp:364
+msgid "Stop Sleep Countdown (running until %1)"
+msgstr "Остановить таймер отключения (установлено на %1)"
+
+#: docking.cpp:366 docking.cpp:373 docking.cpp:380
+msgid "Start Sleep Countdown"
+msgstr "Запустить таймер отключения"
+
+#: docking.cpp:388
+msgid "Power Off"
+msgstr "Выключить"
+
+#: docking.cpp:388
+msgid "Power On"
+msgstr "Включить"
+
+#: docking.cpp:402
+msgid "invalid station"
+msgstr "Неверная станция"
+
+#: docking.cpp:407
+#, c-format
+msgid "TDERadio: %1"
+msgstr "Радиоприёмник KDE"
+
+#: docking.cpp:543 docking.cpp:616 docking.cpp:636
+#, c-format
+msgid "Stop Recording of %1"
+msgstr "Остановить запись %1"
+
+#: docking.cpp:599
+msgid "Start Recording"
+msgstr "Начать запись"
diff --git a/plugins/gui-docking-menu/po/tderadio-gui-docking-menu.pot b/plugins/gui-docking-menu/po/tderadio-gui-docking-menu.pot
new file mode 100644
index 0000000..f687bf3
--- /dev/null
+++ b/plugins/gui-docking-menu/po/tderadio-gui-docking-menu.pot
@@ -0,0 +1,119 @@
+# 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 ""
+
+#: docking-configuration.cpp:70
+msgid "Left Mouse Click on Tray"
+msgstr ""
+
+#: docking-configuration.cpp:73
+msgid "Show/Hide all GUI Elements"
+msgstr ""
+
+#: docking-configuration.cpp:74
+msgid "Power On/Off"
+msgstr ""
+
+#: docking.cpp:44
+msgid "Tray Menu for TDERadio"
+msgstr ""
+
+#: docking.cpp:50
+msgid "Docking Plugin"
+msgstr ""
+
+#: docking.cpp:180
+msgid "Docking Menu"
+msgstr ""
+
+#: docking.cpp:181
+msgid "Docking Menu Configuration"
+msgstr ""
+
+#: docking.cpp:228
+msgid "Search Next Station"
+msgstr ""
+
+#: docking.cpp:230
+msgid "Search Previous Station"
+msgstr ""
+
+#: docking.cpp:235
+msgid "Recording"
+msgstr ""
+
+#: docking.cpp:240
+msgid "Pause Radio"
+msgstr ""
+
+#: docking.cpp:252
+msgid "Show/Hide Plugins"
+msgstr ""
+
+#: docking.cpp:354
+#, c-format
+msgid "next alarm: %1"
+msgstr ""
+
+#: docking.cpp:356
+msgid "<no alarm pending>"
+msgstr ""
+
+#: docking.cpp:364
+msgid "Stop Sleep Countdown (running until %1)"
+msgstr ""
+
+#: docking.cpp:366 docking.cpp:373 docking.cpp:380
+msgid "Start Sleep Countdown"
+msgstr ""
+
+#: docking.cpp:388
+msgid "Power Off"
+msgstr ""
+
+#: docking.cpp:388
+msgid "Power On"
+msgstr ""
+
+#: docking.cpp:402
+msgid "invalid station"
+msgstr ""
+
+#: docking.cpp:407
+#, c-format
+msgid "TDERadio: %1"
+msgstr ""
+
+#: docking.cpp:543 docking.cpp:616 docking.cpp:636
+#, c-format
+msgid "Stop Recording of %1"
+msgstr ""
+
+#: docking.cpp:599
+msgid "Start Recording"
+msgstr ""
diff --git a/plugins/gui-error-log/CMakeL10n.txt b/plugins/gui-error-log/CMakeL10n.txt
new file mode 100644
index 0000000..ba6c0c8
--- /dev/null
+++ b/plugins/gui-error-log/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-gui-error-log"
+ DESTINATION "po"
+)
diff --git a/plugins/gui-error-log/Makefile.am b/plugins/gui-error-log/Makefile.am
new file mode 100644
index 0000000..0e19ea4
--- /dev/null
+++ b/plugins/gui-error-log/Makefile.am
@@ -0,0 +1,17 @@
+SUBDIRS = po .
+
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = liberror-log.la
+liberror_log_la_SOURCES = errorlog.cpp
+liberror_log_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+
+noinst_HEADERS = errorlog.h
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-gui-error-log.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-gui-error-log.pot
diff --git a/plugins/gui-error-log/errorlog.cpp b/plugins/gui-error-log/errorlog.cpp
new file mode 100644
index 0000000..1ed8fdf
--- /dev/null
+++ b/plugins/gui-error-log/errorlog.cpp
@@ -0,0 +1,263 @@
+/***************************************************************************
+ errorlog.cpp - description
+ -------------------
+ begin : Sa Sep 13 2003
+ copyright : (C) 2003 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 "errorlog.h"
+
+#include <tqframe.h>
+#include <tqdatetime.h>
+#include <tqlayout.h>
+
+#include <tdelocale.h>
+#include <kiconloader.h>
+#include <tqtextedit.h>
+#include <tdefiledialog.h>
+#include <kurl.h>
+#include <tdetempfile.h>
+#include <tdeio/netaccess.h>
+
+#define PAGE_ID_INFO 0
+#define PAGE_ID_WARN 1
+#define PAGE_ID_ERROR 2
+#define PAGE_ID_DEBUG 3
+
+///////////////////////////////////////////////////////////////////////
+
+PLUGIN_LIBRARY_FUNCTIONS(ErrorLog, "tderadio-gui-error-log", i18n("Error Logging Window for TDERadio"));
+
+/////////////////////////////////////////////////////////////////////////////
+
+ErrorLog::ErrorLog(const TQString &name)
+ : KDialogBase(KDialogBase::IconList,
+ "",
+ KDialogBase::Close|KDialogBase::User1,
+ KDialogBase::Close,
+ NULL,
+ name.ascii(),
+ false,
+ false,
+ KGuiItem(i18n("Save &as"), "document-save-as")
+ ),
+ WidgetPluginBase(name, i18n("Error Logger")),
+ init_done(false)
+{
+ TQWidget::setCaption(i18n("TDERadio Logger"));
+ TQFrame *info = addPage(i18n("Information"), i18n("Information"),
+ TDEGlobal::instance()->iconLoader()->loadIcon(
+ "messagebox_info", TDEIcon::NoGroup, TDEIcon::SizeMedium
+ )
+ );
+
+ TQGridLayout *linfo = new TQGridLayout(info);
+ linfo->setSpacing( 5 );
+ linfo->setMargin ( 0 );
+ m_teInfos = new TQTextEdit(info);
+ linfo->addWidget(m_teInfos, 0, 0);
+ m_teInfos->setReadOnly(true);
+ logInfo(i18n("logging started"));
+
+
+ TQFrame *warn = addPage(i18n("Warnings"), i18n("Warnings"),
+ TDEGlobal::instance()->iconLoader()->loadIcon(
+ "messagebox_warning", TDEIcon::NoGroup, TDEIcon::SizeMedium
+ )
+ );
+ TQGridLayout *lwarn = new TQGridLayout(warn);
+ lwarn->setSpacing( 5 );
+ lwarn->setMargin ( 0 );
+ m_teWarnings = new TQTextEdit(warn);
+ lwarn->addWidget(m_teWarnings, 0, 0);
+ m_teWarnings->setReadOnly(true);
+ logWarning(i18n("logging started"));
+
+
+
+ TQFrame *err = addPage(i18n("Errors"), i18n("Errors"),
+ TDEGlobal::instance()->iconLoader()->loadIcon(
+ "messagebox_critical", TDEIcon::NoGroup, TDEIcon::SizeMedium
+ )
+ );
+ TQGridLayout *lerr = new TQGridLayout(err);
+ lerr->setSpacing( 5 );
+ lerr->setMargin ( 0 );
+ m_teErrors = new TQTextEdit(err);
+ lerr->addWidget(m_teErrors, 0, 0);
+ m_teErrors->setReadOnly(true);
+ logError(i18n("logging started"));
+
+ TQFrame *debug = addPage(i18n("Debugging"), i18n("Debugging"),
+ TDEGlobal::instance()->iconLoader()->loadIcon(
+ "edit-find", TDEIcon::NoGroup, TDEIcon::SizeMedium
+ )
+ );
+
+ TQGridLayout *ldebug = new TQGridLayout(debug);
+ ldebug->setSpacing( 5 );
+ ldebug->setMargin ( 0 );
+ m_teDebug = new TQTextEdit(debug);
+ ldebug->addWidget(m_teDebug, 0, 0);
+ m_teDebug->setReadOnly(true);
+ logDebug(i18n("logging started"));
+
+ init_done = true;
+}
+
+
+ErrorLog::~ErrorLog()
+{
+}
+
+bool ErrorLog::connectI (Interface *i)
+{
+ bool a = IErrorLog::connectI(i);
+ bool b = PluginBase::connectI(i);
+ return a || b;
+}
+
+bool ErrorLog::disconnectI (Interface *i)
+{
+ bool a = IErrorLog::disconnectI(i);
+ bool b = PluginBase::disconnectI(i);
+ return a || b;
+}
+
+void ErrorLog::restoreState (TDEConfig *config)
+{
+ config->setGroup(TQString("errorlog-") + WidgetPluginBase::name());
+ WidgetPluginBase::restoreState(config, false);
+}
+
+
+void ErrorLog::saveState (TDEConfig *config) const
+{
+ config->setGroup(TQString("errorlog-") + WidgetPluginBase::name());
+ WidgetPluginBase::saveState(config);
+}
+
+
+void ErrorLog::show()
+{
+ WidgetPluginBase::pShow();
+ KDialogBase::show();
+}
+
+void ErrorLog::showOnOrgDesktop()
+{
+ WidgetPluginBase::pShowOnOrgDesktop();
+ //KDialogBase::show();
+}
+
+void ErrorLog::hide()
+{
+ logDebug(TQString("%1, ErrorLog::hide: all: %2, desktop: %3, visible:%4, anywherevisible:%5, cachevalid: %6").arg(name()).arg(m_saveSticky).arg(m_saveDesktop).arg(isReallyVisible()).arg(isAnywhereVisible()).arg(m_geoCacheValid));
+ WidgetPluginBase::pHide();
+ KDialogBase::hide();
+}
+
+void ErrorLog::showEvent(TQShowEvent *e)
+{
+ KDialogBase::showEvent(e);
+ WidgetPluginBase::pShowEvent(e);
+}
+
+void ErrorLog::hideEvent(TQHideEvent *e)
+{
+ KDialogBase::hideEvent(e);
+ WidgetPluginBase::pHideEvent(e);
+}
+
+// IErrorLog
+
+bool ErrorLog::logError (const TQString &s)
+{
+ m_teErrors->append("<i>" + TQDateTime::currentDateTime().toString(Qt::ISODate) + "</i> " + s + "\n");
+ if (init_done) {
+ showPage(PAGE_ID_ERROR);
+ show();
+ }
+ return true;
+}
+
+bool ErrorLog::logWarning(const TQString &s)
+{
+ m_teWarnings->append("<i>" + TQDateTime::currentDateTime().toString(Qt::ISODate) + "</i> " + s + "\n");
+ return true;
+}
+
+bool ErrorLog::logInfo (const TQString &s)
+{
+ m_teInfos->append("<i>" + TQDateTime::currentDateTime().toString(Qt::ISODate) + "</i> " + s + "\n");
+ return true;
+}
+
+bool ErrorLog::logDebug (const TQString &s)
+{
+ m_teDebug->append("<i>" + TQDateTime::currentDateTime().toString(Qt::ISODate) + "</i> " + s + "\n");
+ return true;
+}
+
+// KDialogBase
+
+
+// store Log Data
+void ErrorLog::slotUser1()
+{
+ KFileDialog fd("",
+ ("*.log|" + i18n("Log Files") + "( *.log )").ascii(),
+ this,
+ i18n("Select Log File").ascii(),
+ true);
+ fd.setMode(KFile::File);
+ fd.setOperationMode(KFileDialog::Saving);
+ fd.setCaption (i18n("Save TDERadio Logging Data as ..."));
+
+ if (fd.exec() == TQDialog::Accepted) {
+ KURL url = fd.selectedURL();
+
+ KTempFile tmpFile;
+ tmpFile.setAutoDelete(true);
+ TQFile *outf = tmpFile.file();
+
+ TQTextStream outs(outf);
+ outs.setEncoding(TQTextStream::UnicodeUTF8);
+
+ switch (activePageIndex()) {
+ case PAGE_ID_INFO: outs << m_teInfos->text(); break;
+ case PAGE_ID_WARN: outs << m_teWarnings->text(); break;
+ case PAGE_ID_ERROR: outs << m_teErrors->text(); break;
+ case PAGE_ID_DEBUG: outs << m_teDebug->text(); break;
+ default: break;
+ }
+
+ if (outf->status() != IO_Ok) {
+ logError("ErrorLogger: " +
+ i18n("error writing to tempfile %1").arg(tmpFile.name()));
+ return;
+ }
+
+ // close hopefully flushes buffers ;)
+ outf->close();
+
+ if (!TDEIO::NetAccess::upload(tmpFile.name(), url, this)) {
+ logError("ErrorLogger: " +
+ i18n("error uploading preset file %1").arg(url.url()));
+ }
+ }
+ setIconListAllVisible(true);
+}
+
+
+#include "errorlog.moc"
diff --git a/plugins/gui-error-log/errorlog.h b/plugins/gui-error-log/errorlog.h
new file mode 100644
index 0000000..26bd0c0
--- /dev/null
+++ b/plugins/gui-error-log/errorlog.h
@@ -0,0 +1,90 @@
+/***************************************************************************
+ errorlog.h - description
+ -------------------
+ begin : Sa Sep 13 2003
+ copyright : (C) 2003 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_ERRORLOG_H
+#define KRADIO_ERRORLOG_H
+
+#include <kdialogbase.h>
+
+#include "../../src/include/errorlog-interfaces.h"
+#include "../../src/include/widgetplugins.h"
+
+
+class TQTextEdit;
+class ErrorLog : public KDialogBase,
+ public WidgetPluginBase,
+ public IErrorLog
+{
+Q_OBJECT
+
+public:
+ ErrorLog(const TQString &name = TQString());
+ ~ErrorLog();
+
+ virtual TQString pluginClassName() const { return "ErrorLog"; }
+ virtual const TQString &name() const { return PluginBase::name(); }
+ virtual TQString &name() { return PluginBase::name(); }
+
+ virtual bool connectI (Interface *);
+ virtual bool disconnectI (Interface *);
+
+// WidgetPluginBase
+
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+public slots:
+ virtual void showOnOrgDesktop();
+ virtual void show();
+ virtual void hide();
+ virtual void toggleShown () { WidgetPluginBase::pToggleShown(); }
+
+protected:
+ TQWidget *getWidget() { return this; }
+ const TQWidget *getWidget() const { return this; }
+
+ virtual void showEvent(TQShowEvent *);
+ virtual void hideEvent(TQHideEvent *);
+
+ virtual ConfigPageInfo createConfigurationPage () { return ConfigPageInfo(); }
+ virtual AboutPageInfo createAboutPage () { return AboutPageInfo(); }
+
+// IErrorLog
+
+RECEIVERS:
+ bool logError (const TQString &);
+ bool logWarning(const TQString &);
+ bool logInfo (const TQString &);
+ bool logDebug (const TQString &);
+
+// KDialogBase
+
+protected slots:
+
+ void slotUser1();
+
+protected:
+
+ TQTextEdit *m_teDebug,
+ *m_teInfos,
+ *m_teWarnings,
+ *m_teErrors;
+
+ bool init_done;
+};
+
+#endif
diff --git a/plugins/gui-error-log/po/Makefile.am b/plugins/gui-error-log/po/Makefile.am
new file mode 100644
index 0000000..cab56dc
--- /dev/null
+++ b/plugins/gui-error-log/po/Makefile.am
@@ -0,0 +1,2 @@
+PACKAGE = tderadio-gui-error-log
+POFILES = AUTO
diff --git a/plugins/gui-error-log/po/de.po b/plugins/gui-error-log/po/de.po
new file mode 100644
index 0000000..10ceda9
--- /dev/null
+++ b/plugins/gui-error-log/po/de.po
@@ -0,0 +1,86 @@
+# translation of de.po to
+# translation of tderadio-gui-error-log.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-08-31 00:45+0000\n"
+"Last-Translator: Chris <xchrisx@uber.space>\n"
+"Language-Team: German <https://mirror.git.trinitydesktop.org/weblate/"
+"projects/applications/tderadio-gui-error-log/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.8\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 "Chris (TDE)"
+
+#. 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 "(Keine Email)"
+
+#: errorlog.cpp:39
+msgid "Error Logging Window for TDERadio"
+msgstr "Fehlerprotokollierungsfenster für TDERadio"
+
+#: errorlog.cpp:52
+msgid "Save &as"
+msgstr "Sichern &unter"
+
+#: errorlog.cpp:54
+msgid "Error Logger"
+msgstr "Fehlerprotokoll"
+
+#: errorlog.cpp:57
+msgid "TDERadio Logger"
+msgstr "TDERadio Fehlerprotokoll"
+
+#: errorlog.cpp:70 errorlog.cpp:84 errorlog.cpp:99 errorlog.cpp:113
+msgid "logging started"
+msgstr "Beginn des Protokollierung"
+
+#: errorlog.cpp:73
+msgid "Warnings"
+msgstr "Warnungen"
+
+#: errorlog.cpp:88
+msgid "Errors"
+msgstr "Fehler"
+
+#: errorlog.cpp:101
+msgid "Debugging"
+msgstr "Fehlersuche"
+
+#: errorlog.cpp:219
+msgid "Log Files"
+msgstr "Protokoll-Dateien"
+
+#: errorlog.cpp:221
+msgid "Select Log File"
+msgstr "Auswahl der Protokolldatei"
+
+#: errorlog.cpp:225
+msgid "Save TDERadio Logging Data as ..."
+msgstr "TDERadio-Fehlerprotokoll sichern untern ..."
+
+#: errorlog.cpp:247
+#, c-format
+msgid "error writing to tempfile %1"
+msgstr "Fehler beim schreiben in die temporäre Datei %1"
+
+#: errorlog.cpp:256
+#, c-format
+msgid "error uploading preset file %1"
+msgstr "Fehler beim Upload der Senderdatei %1"
diff --git a/plugins/gui-error-log/po/ru.po b/plugins/gui-error-log/po/ru.po
new file mode 100644
index 0000000..c8d2ef3
--- /dev/null
+++ b/plugins/gui-error-log/po/ru.po
@@ -0,0 +1,87 @@
+# translation of ru.po to
+# translation of tderadio-gui-error-log.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: 2020-01-03 16:07+0000\n"
+"Last-Translator: Serg Bormant <bormant@mail.ru>\n"
+"Language-Team: Russian <https://mirror.git.trinitydesktop.org/weblate/"
+"projects/applications/tderadio-gui-error-log/ru/>\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Generator: Weblate 3.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 ""
+
+#: errorlog.cpp:39
+msgid "Error Logging Window for TDERadio"
+msgstr "Окно ведения журнала ошибок TDERadio"
+
+#: errorlog.cpp:52
+msgid "Save &as"
+msgstr "Сохранить &как"
+
+#: errorlog.cpp:54
+msgid "Error Logger"
+msgstr "Журнал ошибок"
+
+#: errorlog.cpp:57
+msgid "TDERadio Logger"
+msgstr "Журнал TDERadio"
+
+#: errorlog.cpp:70 errorlog.cpp:84 errorlog.cpp:99 errorlog.cpp:113
+msgid "logging started"
+msgstr "Журналирование включено"
+
+#: errorlog.cpp:73
+msgid "Warnings"
+msgstr "Предупреждения"
+
+#: errorlog.cpp:88
+msgid "Errors"
+msgstr "Ошибки"
+
+#: errorlog.cpp:101
+msgid "Debugging"
+msgstr "Отладка"
+
+#: errorlog.cpp:219
+msgid "Log Files"
+msgstr "Файлы журнала"
+
+#: errorlog.cpp:221
+msgid "Select Log File"
+msgstr "Выберите файлы журнала"
+
+#: errorlog.cpp:225
+msgid "Save TDERadio Logging Data as ..."
+msgstr "Сохранить данные журнала TDERadio как..."
+
+#: errorlog.cpp:247
+#, c-format
+msgid "error writing to tempfile %1"
+msgstr "Ошибка записи во временный файл %1"
+
+#: errorlog.cpp:256
+#, c-format
+msgid "error uploading preset file %1"
+msgstr "Ошибка выгрузки файла настроек %1"
diff --git a/plugins/gui-error-log/po/tderadio-gui-error-log.pot b/plugins/gui-error-log/po/tderadio-gui-error-log.pot
new file mode 100644
index 0000000..b836a14
--- /dev/null
+++ b/plugins/gui-error-log/po/tderadio-gui-error-log.pot
@@ -0,0 +1,82 @@
+# 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 ""
+
+#: errorlog.cpp:39
+msgid "Error Logging Window for TDERadio"
+msgstr ""
+
+#: errorlog.cpp:52
+msgid "Save &as"
+msgstr ""
+
+#: errorlog.cpp:54
+msgid "Error Logger"
+msgstr ""
+
+#: errorlog.cpp:57
+msgid "TDERadio Logger"
+msgstr ""
+
+#: errorlog.cpp:70 errorlog.cpp:84 errorlog.cpp:99 errorlog.cpp:113
+msgid "logging started"
+msgstr ""
+
+#: errorlog.cpp:73
+msgid "Warnings"
+msgstr ""
+
+#: errorlog.cpp:88
+msgid "Errors"
+msgstr ""
+
+#: errorlog.cpp:101
+msgid "Debugging"
+msgstr ""
+
+#: errorlog.cpp:219
+msgid "Log Files"
+msgstr ""
+
+#: errorlog.cpp:221
+msgid "Select Log File"
+msgstr ""
+
+#: errorlog.cpp:225
+msgid "Save TDERadio Logging Data as ..."
+msgstr ""
+
+#: errorlog.cpp:247
+#, c-format
+msgid "error writing to tempfile %1"
+msgstr ""
+
+#: errorlog.cpp:256
+#, c-format
+msgid "error uploading preset file %1"
+msgstr ""
diff --git a/plugins/gui-quickbar/CMakeL10n.txt b/plugins/gui-quickbar/CMakeL10n.txt
new file mode 100644
index 0000000..5c9cc3b
--- /dev/null
+++ b/plugins/gui-quickbar/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-gui-quickbar"
+ DESTINATION "po"
+)
diff --git a/plugins/gui-quickbar/Makefile.am b/plugins/gui-quickbar/Makefile.am
new file mode 100644
index 0000000..c43d957
--- /dev/null
+++ b/plugins/gui-quickbar/Makefile.am
@@ -0,0 +1,18 @@
+SUBDIRS = po .
+
+INCLUDES = -I$(top_builddir)/src $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = libquickbar.la
+libquickbar_la_SOURCES = buttonflowlayout.cpp quickbar.cpp \
+ quickbar-configuration.cpp
+libquickbar_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+
+noinst_HEADERS = buttonflowlayout.h quickbar-configuration.h quickbar.h
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-gui-quickbar.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-gui-quickbar.pot
diff --git a/plugins/gui-quickbar/buttonflowlayout.cpp b/plugins/gui-quickbar/buttonflowlayout.cpp
new file mode 100644
index 0000000..45c19d5
--- /dev/null
+++ b/plugins/gui-quickbar/buttonflowlayout.cpp
@@ -0,0 +1,268 @@
+/****************************************************************************
+** $Id: buttonflowtqlayout.cpp 272 2005-05-18 08:12:51Z emw $
+**
+** Implementing your own layout: flow example
+**
+** Copyright (C) 1996 by Trolltech AS. All rights reserved.
+**
+** This file is part of an example program for TQt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+/**
+ Modified 2002 by Klas Kalass (klas.kalass@gmx.de) for tderadio
+ */
+
+#include <kdebug.h>
+
+#include "buttonflowlayout.h"
+
+/*********************************************/
+/* Iterator */
+class ButtonFlowLayoutIterator :public TQGLayoutIterator
+{
+public:
+ ButtonFlowLayoutIterator( TQPtrList<TQLayoutItem> *l ) :idx(0), list(l) {}
+ uint count() const;
+ TQLayoutItem *current();
+ TQLayoutItem *next();
+ TQLayoutItem *takeCurrent();
+
+private:
+ int idx;
+ TQPtrList<TQLayoutItem> *list;
+
+};
+
+uint ButtonFlowLayoutIterator::count() const
+{
+ return list->count();
+}
+
+TQLayoutItem *ButtonFlowLayoutIterator::current()
+{
+ return idx < int(count()) ? list->at(idx) : 0;
+}
+
+TQLayoutItem *ButtonFlowLayoutIterator::next()
+{
+ idx++; return current();
+}
+
+TQLayoutItem *ButtonFlowLayoutIterator::takeCurrent()
+{
+ return idx < int(count()) ? list->take( idx ) : 0;
+}
+
+/**************************************************************/
+
+ButtonFlowLayout::ButtonFlowLayout( TQWidget *parent, int margin, int spacing,
+ const char *name )
+ : TQLayout( parent, margin, spacing, name ),
+ cached_width(0)
+{
+}
+
+ButtonFlowLayout::ButtonFlowLayout( TQLayout* parentLayout, int spacing, const char *name )
+ : TQLayout( parentLayout, spacing, name ),
+ cached_width(0)
+{
+}
+
+ButtonFlowLayout::ButtonFlowLayout( int spacing, const char *name )
+ : TQLayout( spacing, name ),
+ cached_width(0)
+{
+}
+
+ButtonFlowLayout::~ButtonFlowLayout()
+{
+ deleteAllItems();
+}
+
+
+int ButtonFlowLayout::heightForWidth( int w ) const
+{
+ if ( cached_width != w ) {
+ //Not all C++ compilers support "mutable" yet:
+ ButtonFlowLayout * mthis = (ButtonFlowLayout*)this;
+ int h = mthis->doLayout( TQRect(0,0,w,0), TRUE );
+ mthis->cached_hfw = h;
+ mthis->cached_width = w;
+ return h;
+ }
+ return cached_hfw;
+}
+
+void ButtonFlowLayout::addItem( TQLayoutItem *item)
+{
+ list.append( TQT_TQLAYOUTITEM(item) );
+}
+
+bool ButtonFlowLayout::hasHeightForWidth() const
+{
+ return TRUE;
+}
+
+TQSize ButtonFlowLayout::sizeHint() const
+{
+ return minimumSize();
+}
+
+TQSizePolicy::ExpandData ButtonFlowLayout::expanding() const
+{
+ return TQ_SPNoDirection;
+}
+
+TQLayoutIterator ButtonFlowLayout::iterator()
+{
+ // [FIXME]
+#ifdef USE_QT4
+ #warning [FIXME] ContainerAreaLayout iterators may not function correctly under Qt4
+ return TQLayoutIterator( this ); // [FIXME]
+#else // USE_QT4
+ return TQLayoutIterator( new ButtonFlowLayoutIterator( &list ) );
+#endif // USE_QT4
+}
+
+void ButtonFlowLayout::setGeometry( const TQRect &r )
+{
+ TQLayout::setGeometry( r );
+ doLayout( r );
+}
+
+int ButtonFlowLayout::doLayout( const TQRect &r, bool testonly )
+{
+/* kdDebug() << "buttonflowlayout::doLayout ("
+ << r.x() << "," << r.y() << ","
+ << r.width() << "," << r.height() << ", " << testonly << ")\n";
+*/
+ float x = r.x();
+ float y = r.y();
+ int h = 0; //height of this line so far.
+ float buttonWidth = 0;
+ int buttonHeight = 0;
+ int linecount = 0;
+ int totalWidth = r.width();
+ int totalHeight = r.height();
+
+ TQPtrListIterator<TQLayoutItem> it(list);
+ TQLayoutItem *o;
+
+ // get the width of the biggest Button
+
+ it.toFirst();
+ while ( (o=it.current()) != 0 ) {
+ ++it;
+ buttonWidth = TQMAX( buttonWidth, o->sizeHint().width() );
+ buttonHeight = TQMAX( buttonHeight, o->sizeHint().height() );
+ }
+
+ // calculate the optimal width
+ unsigned int columns = (totalWidth + spacing()) /
+ ((int)buttonWidth + spacing());
+ if (columns > it.count() ) columns = it.count();
+ if (columns == 0) columns = 1; // avoid division by zero
+
+
+ int rows = (it.count() - 1) / columns + 1;
+ float deltaH = (float)(totalHeight - rows * buttonHeight - (rows - 1) * spacing())
+ / (float)(rows + 1) ;
+ if (deltaH < 0) deltaH = 0;
+
+ y += deltaH;
+
+ buttonWidth = (float)(totalWidth - spacing()*(columns-1)) / (float)columns;
+
+/* fprintf (stderr, "cols = %i col-width = %f\n"
+ "rows = %i row-height = %i\n"
+ "w = %i h = %i\n",
+ columns, buttonWidth,
+ rows, buttonHeight,
+ totalWidth, totalHeight
+ );
+*/
+ // calculate the positions and sizes
+ it.toFirst();
+ while ( (o = it.current()) != 0 ) {
+
+// fprintf (stderr, "x = %i y = %i\n", x, (int)y);
+ ++it;
+ int btnRight = (int)rint(x + buttonWidth) - 1,
+ btnLeft = (int)rint(x);
+
+ if ( btnRight > r.right() && h > 0 ) {
+ x = r.x();
+ btnRight = (int)rint(x + buttonWidth) - 1;
+ btnLeft = (int)rint(x);
+
+ y += h + spacing() + deltaH;
+ h = 0;
+ linecount++;
+ }
+ if (!testonly)
+ o->setGeometry( TQRect( TQPoint( btnLeft, (int)rint(y) ),
+ TQSize( btnRight - btnLeft + 1,
+ buttonHeight) )
+ );
+
+ x += buttonWidth + spacing();
+ h = TQMAX( h, buttonHeight );
+ }
+
+ int ret = (int)rint(y + h + deltaH) - r.y();
+
+// kdDebug() << "ButtonFlowLayout::doLayout() = " << ret << endl;
+ return ret;
+}
+
+
+TQSize ButtonFlowLayout::minimumSize() const
+{
+ return minimumSize(geometry().size());
+}
+
+
+TQSize ButtonFlowLayout::minimumSize(const TQSize &r) const
+{
+ TQSize s(0, 0);
+
+ for (TQPtrListIterator<TQLayoutItem> it(list); it.current(); ++it) {
+ TQLayoutItem *o = it.current();
+ s = s.expandedTo( o->sizeHint()); //minimumSize() );
+ }
+
+ s.setHeight(heightForWidth(r.width()));
+
+ return s;
+}
+
+#ifdef USE_QT4
+/*!
+ \reimp
+*/
+int ButtonFlowLayout::count() const {
+ return list.count();
+}
+
+/*!
+ \reimp
+*/
+TQLayoutItem* ButtonFlowLayout::itemAt(int index) const {
+ return index >= 0 && index < list.count() ? (const_cast<TQPtrList<TQLayoutItem>&>(list).at(index)) : 0;
+}
+
+/*!
+ \reimp
+*/
+TQLayoutItem* ButtonFlowLayout::takeAt(int index) {
+ if (index < 0 || index >= list.count())
+ return 0;
+ TQLayoutItem *item = list.at(index);
+ list.remove(list.at(index));
+ delete item;
+
+ invalidate();
+ return item;
+}
+#endif // USE_QT4
diff --git a/plugins/gui-quickbar/buttonflowlayout.h b/plugins/gui-quickbar/buttonflowlayout.h
new file mode 100644
index 0000000..f092a74
--- /dev/null
+++ b/plugins/gui-quickbar/buttonflowlayout.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+** $Id: buttonflowtqlayout.h 471 2006-11-11 17:04:51Z emw $
+**
+** Definition of simple flow layout for custom layout example
+**
+** Created : 979899
+**
+** Copyright (C) 1997 by Trolltech AS. All rights reserved.
+**
+** This file is part of an example program for TQt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+/**
+ Modified 2002 by Klas Kalass (klas.kalass@gmx.de) for tderadio
+ */
+#ifndef BUTTONFLOWLAYOUT_H
+#define BUTTONFLOWLAYOUT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/utils.h"
+
+#include <tqlayout.h>
+#include <tqptrlist.h>
+
+class ButtonFlowLayout : public TQLayout
+{
+public:
+ ButtonFlowLayout( TQWidget *parent, int margin = 0, int spacing=-1,
+ const char *name=0 );
+
+ ButtonFlowLayout( TQLayout* parentLayout, int spacing=-1, const char *name=0 );
+
+ ButtonFlowLayout( int spacing=-1, const char *name=0 );
+
+ ~ButtonFlowLayout();
+
+ void addItem( TQLayoutItem *item);
+ bool hasHeightForWidth() const;
+ int heightForWidth( int ) const;
+ TQSize sizeHint() const;
+ TQSize minimumSize() const;
+ TQSize minimumSize(const TQSize &r) const; // minimumSize is dependent from width
+ TQLayoutIterator iterator();
+ TQSizePolicy::ExpandData expanding() const;
+
+#ifdef USE_QT4
+ QLAYOUT_REQUIRED_METHOD_DECLARATIONS
+#endif // USE_QT4
+
+protected:
+ void setGeometry( const TQRect& );
+
+private:
+ int doLayout( const TQRect&, bool testonly = FALSE );
+ TQPtrList<TQLayoutItem> list;
+ int cached_width;
+ int cached_hfw;
+};
+
+#endif
diff --git a/plugins/gui-quickbar/po/Makefile.am b/plugins/gui-quickbar/po/Makefile.am
new file mode 100644
index 0000000..1d1d306
--- /dev/null
+++ b/plugins/gui-quickbar/po/Makefile.am
@@ -0,0 +1,2 @@
+PACKAGE = tderadio-gui-quickbar
+POFILES = AUTO
diff --git a/plugins/gui-quickbar/po/de.po b/plugins/gui-quickbar/po/de.po
new file mode 100644
index 0000000..5a44929
--- /dev/null
+++ b/plugins/gui-quickbar/po/de.po
@@ -0,0 +1,56 @@
+# translation of de.po to
+# translation of tderadio-gui-quickbar.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-27 16:56+0000\n"
+"Last-Translator: Chris <xchrisx@uber.space>\n"
+"Language-Team: German <https://mirror.git.trinitydesktop.org/weblate/"
+"projects/applications/tderadio-gui-quickbar/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"
+
+#: quickbar.cpp:42
+msgid "Radio Station Quick Selection Toolbar"
+msgstr "Senderkurzwahlfenster"
+
+#: quickbar.cpp:48
+msgid "Quickbar Plugin"
+msgstr "Schnellauswahlfenster"
+
+#: quickbar.cpp:139
+msgid "Quickbar"
+msgstr "Kurzwahlfenster"
+
+#: quickbar.cpp:140
+msgid "Quickbar Configuration"
+msgstr "Einrichtung des Kurzwahlfensters"
+
+#: quickbar.cpp:404
+msgid "contentsDragEnterEvent accepted"
+msgstr "contentsDragEnterEvent angenommen"
+
+#: quickbar.cpp:406
+msgid "contentsDragEnterEvent rejected"
+msgstr "contentsDragEnterEvent abgelehnt"
diff --git a/plugins/gui-quickbar/po/ru.po b/plugins/gui-quickbar/po/ru.po
new file mode 100644
index 0000000..48f2b3f
--- /dev/null
+++ b/plugins/gui-quickbar/po/ru.po
@@ -0,0 +1,56 @@
+# translation of ru.po to
+# translation of tderadio-gui-quickbar.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:00+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"
+
+#: quickbar.cpp:42
+msgid "Radio Station Quick Selection Toolbar"
+msgstr "Панель быстрого выбора радиостанций"
+
+#: quickbar.cpp:48
+msgid "Quickbar Plugin"
+msgstr "Панель быстрого доступа"
+
+#: quickbar.cpp:139
+msgid "Quickbar"
+msgstr ""
+"Панель\n"
+" радиостанций"
+
+#: quickbar.cpp:140
+msgid "Quickbar Configuration"
+msgstr "Настройка панели быстрого доступа"
+
+#: quickbar.cpp:404
+msgid "contentsDragEnterEvent accepted"
+msgstr "contentsDragEnterEvent accepted"
+
+#: quickbar.cpp:406
+msgid "contentsDragEnterEvent rejected"
+msgstr "contentsDragEnterEvent rejected"
diff --git a/plugins/gui-quickbar/po/tderadio-gui-quickbar.pot b/plugins/gui-quickbar/po/tderadio-gui-quickbar.pot
new file mode 100644
index 0000000..b78488f
--- /dev/null
+++ b/plugins/gui-quickbar/po/tderadio-gui-quickbar.pot
@@ -0,0 +1,52 @@
+# 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 ""
+
+#: quickbar.cpp:42
+msgid "Radio Station Quick Selection Toolbar"
+msgstr ""
+
+#: quickbar.cpp:48
+msgid "Quickbar Plugin"
+msgstr ""
+
+#: quickbar.cpp:139
+msgid "Quickbar"
+msgstr ""
+
+#: quickbar.cpp:140
+msgid "Quickbar Configuration"
+msgstr ""
+
+#: quickbar.cpp:404
+msgid "contentsDragEnterEvent accepted"
+msgstr ""
+
+#: quickbar.cpp:406
+msgid "contentsDragEnterEvent rejected"
+msgstr ""
diff --git a/plugins/gui-quickbar/quickbar-configuration.cpp b/plugins/gui-quickbar/quickbar-configuration.cpp
new file mode 100644
index 0000000..7fcedb1
--- /dev/null
+++ b/plugins/gui-quickbar/quickbar-configuration.cpp
@@ -0,0 +1,35 @@
+/***************************************************************************
+ quickbar-configuration.cpp - description
+ -------------------
+ begin : Son Aug 3 2003
+ copyright : (C) 2003 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 "quickbar-configuration.h"
+
+using namespace std;
+
+QuickbarConfiguration::QuickbarConfiguration (TQWidget *parent)
+ : StationSelector(parent)
+{
+}
+
+
+QuickbarConfiguration::~QuickbarConfiguration ()
+{
+}
+
+
+
+
+#include "quickbar-configuration.moc"
diff --git a/plugins/gui-quickbar/quickbar-configuration.h b/plugins/gui-quickbar/quickbar-configuration.h
new file mode 100644
index 0000000..e431921
--- /dev/null
+++ b/plugins/gui-quickbar/quickbar-configuration.h
@@ -0,0 +1,37 @@
+/***************************************************************************
+ quickbar-configuration.h - description
+ -------------------
+ begin : Son Aug 3 2003
+ copyright : (C) 2003 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_QUICKBAR_CONFIGURATION_H
+#define KRADIO_QUICKBAR_CONFIGURATION_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/stationselector.h"
+
+class QuickbarConfiguration : public StationSelector
+{
+Q_OBJECT
+
+public :
+ QuickbarConfiguration (TQWidget *parent);
+ ~QuickbarConfiguration ();
+
+};
+
+#endif
diff --git a/plugins/gui-quickbar/quickbar.cpp b/plugins/gui-quickbar/quickbar.cpp
new file mode 100644
index 0000000..d8bba88
--- /dev/null
+++ b/plugins/gui-quickbar/quickbar.cpp
@@ -0,0 +1,424 @@
+/***************************************************************************
+ quickbar.cpp - description
+ -------------------
+ begin : Mon Feb 11 2002
+ copyright : (C) 2002 by Martin Witte / Frank Schwanz
+ email : witte@kawo1.rwth-aachen.de / schwanz@fh-brandenburg.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 <tqtooltip.h>
+#include <tqnamespace.h>
+#include <tqhbuttongroup.h>
+#include <tqvbuttongroup.h>
+
+#include <tdetoolbarbutton.h>
+#include <twin.h>
+#include <tdelocale.h>
+#include <tdeglobal.h>
+#include <tdeconfig.h>
+#include <tdeaboutdata.h>
+
+#include "../../src/include/aboutwidget.h"
+#include "../../src/include/station-drag-object.h"
+#include "../../src/include/stationlist.h"
+#include "../../src/include/radiostation.h"
+
+#include "buttonflowlayout.h"
+#include "quickbar-configuration.h"
+#include "quickbar.h"
+
+///////////////////////////////////////////////////////////////////////
+//// plugin library functions
+
+PLUGIN_LIBRARY_FUNCTIONS(QuickBar, "tderadio-gui-quickbar", i18n("Radio Station Quick Selection Toolbar"));
+
+/////////////////////////////////////////////////////////////////////////////
+
+QuickBar::QuickBar(const TQString &name)
+ : TQWidget(NULL, name.ascii()),
+ WidgetPluginBase(name, i18n("Quickbar Plugin")),
+ m_layout(NULL),
+ m_buttonGroup(NULL),
+ m_showShortName(true),
+ m_ignoreNoticeActivation(false)
+{
+ autoSetCaption();
+ setAcceptDrops(true);
+}
+
+
+QuickBar::~QuickBar()
+{
+}
+
+
+bool QuickBar::connectI(Interface *i)
+{
+ bool a = IRadioClient::connectI(i);
+ bool b = IStationSelection::connectI(i);
+ bool c = PluginBase::connectI(i);
+
+ return a || b || c;
+}
+
+
+bool QuickBar::disconnectI(Interface *i)
+{
+ bool a = IRadioClient::disconnectI(i);
+ bool b = IStationSelection::disconnectI(i);
+ bool c = PluginBase::disconnectI(i);
+
+ return a || b || c;
+}
+
+
+// IStationSelection
+
+bool QuickBar::setStationSelection(const TQStringList &sl)
+{
+ if (m_stationIDs != sl) {
+ m_stationIDs = sl;
+ rebuildGUI();
+ notifyStationSelectionChanged(m_stationIDs);
+ }
+ return true;
+}
+
+// PluginBase methods
+
+
+void QuickBar::restoreState (TDEConfig *config)
+{
+ config->setGroup(TQString("quickBar-") + name());
+
+ WidgetPluginBase::restoreState(config, false);
+
+ int nStations = config->readNumEntry("nStations", 0);
+ m_stationIDs.clear();
+ for (int i = 1; i <= nStations; ++i) {
+ TQString s = config->readEntry(TQString("stationID-") + TQString().setNum(i), TQString());
+ if (s.length())
+ m_stationIDs += s;
+ }
+
+ rebuildGUI();
+ notifyStationSelectionChanged(m_stationIDs);
+}
+
+
+void QuickBar::saveState (TDEConfig *config) const
+{
+ config->setGroup(TQString("quickBar-") + name());
+
+ WidgetPluginBase::saveState(config);
+
+ config->writeEntry("nStations", m_stationIDs.size());
+ int i = 1;
+ TQStringList::const_iterator end = m_stationIDs.end();
+ for (TQStringList::const_iterator it = m_stationIDs.begin(); it != end; ++it, ++i) {
+ config->writeEntry(TQString("stationID-") + TQString().setNum(i), *it);
+ }
+}
+
+
+ConfigPageInfo QuickBar::createConfigurationPage()
+{
+ QuickbarConfiguration *conf = new QuickbarConfiguration(NULL);
+ connectI (conf);
+ return ConfigPageInfo(
+ conf,
+ i18n("Quickbar"),
+ i18n("Quickbar Configuration"),
+ "view_icon"
+ );
+}
+
+
+AboutPageInfo QuickBar::createAboutPage()
+{
+/* TDEAboutData aboutData("tderadio",
+ NULL,
+ NULL,
+ I18N_NOOP("Quickback for TDERadio"),
+ TDEAboutData::License_GPL,
+ "(c) 2002-2005 Martin Witte, Klas Kalass",
+ 0,
+ "http://sourceforge.net/projects/tderadio",
+ 0);
+ aboutData.addAuthor("Martin Witte", "", "witte@kawo1.rwth-aachen.de");
+ aboutData.addAuthor("Klas Kalass", "", "klas.kalass@gmx.de");
+
+ return AboutPageInfo(
+ new TDERadioAboutWidget(aboutData, TDERadioAboutWidget::AbtTabbed),
+ i18n("Quickbar"),
+ i18n("Quickbar Plugin"),
+ "view_icon"
+ );*/
+ return AboutPageInfo();
+}
+
+
+// IRadio methods
+
+bool QuickBar::noticePowerChanged(bool /*on*/)
+{
+ activateCurrentButton();
+ autoSetCaption();
+ return true;
+}
+
+
+bool QuickBar::noticeStationChanged (const RadioStation &rs, int /*idx*/)
+{
+ if (!m_ignoreNoticeActivation)
+ activateButton(rs);
+ autoSetCaption();
+ return true;
+}
+
+
+bool QuickBar::noticeStationsChanged(const StationList &/*sl*/)
+{
+ // FIXME
+ // we can remove no longer existent stationIDs,
+ // but it doesn't matter if we don't care.
+ rebuildGUI();
+ return true;
+}
+
+
+// button management methods
+
+void QuickBar::buttonClicked(int id)
+{
+ // ouch, but we are still using TQStringList :(
+ if (queryIsPowerOn() && id == getButtonID(queryCurrentStation())) {
+ sendPowerOff();
+ } else {
+
+ int k = 0;
+ TQStringList::iterator end = m_stationIDs.end();
+ for (TQStringList::iterator it = m_stationIDs.begin(); it != end; ++it, ++k) {
+ if (k == id) {
+ const RawStationList &sl = queryStations().all();
+ const RadioStation &rs = sl.stationWithID(*it);
+ bool old = m_ignoreNoticeActivation;
+ m_ignoreNoticeActivation = true;
+ sendActivateStation(rs);
+ m_ignoreNoticeActivation = old;
+ sendPowerOn();
+ }
+ }
+ }
+ // Problem: if we click a button twice, there will be no
+ // "station changed"-notification. Thus it would be possible to
+ // enable a button even if power is off or the radio does not
+ // accept the radiostation
+ //activateCurrentButton();
+}
+
+
+int QuickBar::getButtonID(const RadioStation &rs) const
+{
+ TQString stationID = rs.stationID();
+ int k = 0;
+ TQStringList::const_iterator end = m_stationIDs.end();
+ for (TQStringList::const_iterator it = m_stationIDs.begin(); it != end; ++it, ++k) {
+ if (*it == stationID)
+ return k;
+ }
+ return -1;
+}
+
+
+void QuickBar::activateCurrentButton()
+{
+ activateButton(queryCurrentStation());
+}
+
+
+void QuickBar::activateButton(const RadioStation &rs)
+{
+ int buttonID = getButtonID(rs);
+ bool pwr = queryIsPowerOn();
+
+ if (pwr && buttonID >= 0) {
+ m_buttonGroup->setButton(buttonID);
+ } else {
+ for (TQToolButton *b = m_buttons.first(); b; b = m_buttons.next()) {
+ b->setOn(false);
+ }
+ }
+ autoSetCaption();
+}
+
+
+
+// KDE/TQt gui
+
+
+void QuickBar::rebuildGUI()
+{
+ if (m_layout) delete m_layout;
+ if (m_buttonGroup) delete m_buttonGroup;
+
+ for (TQPtrListIterator<TQToolButton> it(m_buttons); it.current(); ++it)
+ delete it.current();
+ m_buttons.clear();
+
+ m_layout = new ButtonFlowLayout(this);
+ m_layout->setMargin(1);
+ m_layout->setSpacing(2);
+
+ m_buttonGroup = new TQButtonGroup(this);
+ TQObject::connect (m_buttonGroup, TQT_SIGNAL(clicked(int)), this, TQT_SLOT(buttonClicked(int)));
+ // we use buttonGroup to enable automatic toggle/untoggle
+ m_buttonGroup->setExclusive(true);
+ m_buttonGroup->setFrameStyle(TQFrame::NoFrame);
+ m_buttonGroup->show();
+
+ int buttonID = 0;
+ const RawStationList &stations = queryStations().all();
+
+ TQStringList::iterator end = m_stationIDs.end();
+ for (TQStringList::iterator it = m_stationIDs.begin(); it != end; ++it, ++buttonID) {
+
+ const RadioStation &rs = stations.stationWithID(*it);
+ if (! rs.isValid()) continue;
+
+ TQToolButton *b = new TQToolButton(this);
+ m_buttons.append(b);
+ b->setToggleButton(true);
+ if (rs.iconName().length())
+ b->setIconSet(TQPixmap(rs.iconName()));
+ else
+ b->setText(m_showShortName ? rs.shortName() : rs.name());
+
+ b->setSizePolicy(TQSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Preferred));
+
+ TQToolTip::add(b, rs.longName());
+ if (isVisible()) b->show();
+
+
+ m_buttonGroup->insert(b, buttonID);
+ m_layout->add(b);
+ }
+
+ // activate correct button
+ activateCurrentButton();
+
+ // calculate geometry
+ if (m_layout) {
+ TQRect r = geometry();
+ int h = m_layout->heightForWidth( r.width());
+
+ if (h > r.height())
+ setGeometry(r.x(), r.y(), r.width(), h);
+ }
+}
+
+
+
+
+void QuickBar::show()
+{
+// KWin::setType(winId(), NET::Toolbar);
+ WidgetPluginBase::pShow();
+ TQWidget::show();
+}
+
+
+void QuickBar::showOnOrgDesktop()
+{
+ WidgetPluginBase::pShowOnOrgDesktop();
+ //TQWidget::show();
+}
+
+
+void QuickBar::hide()
+{
+ WidgetPluginBase::pHide();
+ TQWidget::hide();
+}
+
+void QuickBar::showEvent(TQShowEvent *e)
+{
+ TQWidget::showEvent(e);
+ WidgetPluginBase::pShowEvent(e);
+}
+
+void QuickBar::hideEvent(TQHideEvent *e)
+{
+ TQWidget::hideEvent(e);
+ WidgetPluginBase::pHideEvent(e);
+}
+
+
+void QuickBar::setGeometry (int x, int y, int w, int h)
+{
+ if (m_layout) {
+ TQSize marginSize(m_layout->margin()*2, m_layout->margin()*2);
+ setMinimumSize(m_layout->minimumSize(TQSize(w, h) - marginSize) + marginSize);
+ }
+ TQWidget::setGeometry (x, y, w, h);
+}
+
+
+void QuickBar::setGeometry (const TQRect &r)
+{
+ setGeometry (r.x(), r.y(), r.width(), r.height());
+}
+
+
+void QuickBar::resizeEvent (TQResizeEvent *e)
+{
+ // minimumSize might change because of the flow layout
+ if (m_layout) {
+ TQSize marginSize(m_layout->margin()*2, m_layout->margin()*2);
+ setMinimumSize(m_layout->minimumSize(e->size() - marginSize) + marginSize);
+ }
+
+ TQWidget::resizeEvent (e);
+}
+
+
+void QuickBar::autoSetCaption()
+{
+ const RadioStation &rs = queryCurrentStation();
+ setCaption((queryIsPowerOn() && rs.isValid()) ? rs.longName() : TQString("TDERadio"));
+}
+
+void QuickBar::dragEnterEvent(TQDragEnterEvent* event)
+{
+ bool a = StationDragObject::canDecode(event);
+ if (a)
+ IErrorLogClient::staticLogDebug(i18n("contentsDragEnterEvent accepted"));
+ else
+ IErrorLogClient::staticLogDebug(i18n("contentsDragEnterEvent rejected"));
+ event->accept(a);
+}
+
+void QuickBar::dropEvent(TQDropEvent* event)
+{
+ TQStringList list;
+
+ if ( StationDragObject::decode(event, list) ) {
+ TQStringList l = getStationSelection();
+ for (TQValueListConstIterator<TQString> it = list.begin(); it != list.end(); ++it)
+ if (!l.contains(*it))
+ l.append(*it);
+ setStationSelection(l);
+ }
+}
+
+
+#include "quickbar.moc"
diff --git a/plugins/gui-quickbar/quickbar.h b/plugins/gui-quickbar/quickbar.h
new file mode 100644
index 0000000..2ec4f6b
--- /dev/null
+++ b/plugins/gui-quickbar/quickbar.h
@@ -0,0 +1,139 @@
+/***************************************************************************
+ quickbar.h - description
+ -------------------
+ begin : Mon Feb 11 2002
+ copyright : (C) 2002 by Martin Witte / Klas Kalass
+ 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_QUICKBAR_H
+#define KRADIO_QUICKBAR_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tqwidget.h>
+
+#include "../../src/include/radio_interfaces.h"
+#include "../../src/include/widgetplugins.h"
+#include "../../src/include/stationselection_interfaces.h"
+
+class ButtonFlowLayout;
+class TQButtonGroup;
+class TDEConfig;
+class TQToolButton;
+
+/**
+ *@author Martin Witte / Klas Kalass
+ */
+
+class QuickBar : public TQWidget,
+ public WidgetPluginBase,
+ public IRadioClient,
+ public IStationSelection
+{
+Q_OBJECT
+
+public:
+ QuickBar(const TQString &name = TQString());
+ ~QuickBar();
+
+ virtual TQString pluginClassName() const { return "QuickBar"; }
+
+ const TQString &name() const { return PluginBase::name(); }
+ TQString &name() { return PluginBase::name(); }
+
+ virtual bool connectI(Interface *i);
+ virtual bool disconnectI(Interface *i);
+
+ // IStationSelection
+
+RECEIVERS:
+ bool setStationSelection(const TQStringList &sl);
+
+ANSWERS:
+ const TQStringList & getStationSelection () const { return m_stationIDs; }
+
+
+ // PluginBase
+
+public:
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+ virtual ConfigPageInfo createConfigurationPage();
+ virtual AboutPageInfo createAboutPage();
+
+ // IRadioClient
+
+RECEIVERS:
+ bool noticePowerChanged(bool on);
+ bool noticeStationChanged (const RadioStation &, int idx);
+ bool noticeStationsChanged(const StationList &sl);
+ bool noticePresetFileChanged(const TQString &/*f*/) { return false; }
+
+ bool noticeCurrentSoundStreamIDChanged(SoundStreamID /*id*/) { return false; }
+
+ // button/station Management
+
+
+protected slots:
+
+ void buttonClicked(int id);
+
+protected:
+
+ int getButtonID(const RadioStation &rs) const;
+ void activateCurrentButton();
+ void activateButton(const RadioStation &);
+
+ void autoSetCaption();
+
+
+ void dragEnterEvent(TQDragEnterEvent* event);
+ void dropEvent(TQDropEvent* event);
+
+ // KDE/QT
+
+public slots:
+
+ void toggleShown() { WidgetPluginBase::pToggleShown(); }
+ void show();
+ void hide();
+ void showOnOrgDesktop();
+ void setGeometry (const TQRect &r);
+ void setGeometry (int x, int y, int w, int h);
+
+protected:
+ void rebuildGUI();
+ void showEvent(TQShowEvent *);
+ void hideEvent(TQHideEvent *);
+ void resizeEvent(TQResizeEvent *);
+
+ const TQWidget *getWidget() const { return this; }
+ TQWidget *getWidget() { return this; }
+
+protected :
+
+ ButtonFlowLayout *m_layout;
+ TQButtonGroup *m_buttonGroup;
+
+ TQPtrList<TQToolButton> m_buttons;
+
+ // config
+ bool m_showShortName;
+ TQStringList m_stationIDs;
+
+ bool m_ignoreNoticeActivation;
+};
+#endif
diff --git a/plugins/gui-standard-display/CMakeL10n.txt b/plugins/gui-standard-display/CMakeL10n.txt
new file mode 100644
index 0000000..803a5d5
--- /dev/null
+++ b/plugins/gui-standard-display/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-gui-standard-display"
+ DESTINATION "po"
+)
diff --git a/plugins/gui-standard-display/Makefile.am b/plugins/gui-standard-display/Makefile.am
new file mode 100644
index 0000000..c9b719b
--- /dev/null
+++ b/plugins/gui-standard-display/Makefile.am
@@ -0,0 +1,22 @@
+SUBDIRS = po .
+
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = libstandard-display.la
+libstandard_display_la_SOURCES = displaycfg.cpp displaycfg_interfaces.cpp \
+ radioview-configuration.cpp radioview.cpp \
+ radioview_element.cpp \
+ radioview_frequencyradio.cpp \
+ radioview_frequencyseeker.cpp \
+ radioview_volume.cpp
+libstandard_display_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+
+noinst_HEADERS = displaycfg.h displaycfg_interfaces.h radioview-configuration.h radioview_element.h radioview_frequencyradio.h radioview_frequencyseeker.h radioview.h radioview_volume.h
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-gui-standard-display.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-gui-standard-display.pot
diff --git a/plugins/gui-standard-display/displaycfg.cpp b/plugins/gui-standard-display/displaycfg.cpp
new file mode 100644
index 0000000..e2a37ac
--- /dev/null
+++ b/plugins/gui-standard-display/displaycfg.cpp
@@ -0,0 +1,145 @@
+/***************************************************************************
+ displaycfg.cpp - description
+ -------------------
+ begin : Fr Aug 15 2003
+ copyright : (C) 2003 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 "displaycfg.h"
+#include <kcolorbutton.h>
+#include <kcolordialog.h>
+#include <tdefontdialog.h>
+
+#include <tqlayout.h>
+#include <tdelocale.h>
+#include <tqlabel.h>
+#include <tqbuttongroup.h>
+
+DisplayConfiguration::DisplayConfiguration(TQWidget *parent)
+ : TQWidget (parent),
+ m_dirty(true),
+ m_ignore_gui_updates(false)
+{
+ TQGroupBox *bg = new TQGroupBox(i18n("Display Colors"), this);
+ bg->setColumnLayout(0, Qt::Vertical );
+ bg->layout()->setSpacing( 8 );
+ bg->layout()->setMargin( 12 );
+ TQGridLayout *gl = new TQGridLayout (bg->layout());
+
+ m_btnActive = new KColorButton(queryDisplayActiveColor(), bg);
+ m_btnInactive = new KColorButton(queryDisplayInactiveColor(), bg);
+ m_btnBkgnd = new KColorButton(queryDisplayBkgndColor(), bg);
+
+ connect(m_btnActive, TQT_SIGNAL(changed(const TQColor &)), this, TQT_SLOT(slotSetDirty()));
+ connect(m_btnInactive, TQT_SIGNAL(changed(const TQColor &)), this, TQT_SLOT(slotSetDirty()));
+ connect(m_btnBkgnd, TQT_SIGNAL(changed(const TQColor &)), this, TQT_SLOT(slotSetDirty()));
+
+ TQLabel *l1 = new TQLabel(i18n("Active Text"), bg);
+ TQLabel *l2 = new TQLabel(i18n("Inactive Text"), bg);
+ TQLabel *l3 = new TQLabel(i18n("Background Color"), bg);
+
+ l1->setAlignment(TQLabel::AlignCenter);
+ l2->setAlignment(TQLabel::AlignCenter);
+ l3->setAlignment(TQLabel::AlignCenter);
+
+ l1->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed));
+ l2->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed));
+ l3->setSizePolicy(TQSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed));
+ m_btnActive ->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding));
+ m_btnInactive->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding));
+ m_btnBkgnd ->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding));
+
+ m_btnActive ->setMinimumSize(TQSize(40, 40));
+ m_btnInactive->setMinimumSize(TQSize(40, 40));
+ m_btnBkgnd ->setMinimumSize(TQSize(40, 40));
+
+ gl->addWidget (l1, 0, 0, TQt::AlignCenter);
+ gl->addWidget (l2, 0, 1, TQt::AlignCenter);
+ gl->addWidget (l3, 0, 2, TQt::AlignCenter);
+ gl->addWidget (m_btnActive, 1, 0);
+ gl->addWidget (m_btnInactive, 1, 1);
+ gl->addWidget (m_btnBkgnd, 1, 2);
+
+ m_fontChooser = new TDEFontChooser(this, NULL, false, TQStringList(), true, 4);
+ m_fontChooser->setFont(queryDisplayFont());
+ m_fontChooser->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding));
+
+ TQVBoxLayout *l = new TQVBoxLayout(this, 10);
+ l->addWidget(bg);
+ l->addWidget(m_fontChooser);
+
+ connect(m_btnActive, TQT_SIGNAL(changed(const TQColor &)), this, TQT_SLOT(slotSetDirty()));
+ connect(m_btnInactive, TQT_SIGNAL(changed(const TQColor &)), this, TQT_SLOT(slotSetDirty()));
+ connect(m_btnBkgnd, TQT_SIGNAL(changed(const TQColor &)), this, TQT_SLOT(slotSetDirty()));
+ connect(m_fontChooser, TQT_SIGNAL(fontSelected(const TQFont &)), this, TQT_SLOT(slotSetDirty()));
+
+}
+
+
+DisplayConfiguration::~DisplayConfiguration()
+{
+}
+
+
+bool DisplayConfiguration::noticeDisplayColorsChanged(const TQColor &activeColor, const TQColor &inactiveColor, const TQColor &bkgnd)
+{
+ m_ignore_gui_updates = true;
+ m_btnActive->setColor(activeColor);
+ m_btnInactive->setColor(inactiveColor);
+ m_btnBkgnd->setColor(bkgnd);
+ m_ignore_gui_updates = false;
+ return true;
+}
+
+
+bool DisplayConfiguration::noticeDisplayFontChanged(const TQFont &f)
+{
+ m_ignore_gui_updates = true;
+ m_fontChooser->setFont(f);
+ m_ignore_gui_updates = false;
+ return true;
+}
+
+
+void DisplayConfiguration::slotOK()
+{
+ if (m_dirty) {
+ sendDisplayColors(m_btnActive->color(), m_btnInactive->color(), m_btnBkgnd->color());
+ sendDisplayFont(m_fontChooser->font());
+ m_dirty = false;
+ }
+}
+
+void DisplayConfiguration::slotCancel()
+{
+ if (m_dirty) {
+ m_ignore_gui_updates = true;
+ m_btnActive ->setColor(queryDisplayActiveColor());
+ m_btnInactive->setColor(queryDisplayInactiveColor());
+ m_btnBkgnd ->setColor(queryDisplayBkgndColor());
+ m_fontChooser->setFont(queryDisplayFont());
+ m_dirty = false;
+ m_ignore_gui_updates = false;
+ }
+}
+
+void DisplayConfiguration::slotSetDirty()
+{
+ if (!m_dirty && !m_ignore_gui_updates) {
+ m_dirty = true;
+ emit sigDirty();
+ }
+}
+
+
+#include "displaycfg.moc"
diff --git a/plugins/gui-standard-display/displaycfg.h b/plugins/gui-standard-display/displaycfg.h
new file mode 100644
index 0000000..aeb3e97
--- /dev/null
+++ b/plugins/gui-standard-display/displaycfg.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ displaycfg.h - description
+ -------------------
+ begin : Fr Aug 15 2003
+ copyright : (C) 2003 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_DISPLAYCFG_H
+#define KRADIO_DISPLAYCFG_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "displaycfg_interfaces.h"
+#include <tqwidget.h>
+
+class KColorButton;
+class TDEFontChooser;
+
+class DisplayConfiguration : public TQWidget,
+ public IDisplayCfgClient
+{
+Q_OBJECT
+
+public:
+ DisplayConfiguration(TQWidget *parent);
+ ~DisplayConfiguration();
+
+// Interface
+
+ bool connectI (Interface *i) { return IDisplayCfgClient::connectI(i); }
+ bool disconnectI (Interface *i) { return IDisplayCfgClient::disconnectI(i); }
+
+// IDisplayCfgClient
+
+RECEIVERS:
+ bool noticeDisplayColorsChanged(const TQColor &activeColor, const TQColor &inactiveColor, const TQColor &bkgnd);
+ bool noticeDisplayFontChanged(const TQFont &f);
+
+
+public slots:
+
+ void slotOK();
+ void slotCancel();
+ void slotSetDirty();
+
+signals:
+
+ void sigDirty();
+
+protected:
+ KColorButton *m_btnActive;
+ KColorButton *m_btnInactive;
+ KColorButton *m_btnBkgnd;
+ TDEFontChooser *m_fontChooser;
+
+ bool m_dirty;
+ bool m_ignore_gui_updates;
+};
+
+
+#endif
diff --git a/plugins/gui-standard-display/displaycfg_interfaces.cpp b/plugins/gui-standard-display/displaycfg_interfaces.cpp
new file mode 100644
index 0000000..67e5aba
--- /dev/null
+++ b/plugins/gui-standard-display/displaycfg_interfaces.cpp
@@ -0,0 +1,69 @@
+/***************************************************************************
+ displaycfg_interfaces.cpp - description
+ -------------------
+ begin : Fr Aug 15 2003
+ copyright : (C) 2003 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 "displaycfg_interfaces.h"
+
+// IDisplayCfg
+
+IF_IMPL_SENDER ( IDisplayCfg::notifyDisplayColorsChanged(const TQColor &a, const TQColor &b, const TQColor &c),
+ noticeDisplayColorsChanged(a,b, c) )
+
+IF_IMPL_SENDER ( IDisplayCfg::notifyDisplayFontChanged(const TQFont &f),
+ noticeDisplayFontChanged(f) )
+
+// IDisplayCfgClient
+
+IF_IMPL_SENDER ( IDisplayCfgClient::sendDisplayColors(const TQColor &a, const TQColor &b, const TQColor &c),
+ setDisplayColors(a,b, c) )
+
+IF_IMPL_SENDER ( IDisplayCfgClient::sendDisplayFont(const TQFont &f),
+ setDisplayFont(f) )
+
+const TQColor default_display_active_color = TQColor(20, 244, 20);
+IF_IMPL_QUERY ( const TQColor &IDisplayCfgClient::queryDisplayActiveColor(),
+ getDisplayActiveColor(),
+ default_display_active_color )
+
+const TQColor default_display_inactive_color = TQColor(10, 117, 10).light(75);
+IF_IMPL_QUERY ( const TQColor &IDisplayCfgClient::queryDisplayInactiveColor(),
+ getDisplayInactiveColor(),
+ default_display_inactive_color )
+
+const TQColor default_display_bkgnd_color = TQColor(10, 117, 10);
+IF_IMPL_QUERY ( const TQColor &IDisplayCfgClient::queryDisplayBkgndColor(),
+ getDisplayBkgndColor(),
+ default_display_bkgnd_color )
+
+const TQFont default_display_font = TQFont("Helvetica");
+IF_IMPL_QUERY ( const TQFont &IDisplayCfgClient::queryDisplayFont(),
+ getDisplayFont(),
+ default_display_font )
+
+
+void IDisplayCfgClient::noticeConnectedI (cmplInterface *, bool /*pointer_valid*/)
+{
+ noticeDisplayColorsChanged(queryDisplayActiveColor(), queryDisplayInactiveColor(), queryDisplayBkgndColor());
+ noticeDisplayFontChanged(queryDisplayFont());
+}
+
+
+void IDisplayCfgClient::noticeDisconnectedI (cmplInterface *, bool /*pointer_valid*/)
+{
+ noticeDisplayColorsChanged(queryDisplayActiveColor(), queryDisplayInactiveColor(), queryDisplayBkgndColor());
+ noticeDisplayFontChanged(queryDisplayFont());
+}
+
diff --git a/plugins/gui-standard-display/displaycfg_interfaces.h b/plugins/gui-standard-display/displaycfg_interfaces.h
new file mode 100644
index 0000000..d458dc9
--- /dev/null
+++ b/plugins/gui-standard-display/displaycfg_interfaces.h
@@ -0,0 +1,82 @@
+/***************************************************************************
+ displaycfg_interfaces.h - description
+ -------------------
+ begin : Fr Aug 15 2003
+ copyright : (C) 2003 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_DISPLAYCFG_INTERFACES_H
+#define KRADIO_DISPLAYCFG_INTERFACES_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/interfaces.h"
+
+#include <tqfont.h>
+#include <tqcolor.h>
+
+///////////////////////////////////////////////////////////////////////
+
+
+INTERFACE(IDisplayCfg, IDisplayCfgClient)
+{
+public :
+ IF_CON_DESTRUCTOR(IDisplayCfg, -1)
+
+RECEIVERS:
+ IF_RECEIVER( setDisplayColors(const TQColor &activeColor, const TQColor &inactiveColor, const TQColor &bkgnd) )
+ IF_RECEIVER( setDisplayFont (const TQFont &f) )
+
+SENDERS:
+ IF_SENDER ( notifyDisplayColorsChanged(const TQColor &activeColor, const TQColor &inactiveColor, const TQColor &bkgnd) )
+ IF_SENDER ( notifyDisplayFontChanged(const TQFont &f) )
+
+ANSWERS:
+ IF_ANSWER ( const TQColor &getDisplayActiveColor() const )
+ IF_ANSWER ( const TQColor &getDisplayInactiveColor() const )
+ IF_ANSWER ( const TQColor &getDisplayBkgndColor() const )
+ IF_ANSWER ( const TQFont &getDisplayFont() const )
+
+};
+
+
+INTERFACE(IDisplayCfgClient, IDisplayCfg)
+{
+friend class IDisplayCfg;
+
+public :
+ IF_CON_DESTRUCTOR(IDisplayCfgClient, 1)
+
+SENDERS:
+ IF_SENDER ( sendDisplayColors(const TQColor &activeColor, const TQColor &inactiveColor, const TQColor &bkgnd) )
+ IF_SENDER ( sendDisplayFont (const TQFont &f) )
+
+RECEIVERS:
+ IF_RECEIVER( noticeDisplayColorsChanged(const TQColor &activeColor, const TQColor &inactiveColor, const TQColor &bkgnd) )
+ IF_RECEIVER( noticeDisplayFontChanged(const TQFont &f) )
+
+QUERIES:
+ IF_QUERY ( const TQColor &queryDisplayActiveColor() )
+ IF_QUERY ( const TQColor &queryDisplayInactiveColor() )
+ IF_QUERY ( const TQColor &queryDisplayBkgndColor() )
+ IF_QUERY ( const TQFont &queryDisplayFont() )
+
+RECEIVERS:
+ virtual void noticeConnectedI (cmplInterface *, bool pointer_valid);
+ virtual void noticeDisconnectedI (cmplInterface *, bool pointer_valid);
+};
+
+
+#endif
diff --git a/plugins/gui-standard-display/po/Makefile.am b/plugins/gui-standard-display/po/Makefile.am
new file mode 100644
index 0000000..a9b5c92
--- /dev/null
+++ b/plugins/gui-standard-display/po/Makefile.am
@@ -0,0 +1,2 @@
+PACKAGE = tderadio-gui-standard-display
+POFILES = AUTO
diff --git a/plugins/gui-standard-display/po/de.po b/plugins/gui-standard-display/po/de.po
new file mode 100644
index 0000000..127dbe9
--- /dev/null
+++ b/plugins/gui-standard-display/po/de.po
@@ -0,0 +1,210 @@
+# translation of tderadio-gui-standard-display.po to
+# This file is put in the public domain.
+#
+# Ernst Martin Witte <emw@nocabal.de>, 2006.
+msgid ""
+msgstr ""
+"Project-Id-Version: tderadio-gui-standard-display\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-05-11 04:30+0200\n"
+"PO-Revision-Date: 2019-11-27 16:56+0000\n"
+"Last-Translator: Chris <xchrisx@uber.space>\n"
+"Language-Team: German <https://mirror.git.trinitydesktop.org/weblate/"
+"projects/applications/tderadio-gui-standard-display/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"
+
+#: displaycfg.cpp:33
+msgid "Display Colors"
+msgstr "Farben für die Radioanzeige"
+
+#: displaycfg.cpp:47
+msgid "Active Text"
+msgstr "Aktiver Text"
+
+#: displaycfg.cpp:48
+msgid "Inactive Text"
+msgstr "Inaktiver Text"
+
+#: displaycfg.cpp:49
+msgid "Background Color"
+msgstr "Hintergrundfarbe"
+
+#: radioview.cpp:55
+msgid "Standard Display for TDERadio"
+msgstr "Standardanzeige für TDERadio"
+
+#: radioview.cpp:72
+msgid "Radio Display"
+msgstr "Radio-Anzeige"
+
+#: radioview.cpp:127
+msgid "Pause TDERadio"
+msgstr "TDERadio pausieren"
+
+#: radioview.cpp:133
+msgid "Start Recording"
+msgstr "Aufnahme starten"
+
+#: radioview.cpp:141
+msgid "5 min"
+msgstr "5 min"
+
+#: radioview.cpp:142
+msgid "10 min"
+msgstr "10 min"
+
+#: radioview.cpp:143
+msgid "15 min"
+msgstr "15 min"
+
+#: radioview.cpp:144
+msgid "30 min"
+msgstr "30 min"
+
+#: radioview.cpp:145
+msgid "60 min"
+msgstr "60 min"
+
+#: radioview.cpp:189
+msgid "Configure TDERadio"
+msgstr "TDERadio Einrichten"
+
+#: radioview.cpp:190
+msgid "Power On/Off"
+msgstr "Ein/Ausschalten"
+
+#: radioview.cpp:191
+msgid "Quit TDERadio Application"
+msgstr "TDERadio beenden"
+
+#: radioview.cpp:192
+msgid "Start/Stop Recording"
+msgstr "Aufnahme starten/beenden"
+
+#: radioview.cpp:193
+msgid "Start/Stop Sleep Countdown"
+msgstr "Schlummermodus ein/ausschalten"
+
+#: radioview.cpp:194
+msgid "Show/Hide Plugins"
+msgstr "Plugins anzeigen/verstecken"
+
+#: radioview.cpp:195
+msgid "Select a Radio Station"
+msgstr "Sender auswählen"
+
+#: radioview.cpp:332
+msgid "no preset defined"
+msgstr "kein voreingestellter Sender gefunden"
+
+#: radioview.cpp:442 radioview.cpp:480
+#, c-format
+msgid "Stop Recording of %1"
+msgstr "Aufnahme von %1 beenden"
+
+#: radioview.cpp:553
+msgid "Display"
+msgstr "Anzeige"
+
+#: radioview.cpp:554
+msgid "Display Configuration"
+msgstr "Einrichtung der Radio-Anzeige"
+
+#: radioview.cpp:590
+msgid "set Toolbar-Flag for Display"
+msgstr "Werkzeugleisten-Flag für das Displayfenster"
+
+#: radioview.cpp:593
+msgid "Common"
+msgstr "Allgemein"
+
+#: radioview_frequencyradio.cpp:99 radioview_frequencyradio.cpp:100
+msgid "Frequency Display"
+msgstr "Frequenzanzeige"
+
+#: radioview_frequencyradio.cpp:388 radioview_frequencyradio.cpp:389
+msgid "AM"
+msgstr "MW"
+
+#: radioview_frequencyradio.cpp:394 radioview_frequencyradio.cpp:395
+msgid "FM"
+msgstr "UKW"
+
+#: radioview_frequencyradio.cpp:406
+msgid "%1 kHz"
+msgstr "%1 kHz"
+
+#: radioview_frequencyradio.cpp:408
+msgid "%1 MHz"
+msgstr "%1 MHz"
+
+#: radioview_frequencyseeker.cpp:76
+msgid "Search for previous Radio Station"
+msgstr "Suche nach vorherigem Sender"
+
+#: radioview_frequencyseeker.cpp:77
+msgid "Search for next Radio Station"
+msgstr "Suche nach nächstem Sender"
+
+#: radioview_frequencyseeker.cpp:78
+msgid "Decrement Frequency"
+msgstr "Frequenz erniedrigen"
+
+#: radioview_frequencyseeker.cpp:79
+msgid "Increment Frequency"
+msgstr "Frequenz erhöhen"
+
+#: radioview_frequencyseeker.cpp:80
+msgid "Change Frequency"
+msgstr "Frequenz verändern"
+
+#: radioview_volume.cpp:56
+msgid "Change Volume"
+msgstr "Läutstärke verändern"
+
+#: radioview_seekinterface.ui:17
+#, no-c-format
+msgid "RadioView_SeekInterface"
+msgstr "RadioView_SeekInterface"
+
+#: radioview_seekinterface.ui:45
+#, no-c-format
+msgid "search previous station"
+msgstr "Suche vorherigen Sender"
+
+#: radioview_seekinterface.ui:73
+#, no-c-format
+msgid "decrease freq. by 0.05 MHz"
+msgstr "Frequenz um 0.05 MHz verringern"
+
+#: radioview_seekinterface.ui:108
+#, no-c-format
+msgid "Frequency control"
+msgstr "Frequenz verändern"
+
+#: radioview_seekinterface.ui:129
+#, no-c-format
+msgid "increase freq. by 0.05 MHz"
+msgstr "Frequenz um 0.05 MHz erhöhen"
+
+#: radioview_seekinterface.ui:146
+#, no-c-format
+msgid "search next station"
+msgstr "Suche nächsten Sender"
diff --git a/plugins/gui-standard-display/po/nl.po b/plugins/gui-standard-display/po/nl.po
new file mode 100644
index 0000000..5e14e1c
--- /dev/null
+++ b/plugins/gui-standard-display/po/nl.po
@@ -0,0 +1,208 @@
+# SOME DESCRIPTIVE TITLE.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2020-05-11 04:30+0200\n"
+"PO-Revision-Date: 2019-12-01 23:42+0000\n"
+"Last-Translator: Heimen Stoffels <vistausss@outlook.com>\n"
+"Language-Team: Dutch <https://mirror.git.trinitydesktop.org/weblate/projects/"
+"applications/tderadio-gui-standard-display/nl/>\n"
+"Language: nl\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 "Heimen Stoffels"
+
+#. 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 "vistausss@outlook.com"
+
+#: displaycfg.cpp:33
+msgid "Display Colors"
+msgstr "Kleurenschema"
+
+#: displaycfg.cpp:47
+msgid "Active Text"
+msgstr "Actieve tekst"
+
+#: displaycfg.cpp:48
+msgid "Inactive Text"
+msgstr "Inactieve tekst"
+
+#: displaycfg.cpp:49
+msgid "Background Color"
+msgstr "Achtergrondkleur"
+
+#: radioview.cpp:55
+msgid "Standard Display for TDERadio"
+msgstr "Standaardweergave van TDERadio"
+
+#: radioview.cpp:72
+msgid "Radio Display"
+msgstr "Radioweergave"
+
+#: radioview.cpp:127
+msgid "Pause TDERadio"
+msgstr "TDERadio pauzeren"
+
+#: radioview.cpp:133
+msgid "Start Recording"
+msgstr "Opname starten"
+
+#: radioview.cpp:141
+msgid "5 min"
+msgstr "5 min"
+
+#: radioview.cpp:142
+msgid "10 min"
+msgstr "10 min"
+
+#: radioview.cpp:143
+msgid "15 min"
+msgstr "15 min"
+
+#: radioview.cpp:144
+msgid "30 min"
+msgstr "30 min"
+
+#: radioview.cpp:145
+msgid "60 min"
+msgstr "60 min"
+
+#: radioview.cpp:189
+msgid "Configure TDERadio"
+msgstr "TDERadio instellen"
+
+#: radioview.cpp:190
+msgid "Power On/Off"
+msgstr "Aan-/Uitzetten"
+
+#: radioview.cpp:191
+msgid "Quit TDERadio Application"
+msgstr "TDERadio afsluiten"
+
+#: radioview.cpp:192
+msgid "Start/Stop Recording"
+msgstr "Opname starten/stoppen"
+
+#: radioview.cpp:193
+msgid "Start/Stop Sleep Countdown"
+msgstr "Slaaptimer starten/stoppen"
+
+#: radioview.cpp:194
+msgid "Show/Hide Plugins"
+msgstr "Plug-ins tonen/verbergen"
+
+#: radioview.cpp:195
+msgid "Select a Radio Station"
+msgstr "Kies een radiostation"
+
+#: radioview.cpp:332
+msgid "no preset defined"
+msgstr "geen voorinstelling opgegeven"
+
+#: radioview.cpp:442 radioview.cpp:480
+#, c-format
+msgid "Stop Recording of %1"
+msgstr "Stoppen met opnemen van %1"
+
+#: radioview.cpp:553
+msgid "Display"
+msgstr "Weergave"
+
+#: radioview.cpp:554
+msgid "Display Configuration"
+msgstr "Weergave-instellingen"
+
+#: radioview.cpp:590
+msgid "set Toolbar-Flag for Display"
+msgstr "Werkbalk-vlag instellen voor weergave"
+
+#: radioview.cpp:593
+msgid "Common"
+msgstr "Algemeen"
+
+#: radioview_frequencyradio.cpp:99 radioview_frequencyradio.cpp:100
+msgid "Frequency Display"
+msgstr "Frequentie tonen"
+
+#: radioview_frequencyradio.cpp:388 radioview_frequencyradio.cpp:389
+msgid "AM"
+msgstr "AM"
+
+#: radioview_frequencyradio.cpp:394 radioview_frequencyradio.cpp:395
+msgid "FM"
+msgstr "FM"
+
+#: radioview_frequencyradio.cpp:406
+msgid "%1 kHz"
+msgstr "%1 kHz"
+
+#: radioview_frequencyradio.cpp:408
+msgid "%1 MHz"
+msgstr "%1 MHz"
+
+#: radioview_frequencyseeker.cpp:76
+msgid "Search for previous Radio Station"
+msgstr "Zoeken naar vorig radiostation"
+
+#: radioview_frequencyseeker.cpp:77
+msgid "Search for next Radio Station"
+msgstr "Zoeken naar volgend radiostation"
+
+#: radioview_frequencyseeker.cpp:78
+msgid "Decrement Frequency"
+msgstr "Frequentie verlagen"
+
+#: radioview_frequencyseeker.cpp:79
+msgid "Increment Frequency"
+msgstr "Frequentie verhogen"
+
+#: radioview_frequencyseeker.cpp:80
+msgid "Change Frequency"
+msgstr "Frequentie aanpassen"
+
+#: radioview_volume.cpp:56
+msgid "Change Volume"
+msgstr "Volume aanpassen"
+
+#: radioview_seekinterface.ui:17
+#, no-c-format
+msgid "RadioView_SeekInterface"
+msgstr "RadioView_SeekInterface"
+
+#: radioview_seekinterface.ui:45
+#, no-c-format
+msgid "search previous station"
+msgstr "vorig radiostation zoeken"
+
+#: radioview_seekinterface.ui:73
+#, no-c-format
+msgid "decrease freq. by 0.05 MHz"
+msgstr "freq. verlagen met 0.05 MHz"
+
+#: radioview_seekinterface.ui:108
+#, no-c-format
+msgid "Frequency control"
+msgstr "Frequentiebeheer"
+
+#: radioview_seekinterface.ui:129
+#, no-c-format
+msgid "increase freq. by 0.05 MHz"
+msgstr "freq. verhogen met 0.05 MHz"
+
+#: radioview_seekinterface.ui:146
+#, no-c-format
+msgid "search next station"
+msgstr "volgend radiostation zoeken"
diff --git a/plugins/gui-standard-display/po/ru.po b/plugins/gui-standard-display/po/ru.po
new file mode 100644
index 0000000..3263ebe
--- /dev/null
+++ b/plugins/gui-standard-display/po/ru.po
@@ -0,0 +1,209 @@
+# translation of ru.po to
+# translation of tderadio-gui-standard-display.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 13:06+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"
+
+#: displaycfg.cpp:33
+msgid "Display Colors"
+msgstr "Цвета"
+
+#: displaycfg.cpp:47
+msgid "Active Text"
+msgstr "Цвет активного текста"
+
+#: displaycfg.cpp:48
+msgid "Inactive Text"
+msgstr "Цвет инертного текста"
+
+#: displaycfg.cpp:49
+msgid "Background Color"
+msgstr "Цвет фона"
+
+#: radioview.cpp:55
+msgid "Standard Display for TDERadio"
+msgstr "Главное окно TDERadio"
+
+#: radioview.cpp:72
+msgid "Radio Display"
+msgstr "Главное окно"
+
+#: radioview.cpp:127
+msgid "Pause TDERadio"
+msgstr "Приостановить"
+
+#: radioview.cpp:133
+msgid "Start Recording"
+msgstr "Начать запись"
+
+#: radioview.cpp:141
+msgid "5 min"
+msgstr "5 минут"
+
+#: radioview.cpp:142
+msgid "10 min"
+msgstr "10 минут"
+
+#: radioview.cpp:143
+msgid "15 min"
+msgstr "четверть часа"
+
+#: radioview.cpp:144
+msgid "30 min"
+msgstr "полчаса"
+
+#: radioview.cpp:145
+msgid "60 min"
+msgstr "час"
+
+#: radioview.cpp:189
+msgid "Configure TDERadio"
+msgstr "Настроить TDERadio"
+
+#: radioview.cpp:190
+msgid "Power On/Off"
+msgstr "Включить/выключить"
+
+#: radioview.cpp:191
+msgid "Quit TDERadio Application"
+msgstr "Закрыть TDERadio"
+
+#: radioview.cpp:192
+msgid "Start/Stop Recording"
+msgstr "Начать/завершить запись"
+
+#: radioview.cpp:193
+msgid "Start/Stop Sleep Countdown"
+msgstr "Включить/выключить таймер отключения"
+
+#: radioview.cpp:194
+msgid "Show/Hide Plugins"
+msgstr "Показать/скрыть"
+
+#: radioview.cpp:195
+msgid "Select a Radio Station"
+msgstr "Выбор радиостанции из списка"
+
+#: radioview.cpp:332
+msgid "no preset defined"
+msgstr "Станция не определена"
+
+#: radioview.cpp:442 radioview.cpp:480
+#, c-format
+msgid "Stop Recording of %1"
+msgstr "Остановить запись %1"
+
+#: radioview.cpp:553
+msgid "Display"
+msgstr "Вид"
+
+#: radioview.cpp:554
+msgid "Display Configuration"
+msgstr "Настройка внешнего вида"
+
+#: radioview.cpp:590
+msgid "set Toolbar-Flag for Display"
+msgstr ""
+
+#: radioview.cpp:593
+msgid "Common"
+msgstr "Общие"
+
+#: radioview_frequencyradio.cpp:99 radioview_frequencyradio.cpp:100
+msgid "Frequency Display"
+msgstr "Отображение частоты"
+
+#: radioview_frequencyradio.cpp:388 radioview_frequencyradio.cpp:389
+msgid "AM"
+msgstr "ДВ/СВ/КВ"
+
+#: radioview_frequencyradio.cpp:394 radioview_frequencyradio.cpp:395
+msgid "FM"
+msgstr "УКВ"
+
+#: radioview_frequencyradio.cpp:406
+msgid "%1 kHz"
+msgstr "%1 кГц"
+
+#: radioview_frequencyradio.cpp:408
+msgid "%1 MHz"
+msgstr "%1 МГц"
+
+#: radioview_frequencyseeker.cpp:76
+msgid "Search for previous Radio Station"
+msgstr "Искать станцию вниз"
+
+#: radioview_frequencyseeker.cpp:77
+msgid "Search for next Radio Station"
+msgstr "Искать станцию вверх"
+
+#: radioview_frequencyseeker.cpp:78
+msgid "Decrement Frequency"
+msgstr "Уменьшить частоту"
+
+#: radioview_frequencyseeker.cpp:79
+msgid "Increment Frequency"
+msgstr "Увеличить частоту"
+
+#: radioview_frequencyseeker.cpp:80
+msgid "Change Frequency"
+msgstr "Изменить частоту"
+
+#: radioview_volume.cpp:56
+msgid "Change Volume"
+msgstr "Изменить громкость"
+
+#: radioview_seekinterface.ui:17
+#, no-c-format
+msgid "RadioView_SeekInterface"
+msgstr "RadioView_SeekInterface"
+
+#: radioview_seekinterface.ui:45
+#, no-c-format
+msgid "search previous station"
+msgstr "Поиск предыдущей станции"
+
+#: radioview_seekinterface.ui:73
+#, no-c-format
+msgid "decrease freq. by 0.05 MHz"
+msgstr "Уменьшать частоту по 0,05 МГц"
+
+#: radioview_seekinterface.ui:108
+#, no-c-format
+msgid "Frequency control"
+msgstr "Управление частотой"
+
+#: radioview_seekinterface.ui:129
+#, no-c-format
+msgid "increase freq. by 0.05 MHz"
+msgstr "Увеличивать частоту по 0,05 МГц"
+
+#: radioview_seekinterface.ui:146
+#, no-c-format
+msgid "search next station"
+msgstr "Поиск следующей станции"
diff --git a/plugins/gui-standard-display/po/tderadio-gui-standard-display.pot b/plugins/gui-standard-display/po/tderadio-gui-standard-display.pot
new file mode 100644
index 0000000..7c96d69
--- /dev/null
+++ b/plugins/gui-standard-display/po/tderadio-gui-standard-display.pot
@@ -0,0 +1,207 @@
+# 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 ""
+
+#: displaycfg.cpp:33
+msgid "Display Colors"
+msgstr ""
+
+#: displaycfg.cpp:47
+msgid "Active Text"
+msgstr ""
+
+#: displaycfg.cpp:48
+msgid "Inactive Text"
+msgstr ""
+
+#: displaycfg.cpp:49
+msgid "Background Color"
+msgstr ""
+
+#: radioview.cpp:55
+msgid "Standard Display for TDERadio"
+msgstr ""
+
+#: radioview.cpp:72
+msgid "Radio Display"
+msgstr ""
+
+#: radioview.cpp:127
+msgid "Pause TDERadio"
+msgstr ""
+
+#: radioview.cpp:133
+msgid "Start Recording"
+msgstr ""
+
+#: radioview.cpp:141
+msgid "5 min"
+msgstr ""
+
+#: radioview.cpp:142
+msgid "10 min"
+msgstr ""
+
+#: radioview.cpp:143
+msgid "15 min"
+msgstr ""
+
+#: radioview.cpp:144
+msgid "30 min"
+msgstr ""
+
+#: radioview.cpp:145
+msgid "60 min"
+msgstr ""
+
+#: radioview.cpp:189
+msgid "Configure TDERadio"
+msgstr ""
+
+#: radioview.cpp:190
+msgid "Power On/Off"
+msgstr ""
+
+#: radioview.cpp:191
+msgid "Quit TDERadio Application"
+msgstr ""
+
+#: radioview.cpp:192
+msgid "Start/Stop Recording"
+msgstr ""
+
+#: radioview.cpp:193
+msgid "Start/Stop Sleep Countdown"
+msgstr ""
+
+#: radioview.cpp:194
+msgid "Show/Hide Plugins"
+msgstr ""
+
+#: radioview.cpp:195
+msgid "Select a Radio Station"
+msgstr ""
+
+#: radioview.cpp:332
+msgid "no preset defined"
+msgstr ""
+
+#: radioview.cpp:442 radioview.cpp:480
+#, c-format
+msgid "Stop Recording of %1"
+msgstr ""
+
+#: radioview.cpp:553
+msgid "Display"
+msgstr ""
+
+#: radioview.cpp:554
+msgid "Display Configuration"
+msgstr ""
+
+#: radioview.cpp:590
+msgid "set Toolbar-Flag for Display"
+msgstr ""
+
+#: radioview.cpp:593
+msgid "Common"
+msgstr ""
+
+#: radioview_frequencyradio.cpp:99 radioview_frequencyradio.cpp:100
+msgid "Frequency Display"
+msgstr ""
+
+#: radioview_frequencyradio.cpp:388 radioview_frequencyradio.cpp:389
+msgid "AM"
+msgstr ""
+
+#: radioview_frequencyradio.cpp:394 radioview_frequencyradio.cpp:395
+msgid "FM"
+msgstr ""
+
+#: radioview_frequencyradio.cpp:406
+msgid "%1 kHz"
+msgstr ""
+
+#: radioview_frequencyradio.cpp:408
+msgid "%1 MHz"
+msgstr ""
+
+#: radioview_frequencyseeker.cpp:76
+msgid "Search for previous Radio Station"
+msgstr ""
+
+#: radioview_frequencyseeker.cpp:77
+msgid "Search for next Radio Station"
+msgstr ""
+
+#: radioview_frequencyseeker.cpp:78
+msgid "Decrement Frequency"
+msgstr ""
+
+#: radioview_frequencyseeker.cpp:79
+msgid "Increment Frequency"
+msgstr ""
+
+#: radioview_frequencyseeker.cpp:80
+msgid "Change Frequency"
+msgstr ""
+
+#: radioview_volume.cpp:56
+msgid "Change Volume"
+msgstr ""
+
+#: radioview_seekinterface.ui:17
+#, no-c-format
+msgid "RadioView_SeekInterface"
+msgstr ""
+
+#: radioview_seekinterface.ui:45
+#, no-c-format
+msgid "search previous station"
+msgstr ""
+
+#: radioview_seekinterface.ui:73
+#, no-c-format
+msgid "decrease freq. by 0.05 MHz"
+msgstr ""
+
+#: radioview_seekinterface.ui:108
+#, no-c-format
+msgid "Frequency control"
+msgstr ""
+
+#: radioview_seekinterface.ui:129
+#, no-c-format
+msgid "increase freq. by 0.05 MHz"
+msgstr ""
+
+#: radioview_seekinterface.ui:146
+#, no-c-format
+msgid "search next station"
+msgstr ""
diff --git a/plugins/gui-standard-display/radioview-configuration.cpp b/plugins/gui-standard-display/radioview-configuration.cpp
new file mode 100644
index 0000000..64af3ed
--- /dev/null
+++ b/plugins/gui-standard-display/radioview-configuration.cpp
@@ -0,0 +1,116 @@
+/***************************************************************************
+ radioview-configuration.cpp - description
+ -------------------
+ begin : Fr Aug 15 2003
+ copyright : (C) 2003 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 "radioview-configuration.h"
+
+RadioViewConfiguration::RadioViewConfiguration(TQWidget *parent)
+ : TQTabWidget (parent),
+ m_dirty(true)
+{
+}
+
+RadioViewConfiguration::~RadioViewConfiguration()
+{
+}
+
+
+void RadioViewConfiguration::addTab (TQWidget *child, const TQString &label)
+{
+ TQTabWidget::addTab(child, label);
+ TQObject::connect(this, TQT_SIGNAL(sigOK()), child, TQT_SLOT(slotOK()));
+ TQObject::connect(this, TQT_SIGNAL(sigCancel()), child, TQT_SLOT(slotCancel()));
+ TQObject::connect(child, TQT_SIGNAL(sigDirty()), this, TQT_SLOT(slotSetDirty()));
+}
+
+
+void RadioViewConfiguration::addTab (TQWidget *child, const TQIconSet &iconset, const TQString &label)
+{
+ TQTabWidget::addTab(child, iconset, label);
+ TQObject::connect(this, TQT_SIGNAL(sigOK()), child, TQT_SLOT(slotOK()));
+ TQObject::connect(this, TQT_SIGNAL(sigCancel()), child, TQT_SLOT(slotCancel()));
+ TQObject::connect(child, TQT_SIGNAL(sigDirty()), this, TQT_SLOT(slotSetDirty()));
+}
+
+
+void RadioViewConfiguration::addTab (TQWidget *child, TQTab *tab)
+{
+ TQTabWidget::addTab(child, tab);
+ TQObject::connect(this, TQT_SIGNAL(sigOK()), child, TQT_SLOT(slotOK()));
+ TQObject::connect(this, TQT_SIGNAL(sigCancel()), child, TQT_SLOT(slotCancel()));
+ TQObject::connect(child, TQT_SIGNAL(sigDirty()), this, TQT_SLOT(slotSetDirty()));
+}
+
+
+void RadioViewConfiguration::insertTab (TQWidget *child, const TQString &label, int index)
+{
+ TQTabWidget::insertTab(child, label, index);
+ TQObject::connect(this, TQT_SIGNAL(sigOK()), child, TQT_SLOT(slotOK()));
+ TQObject::connect(this, TQT_SIGNAL(sigCancel()), child, TQT_SLOT(slotCancel()));
+ TQObject::connect(child, TQT_SIGNAL(sigDirty()), this, TQT_SLOT(slotSetDirty()));
+}
+
+
+void RadioViewConfiguration::insertTab (TQWidget *child, const TQIconSet &iconset, const TQString &label, int index)
+{
+ TQTabWidget::insertTab(child, iconset, label, index);
+ TQObject::connect(this, TQT_SIGNAL(sigOK()), child, TQT_SLOT(slotOK()));
+ TQObject::connect(this, TQT_SIGNAL(sigCancel()), child, TQT_SLOT(slotCancel()));
+ TQObject::connect(child, TQT_SIGNAL(sigDirty()), this, TQT_SLOT(slotSetDirty()));
+}
+
+
+void RadioViewConfiguration::insertTab (TQWidget *child, TQTab *tab, int index)
+{
+ TQTabWidget::insertTab(child, tab, index);
+ TQObject::connect(this, TQT_SIGNAL(sigOK()), child, TQT_SLOT(slotOK()));
+ TQObject::connect(this, TQT_SIGNAL(sigCancel()), child, TQT_SLOT(slotCancel()));
+ TQObject::connect(child, TQT_SIGNAL(sigDirty()), this, TQT_SLOT(slotSetDirty()));
+}
+
+
+void RadioViewConfiguration::removePage(TQWidget *w)
+{
+ TQObject::disconnect(this, TQT_SIGNAL(sigOK()), w, TQT_SLOT(slotOK()));
+ TQObject::disconnect(this, TQT_SIGNAL(sigCancel()), w, TQT_SLOT(slotCancel()));
+ TQObject::disconnect(w, TQT_SIGNAL(sigDirty()), this, TQT_SLOT(slotSetDirty()));
+ TQTabWidget::removePage(w);
+}
+
+
+void RadioViewConfiguration::slotOK()
+{
+ if (m_dirty) {
+ emit sigOK();
+ m_dirty = false;
+ }
+}
+
+void RadioViewConfiguration::slotCancel()
+{
+ if (m_dirty) {
+ emit sigCancel();
+ m_dirty = false;
+ }
+}
+
+void RadioViewConfiguration::slotSetDirty()
+{
+ m_dirty = true;
+}
+
+
+#include "radioview-configuration.moc"
diff --git a/plugins/gui-standard-display/radioview-configuration.h b/plugins/gui-standard-display/radioview-configuration.h
new file mode 100644
index 0000000..7f14638
--- /dev/null
+++ b/plugins/gui-standard-display/radioview-configuration.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+ radioview-configuration.h - description
+ -------------------
+ begin : Fr Aug 15 2003
+ copyright : (C) 2003 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_RADIOVIEW_CONFIGURATION_H
+#define KRADIO_RADIOVIEW_CONFIGURATION_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+
+#include <tqtabwidget.h>
+
+class RadioViewConfiguration : public TQTabWidget
+{
+Q_OBJECT
+
+public :
+ RadioViewConfiguration(TQWidget *parent = NULL);
+ ~RadioViewConfiguration();
+
+ void addTab (TQWidget *child, const TQString &label);
+ void addTab (TQWidget *child, const TQIconSet &iconset, const TQString &label);
+ void addTab (TQWidget *child, TQTab *tab);
+ void insertTab (TQWidget *child, const TQString &label, int index = -1);
+ void insertTab (TQWidget *child, const TQIconSet &iconset, const TQString &label, int index = -1);
+ void insertTab (TQWidget *child, TQTab *tab, int index = -1);
+ void removePage(TQWidget *w);
+
+public slots:
+
+ void slotOK();
+ void slotCancel();
+ void slotSetDirty();
+
+signals:
+
+ void sigOK();
+ void sigCancel();
+
+protected:
+ bool m_dirty;
+};
+
+
+
+#endif
diff --git a/plugins/gui-standard-display/radioview.cpp b/plugins/gui-standard-display/radioview.cpp
new file mode 100644
index 0000000..dc828ab
--- /dev/null
+++ b/plugins/gui-standard-display/radioview.cpp
@@ -0,0 +1,807 @@
+/***************************************************************************
+ radioview.cpp - description
+ -------------------
+ begin : Mit Mai 28 2003
+ copyright : (C) 2003 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 <tqwidgetstack.h>
+#include <tqlayout.h>
+#include <tqtoolbutton.h>
+#include <tqslider.h>
+#include <tqfile.h>
+#include <tqtooltip.h>
+#include <tqcheckbox.h>
+#include <tqimage.h>
+
+#include <kcombobox.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+#include <twin.h>
+#include <tdeconfig.h>
+#include <tdepopupmenu.h>
+
+#include "../../src/include/radiodevice_interfaces.h"
+#include "../../src/include/radiostation.h"
+#include "../../src/include/stationlist.h"
+#include "../../src/include/pluginmanager.h"
+#include "../../src/include/plugin_configuration_dialog.h"
+#include "../../src/include/aboutwidget.h"
+
+#include "radioview.h"
+#include "radioview_frequencyradio.h"
+#include "radioview_volume.h"
+#include "radioview_frequencyseeker.h"
+#include "radioview-configuration.h"
+
+#include <tdeaboutdata.h>
+
+#define POPUP_ID_START_RECORDING_DEFAULT 0
+#define POPUP_ID_STOP_RECORDING_BASE 100
+
+///////////////////////////////////////////////////////////////////////
+
+PLUGIN_LIBRARY_FUNCTIONS(RadioView, "tderadio-gui-standard-display", i18n("Standard Display for TDERadio"));
+
+///////////////////////////////////////////////////////////////////////
+
+bool RadioView::ElementCfg::operator == (const ElementCfg &x) const
+{
+ if (!x.element || !element)
+ return x.cfg == cfg;
+ if (!x.cfg || !cfg)
+ return x.element == element;
+ return element == x.element && cfg == x.cfg;
+}
+
+///////////////////////////////////////////////////////////////////////
+
+RadioView::RadioView(const TQString &name)
+ : TQWidget(NULL, name.ascii()),
+ WidgetPluginBase(name, i18n("Radio Display")),
+ enableToolbarFlag(false),
+ btnPower(NULL),
+ btnConfigure(NULL),
+ btnQuit(NULL),
+ btnRecording(NULL),
+ btnSnooze(NULL),
+ btnPlugins(NULL),
+ comboStations(NULL),
+ currentDevice(NULL),
+ m_RecordingMenu(NULL),
+ m_NextRecordingMenuID(POPUP_ID_STOP_RECORDING_BASE),
+ m_PluginMenu(NULL)
+{
+ for (int i = 0; i < clsClassMAX; ++i)
+ maxUsability[i] = 0;
+
+ TQBoxLayout *l01 = new TQBoxLayout(this, TQBoxLayout::LeftToRight, /*spacing=*/3);
+ l01->setMargin(1);
+ l01->setSpacing(2);
+ widgetStacks[clsRadioSound] = new TQWidgetStack (this);
+ l01->addWidget(widgetStacks[clsRadioSound]);
+
+ TQBoxLayout *l02 = new TQBoxLayout(l01, TQBoxLayout::Down);
+ TQBoxLayout *l03 = new TQBoxLayout(l02, TQBoxLayout::LeftToRight);
+ comboStations = new KComboBox (this);
+ l02->addWidget (comboStations);
+
+ TQBoxLayout *l05 = new TQBoxLayout(l03, TQBoxLayout::Down);
+ widgetStacks[clsRadioDisplay] = new TQWidgetStack (this);
+ l05->addWidget(widgetStacks[clsRadioDisplay]);
+ widgetStacks[clsRadioSeek] = new TQWidgetStack (this);
+ l05->addWidget(widgetStacks[clsRadioSeek]);
+
+ TQGridLayout *l04 = new TQGridLayout (l03, /*rows=*/ 3, /*cols=*/ 2);
+ btnPower = new TQToolButton(this);
+ btnPower->setToggleButton(true);
+ btnRecording = new TQToolButton(this);
+ btnRecording->setToggleButton(true);
+ btnConfigure = new TQToolButton(this);
+ btnConfigure->setToggleButton(true);
+ btnQuit = new TQToolButton(this);
+ btnSnooze = new TQToolButton(this);
+ btnSnooze->setToggleButton(true);
+ btnPlugins = new TQToolButton(this);
+ btnPlugins->setPopupDelay(1);
+ l04->addWidget (btnPower, 0, 0);
+ l04->addWidget (btnRecording, 0, 1);
+ l04->addWidget (btnConfigure, 1, 0);
+ l04->addWidget (btnQuit, 1, 1);
+ l04->addWidget (btnSnooze, 2, 0);
+ l04->addWidget (btnPlugins, 2, 1);
+
+ m_pauseMenu = new TDEPopupMenu(btnPower);
+ m_pauseMenu->insertItem(SmallIcon("tderadio_pause"),
+ i18n("Pause TDERadio"),
+ this, TQT_SLOT(slotPause()));
+ btnPower->setPopupDelay(200);
+
+ m_RecordingMenu = new TDEPopupMenu(btnRecording);
+ m_RecordingMenu->insertItem(SmallIcon("tderadio_record"),
+ i18n("Start Recording"),
+ POPUP_ID_START_RECORDING_DEFAULT);
+ TQObject::connect(m_RecordingMenu, TQT_SIGNAL(activated(int)),
+ this, TQT_SLOT(slotRecordingMenu(int)));
+ btnRecording->setPopup(m_RecordingMenu);
+
+
+ m_SnoozeMenu = new TDEPopupMenu(btnSnooze);
+ m_SnoozeMenu->insertItem(i18n("5 min"), this, TQT_SLOT(slotSnooze(int)), 0, 5);
+ m_SnoozeMenu->insertItem(i18n("10 min"), this, TQT_SLOT(slotSnooze(int)), 0, 10);
+ m_SnoozeMenu->insertItem(i18n("15 min"), this, TQT_SLOT(slotSnooze(int)), 0, 15);
+ m_SnoozeMenu->insertItem(i18n("30 min"), this, TQT_SLOT(slotSnooze(int)), 0, 30);
+ m_SnoozeMenu->insertItem(i18n("60 min"), this, TQT_SLOT(slotSnooze(int)), 0, 60);
+ btnSnooze->setPopup(m_SnoozeMenu);
+ btnSnooze->setPopupDelay(200);
+
+ // Plugin-Button/Menu
+
+ m_PluginMenu = new TDEPopupMenu(btnPlugins);
+ if (m_manager)
+ m_manager->addWidgetPluginMenuItems(m_PluginMenu, m_Plugins2MenuID);
+ btnPlugins->setPopup(m_PluginMenu);
+
+ // ICONS
+
+ btnPower->setIconSet(SmallIconSet("tderadio_muteon"));
+ btnRecording->setIconSet(SmallIconSet("tderadio_record"));
+ btnConfigure->setIconSet(SmallIconSet("configure"));
+ btnQuit->setIconSet(SmallIconSet("system-log-out"));
+ btnSnooze->setIconSet(SmallIconSet("tderadio_zzz"));
+ btnPlugins->setIconSet(SmallIconSet("tderadio_plugins"));
+
+ widgetStacks[clsRadioSound] ->setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Preferred));
+ widgetStacks[clsRadioDisplay]->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Preferred));
+ widgetStacks[clsRadioSeek] ->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed));
+ comboStations ->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Fixed));
+ comboStations->setMinimumHeight(28);
+
+
+ TQObject::connect(btnPower, TQT_SIGNAL(toggled(bool)),
+ this, TQT_SLOT(slotPower(bool)));
+ TQObject::connect(btnQuit, TQT_SIGNAL(clicked()),
+ kapp, TQT_SLOT(quit()));
+ TQObject::connect(btnConfigure, TQT_SIGNAL(toggled(bool)),
+ this, TQT_SLOT(slotConfigure(bool)));
+ TQObject::connect(btnRecording, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotRecord()));
+ TQObject::connect(btnSnooze, TQT_SIGNAL(toggled(bool)),
+ this, TQT_SLOT(slotSnooze(bool)));
+ TQObject::connect(comboStations, TQT_SIGNAL(activated(int)),
+ this, TQT_SLOT(slotComboStationSelected(int)));
+ TQObject::connect(btnPlugins, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotBtnPluginsClicked()));
+
+ // tooltips
+
+ TQToolTip::add(btnConfigure, i18n("Configure TDERadio"));
+ TQToolTip::add(btnPower, i18n("Power On/Off"));
+ TQToolTip::add(btnQuit, i18n("Quit TDERadio Application"));
+ TQToolTip::add(btnRecording, i18n("Start/Stop Recording"));
+ TQToolTip::add(btnSnooze, i18n("Start/Stop Sleep Countdown"));
+ TQToolTip::add(btnPlugins, i18n("Show/Hide Plugins"));
+ TQToolTip::add(comboStations, i18n("Select a Radio Station"));
+
+ // testing
+ addElement (new RadioViewFrequencyRadio (this, TQString()));
+ addElement (new RadioViewVolume(this, TQString()));
+ addElement (new RadioViewFrequencySeeker(this, TQString()));
+
+ autoSetCaption();
+}
+
+
+RadioView::~RadioView ()
+{
+ TQPtrListIterator<TQObject> it(configPages);
+ while (configPages.first()) {
+ delete configPages.first();
+ }
+ configPages.clear();
+}
+
+
+bool RadioView::addElement (RadioViewElement *e)
+{
+ if (!e) return false;
+
+ RadioViewClass cls = e->getClass();
+
+ if (cls < 0 || cls >= clsClassMAX)
+ return false;
+
+
+ e->reparent(this, TQPoint(0, 0), true);
+ TQObject::connect(e, TQT_SIGNAL(destroyed(TQObject*)),
+ this, TQT_SLOT(removeElement(TQObject*)));
+ elements.append(e);
+ widgetStacks[cls]->addWidget(e);
+
+ // connect Element with device, disconnect doesn't matter (comp. removeElement)
+ // other devices follow if currentDevice changes
+ if (currentDevice)
+ e->connectI(currentDevice);
+
+ e->connectI(getSoundStreamServer());
+
+ TQPtrListIterator<TQObject> it(configPages);
+ for (; it.current(); ++it) {
+ addConfigurationTabFor(e, (TQTabWidget *)it.current());
+ }
+
+ selectTopWidgets();
+
+ return true;
+}
+
+
+bool RadioView::removeElement (TQObject *_e)
+{
+ RadioViewElement *e = dynamic_cast<RadioViewElement*>(_e);
+ if (!e)
+ return false;
+
+ ElementCfgListIterator it;
+ while ((it = elementConfigPages.find(e)) != elementConfigPages.end()) {
+ delete (*it).cfg;
+ // it must not used behind, the element will be deleted automatically
+ // by slotElementConfigPageDeleted
+ }
+
+ e->disconnectI(getSoundStreamServer());
+
+ if (currentDevice)
+ e->disconnectI(currentDevice);
+
+ RadioViewClass cls = e->getClass();
+ TQObject::disconnect(e, TQT_SIGNAL(destroyed(TQObject*)),
+ this, TQT_SLOT(removeElement(TQObject*)));
+ widgetStacks[cls]->removeWidget(e);
+ elements.remove(e);
+
+ selectTopWidgets();
+
+ return true;
+}
+
+
+void RadioView::selectTopWidgets()
+{
+ for (int i = 0; i < clsClassMAX; ++i)
+ maxUsability[i] = 0;
+
+ for (ElementListIterator i(elements); i.current(); ++i) {
+ RadioViewElement *e = i.current();
+ RadioViewClass cls = e->getClass();
+ float u = e->getUsability(currentDevice);
+ if (u > maxUsability[cls]) {
+ maxUsability[cls] = u;
+ widgetStacks[cls]->raiseWidget(e);
+ }
+ }
+ // adjustLayout!?
+}
+
+
+// IRadioClient
+
+bool RadioView::noticePowerChanged(bool on)
+{
+ btnPower->setIconSet(SmallIconSet( on ? "tderadio_muteoff" : "tderadio_muteon"));
+ btnPower->setOn(on);
+ if (on) {
+ btnPower->setPopup(m_pauseMenu);
+ } else {
+ btnPower->setPopup(NULL);
+ }
+ autoSetCaption();
+ return true;
+}
+
+
+bool RadioView::noticeStationChanged (const RadioStation &, int idx)
+{
+ // add 1 for "no preset defined" entry
+ comboStations->setCurrentItem(idx + 1);
+ autoSetCaption();
+ bool r = false;
+ SoundFormat sf;
+ queryIsRecordingRunning(queryCurrentSoundStreamID(), r, sf);
+ m_RecordingMenu->setItemEnabled(POPUP_ID_START_RECORDING_DEFAULT, !r);
+ return true;
+}
+
+
+bool RadioView::noticeStationsChanged(const StationList &sl)
+{
+ const RawStationList &list = sl.all();
+
+ comboStations->clear();
+ comboStations->insertItem("<" + i18n("no preset defined") + ">");
+
+ for (RawStationList::Iterator i(list); i.current(); ++i) {
+ RadioStation *stn = i.current();
+ TQString icon = stn->iconName();
+ if (icon.length() && TQFile(icon).exists()) {
+ TQImage img(icon);
+ int h = img.height();
+ float f = (float)(comboStations->height() - 4) / (h ? (float)h : 1.0);
+ comboStations->insertItem(img.smoothScale((int)(img.width()*f), (int)(h * f)), stn->name());
+ } else {
+ comboStations->insertItem(stn->name());
+ }
+ }
+
+ noticeStationChanged(queryCurrentStation(), queryCurrentStationIdx());
+ return true;
+}
+
+
+bool RadioView::noticeCurrentSoundStreamIDChanged(SoundStreamID /*id*/)
+{
+ // FIXME: perhaps do something
+ return false;
+}
+
+// IRadioDevicePoolClient
+
+bool RadioView::noticeActiveDeviceChanged(IRadioDevice *newDevice)
+{
+ IRadioDevice *oldDevice = currentDevice;
+ currentDevice = newDevice;
+
+ for (ElementListIterator i(elements); i.current(); ++i) {
+ RadioViewElement *e = i.current();
+ if (oldDevice)
+ e->disconnectI(oldDevice);
+ if (newDevice)
+ e->connectI(currentDevice);
+ }
+
+ selectTopWidgets();
+ return true;
+}
+
+
+// Interface
+
+bool RadioView::connectI(Interface *i)
+{
+ bool a = IRadioClient::connectI(i);
+ bool b = IRadioDevicePoolClient::connectI(i);
+ bool c = PluginBase::connectI(i);
+ bool d = ITimeControlClient::connectI(i);
+
+ // Callbacks for ISoundStreamClient
+
+ bool e = ISoundStreamClient::connectI(i);
+
+ return a || b || c || d || e;
+}
+
+
+bool RadioView::disconnectI(Interface *i)
+{
+ bool a = IRadioClient::disconnectI(i);
+ bool b = IRadioDevicePoolClient::disconnectI(i);
+ bool c = PluginBase::disconnectI(i);
+ bool d = ITimeControlClient::disconnectI(i);
+ bool e = ISoundStreamClient::disconnectI(i);
+ if (e) {
+ // special task for soundstreamclient, different from radio device pool
+ for (ElementListIterator it(elements); it.current(); ++it) {
+ RadioViewElement *e = it.current();
+ e->disconnectI(i);
+ }
+ }
+ return a || b || c || d || e;
+}
+
+void RadioView::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid)
+{
+ ISoundStreamClient::noticeConnectedI(s, pointer_valid);
+ if (s && pointer_valid) {
+ s->register4_sendStartRecordingWithFormat(this);
+ s->register4_sendStopRecording (this);
+ s->register4_notifySoundStreamChanged (this);
+
+ // special task for soundstreamclient, different from radio device pool
+ for (ElementListIterator it(elements); it.current(); ++it) {
+ RadioViewElement *e = it.current();
+ e->connectI(s);
+ }
+ }
+}
+
+// ISoundStreamClient
+
+bool RadioView::startRecordingWithFormat(
+ SoundStreamID id,
+ const SoundFormat &/*proposed_format*/,
+ SoundFormat &/*real_format*/)
+{
+ if (!id.isValid() || id != queryCurrentSoundStreamID() || m_StreamID2MenuID.contains(id))
+ return false;
+
+ TQString descr;
+ querySoundStreamDescription(id, descr);
+ int menu_id = m_NextRecordingMenuID++;
+ m_RecordingMenu->insertItem(SmallIcon("tderadio_record"),
+ i18n("Stop Recording of %1").arg(descr),
+ menu_id);
+ m_MenuID2StreamID.insert(menu_id, id);
+ m_StreamID2MenuID.insert(id, menu_id);
+ btnRecording->setOn(true);
+
+ if (id == queryCurrentSoundStreamID())
+ m_RecordingMenu->setItemEnabled(POPUP_ID_START_RECORDING_DEFAULT, false);
+
+ return false; // this is only a "hook" that does not initiate the recording so don't say that we handled the event
+}
+
+
+bool RadioView::stopRecording (SoundStreamID id)
+{
+ if (!id.isValid() || !m_StreamID2MenuID.contains(id))
+ return false;
+
+ int menu_id = m_StreamID2MenuID[id];
+ m_RecordingMenu->removeItem(menu_id);
+ m_MenuID2StreamID.remove(menu_id);
+ m_StreamID2MenuID.remove(id);
+ btnRecording->setOn(m_StreamID2MenuID.count() > 0);
+
+ if (id == queryCurrentSoundStreamID())
+ m_RecordingMenu->setItemEnabled(POPUP_ID_START_RECORDING_DEFAULT, true);
+
+ return false;
+}
+
+
+bool RadioView::noticeSoundStreamChanged(SoundStreamID id)
+{
+ if (m_StreamID2MenuID.contains(id)) {
+ TQString descr;
+ querySoundStreamDescription(id, descr);
+ m_RecordingMenu->changeItem(m_StreamID2MenuID[id],
+ SmallIcon("tderadio_record"),
+ i18n("Stop Recording of %1").arg(descr));
+ return true;
+ }
+ return false;
+}
+
+
+// ITimeControl
+
+bool RadioView::noticeCountdownStarted(const TQDateTime &)
+{
+ btnSnooze->setOn(true);
+ return true;
+}
+
+bool RadioView::noticeCountdownStopped()
+{
+ btnSnooze->setOn(false);
+ return true;
+}
+
+bool RadioView::noticeCountdownZero()
+{
+ btnSnooze->setOn(false);
+ return true;
+}
+
+// WidgetPluginBase
+
+void RadioView::saveState (TDEConfig *config) const
+{
+ config->setGroup(TQString("radioview-") + name());
+
+ config->writeEntry("enableToobarFlag", enableToolbarFlag);
+ WidgetPluginBase::saveState(config);
+
+ for (ElementListIterator i(elements); i.current(); ++i) {
+ RadioViewElement *e = i.current();
+ e->saveState(config);
+ }
+}
+
+
+void RadioView::restoreState (TDEConfig *config)
+{
+ config->setGroup(TQString("radioview-") + name());
+
+ enableToolbarFlag = config->readBoolEntry("enableToolbarFlag", false);
+ WidgetPluginBase::restoreState(config);
+
+ for (ElementListIterator i(elements); i.current(); ++i) {
+ RadioViewElement *e = i.current();
+ e->restoreState(config);
+ }
+}
+
+
+ConfigPageInfo RadioView::createConfigurationPage()
+{
+ RadioViewConfiguration *c = new RadioViewConfiguration();
+
+ //addCommonConfigurationTab(c);
+
+ for (ElementListIterator i(elements); i.current(); ++i) {
+ addConfigurationTabFor(i.current(), c);
+ }
+
+ configPages.append(TQT_TQOBJECT(c));
+ TQObject::connect(c, TQT_SIGNAL(destroyed(TQObject *)),
+ this, TQT_SLOT(slotConfigPageDeleted(TQObject *)));
+
+ return ConfigPageInfo(
+ c,
+ i18n("Display"),
+ i18n("Display Configuration"),
+ "openterm"
+ );
+}
+
+
+void RadioView::addConfigurationTabFor(RadioViewElement *e, TQTabWidget *c)
+{
+ if (!e || !c)
+ return;
+
+ ConfigPageInfo inf = e->createConfigurationPage();
+
+ if (inf.page) {
+
+ if (inf.iconName.length()) {
+ c->addTab(inf.page, TQIconSet(SmallIconSet(inf.iconName)), inf.itemName);
+ } else {
+ c->addTab(inf.page, inf.itemName);
+ }
+
+ elementConfigPages.push_back(ElementCfg(e, TQT_TQOBJECT(inf.page)));
+ TQObject::connect(inf.page, TQT_SIGNAL(destroyed(TQObject *)),
+ this, TQT_SLOT(slotElementConfigPageDeleted(TQObject *)));
+ }
+}
+
+
+void RadioView::addCommonConfigurationTab(TQTabWidget *c)
+{
+ if (!c)
+ return;
+
+ TQFrame *f = new TQFrame(c);
+ TQVBoxLayout *l = new TQVBoxLayout(f, 10);
+
+ l->addWidget(new TQCheckBox(i18n("set Toolbar-Flag for Display"), f));
+ l->addItem(new TQSpacerItem(1, 3, TQSizePolicy::Fixed, TQSizePolicy::Expanding));
+
+ c->addTab(f, i18n("Common"));
+
+ elementConfigPages.push_back(ElementCfg(TQT_TQOBJECT(f)));
+ TQObject::connect(f, TQT_SIGNAL(destroyed(TQObject *)),
+ this, TQT_SLOT(slotElementConfigPageDeleted(TQObject *)));
+}
+
+
+AboutPageInfo RadioView::createAboutPage()
+{
+/* TDEAboutData aboutData("tderadio",
+ NULL,
+ NULL,
+ I18N_NOOP("Standard Radio Display for TDERadio"),
+ TDEAboutData::License_GPL,
+ "(c) 2002-2005 Martin Witte, Klas Kalass",
+ 0,
+ "http://sourceforge.net/projects/tderadio",
+ 0);
+ aboutData.addAuthor("Martin Witte", "", "witte@kawo1.rwth-aachen.de");
+ aboutData.addAuthor("Klas Kalass", "", "klas.kalass@gmx.de");
+
+ return AboutPageInfo(
+ new TDERadioAboutWidget(aboutData, TDERadioAboutWidget::AbtTabbed),
+ i18n("Display"),
+ i18n("Standard Radio Display for TDERadio"),
+ "openterm"
+ );*/
+ return AboutPageInfo();
+}
+
+
+void RadioView::noticeWidgetPluginShown(WidgetPluginBase *p, bool shown)
+{
+ if (!m_manager || !p)
+ return;
+ if ((WidgetPluginBase*)m_manager->getConfigDialog() == p) {
+ btnConfigure->blockSignals(true);
+ btnConfigure->setOn(shown);
+ btnConfigure->blockSignals(false);
+ }
+
+ if (m_Plugins2MenuID.contains(p)) {
+ m_manager->updateWidgetPluginMenuItem(p, m_PluginMenu, m_Plugins2MenuID, shown);
+ }
+}
+
+
+// own Stuff
+
+void RadioView::noticePluginsChanged(const PluginList &/*l*/)
+{
+ m_Plugins2MenuID.clear();
+ m_PluginMenu->clear();
+ if (m_manager)
+ m_manager->addWidgetPluginMenuItems(m_PluginMenu, m_Plugins2MenuID);
+}
+
+
+void RadioView::slotPower(bool on)
+{
+ on ? sendPowerOn() : sendPowerOff();
+ btnPower->setOn(queryIsPowerOn());
+}
+
+
+void RadioView::slotPause()
+{
+ if (queryIsPowerOn()) {
+ sendPausePlayback(queryCurrentSoundStreamID());
+ }
+}
+
+
+void RadioView::slotConfigure(bool b)
+{
+ TQWidget *w = m_manager ? m_manager->getConfigDialog() : NULL;
+ if (w) b ? w->show() : w->hide();
+ if (!w)
+ btnConfigure->setOn(false);
+}
+
+
+void RadioView::slotRecord()
+{
+ SoundStreamID id = queryCurrentSoundStreamID();
+ bool b = btnRecording->isOn();
+
+ bool r = false;
+ SoundFormat sf;
+ queryIsRecordingRunning(id, r, sf);
+
+ if (!r && b /*!m_StreamID2MenuID.contains(id)*/) {
+ if (!queryIsPowerOn())
+ sendPowerOn();
+ sendStartRecording(id);
+ } else if (r && !b) {
+ sendStopRecording(id);
+ }
+}
+
+
+void RadioView::slotRecordingMenu(int i)
+{
+ if (i == POPUP_ID_START_RECORDING_DEFAULT) {
+ SoundStreamID id = queryCurrentSoundStreamID();
+ bool r = false;
+ SoundFormat sf;
+ queryIsRecordingRunning(id, r, sf);
+ if (!r) {
+ if (!queryIsPowerOn())
+ sendPowerOn();
+ sendStartRecording(id);
+ }
+ } else if (m_MenuID2StreamID.contains(i)) {
+ sendStopRecording(m_MenuID2StreamID[i]);
+ }
+}
+
+
+void RadioView::slotSnooze(bool on)
+{
+ if (on)
+ sendStartCountdown();
+ else
+ sendStopCountdown();
+}
+
+
+void RadioView::slotSnooze(int n)
+{
+ sendCountdownSeconds(n*60);
+ sendStartCountdown();
+}
+
+
+void RadioView::slotComboStationSelected(int idx)
+{
+ if (idx > 0) {
+ sendActivateStation(idx - 1);
+ } else {
+ comboStations->setCurrentItem(queryCurrentStationIdx() + 1);
+ }
+}
+
+void RadioView::slotBtnPluginsClicked()
+{
+ btnPlugins->openPopup();
+}
+
+void RadioView::slotConfigPageDeleted(TQObject *o)
+{
+ configPages.remove(o);
+}
+
+
+void RadioView::slotElementConfigPageDeleted(TQObject *o)
+{
+ ElementCfgListIterator it;
+ while ((it = elementConfigPages.find(o)) != elementConfigPages.end()) {
+ elementConfigPages.remove(it);
+ }
+}
+
+
+void RadioView::show()
+{
+ if (enableToolbarFlag)
+ KWin::setType(winId(), NET::Toolbar);
+ else
+ KWin::setType(winId(), NET::Normal);
+ WidgetPluginBase::pShow();
+ TQWidget::show();
+}
+
+
+void RadioView::showOnOrgDesktop()
+{
+ WidgetPluginBase::pShowOnOrgDesktop();
+ //TQWidget::show();
+}
+
+
+
+void RadioView::hide()
+{
+ WidgetPluginBase::pHide();
+ TQWidget::hide();
+}
+
+
+void RadioView::showEvent(TQShowEvent *e)
+{
+ TQWidget::showEvent(e);
+ WidgetPluginBase::pShowEvent(e);
+}
+
+
+void RadioView::hideEvent(TQHideEvent *e)
+{
+ TQWidget::hideEvent(e);
+ WidgetPluginBase::pHideEvent(e);
+}
+
+
+void RadioView::autoSetCaption()
+{
+ const RadioStation &rs = queryCurrentStation();
+ setCaption((queryIsPowerOn() && rs.isValid()) ? rs.longName() : TQString("TDERadio"));
+}
+
+
+
+
+#include "radioview.moc"
diff --git a/plugins/gui-standard-display/radioview.h b/plugins/gui-standard-display/radioview.h
new file mode 100644
index 0000000..2874d18
--- /dev/null
+++ b/plugins/gui-standard-display/radioview.h
@@ -0,0 +1,208 @@
+/***************************************************************************
+ radioview.h - description
+ -------------------
+ begin : Mit Mai 28 2003
+ copyright : (C) 2003 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_RADIOVIEW_H
+#define KRADIO_RADIOVIEW_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tqobjectlist.h>
+
+#include "../../src/include/radio_interfaces.h"
+#include "../../src/include/radiodevicepool_interfaces.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+#include "../../src/include/timecontrol_interfaces.h"
+#include "../../src/include/widgetplugins.h"
+#include "radioview_element.h"
+
+class TQWidgetStack;
+class TQToolButton;
+class KComboBox;
+class TQTabWidget;
+class TDEPopupMenu;
+
+
+
+class RadioView : public TQWidget,
+ public WidgetPluginBase,
+ public IRadioClient,
+ public IRadioDevicePoolClient,
+ public ISoundStreamClient,
+ public ITimeControlClient
+{
+Q_OBJECT
+
+public:
+
+ RadioView(const TQString &name);
+ virtual ~RadioView();
+
+ virtual TQString pluginClassName() const { return "RadioView"; }
+
+ const TQString &name() const { return PluginBase::name(); }
+ TQString &name() { return PluginBase::name(); }
+
+ // WidgetPluginBase
+
+public:
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+ virtual bool connectI(Interface *i);
+ virtual bool disconnectI(Interface *i);
+
+ virtual void noticeWidgetPluginShown(WidgetPluginBase *p, bool shown);
+ virtual void noticePluginsChanged(const PluginList &);
+
+ virtual ConfigPageInfo createConfigurationPage();
+ virtual AboutPageInfo createAboutPage();
+
+public slots:
+ // connects destroy-msg with remove-function
+ bool addElement (RadioViewElement *);
+ bool removeElement (TQObject *);
+
+protected:
+ void selectTopWidgets();
+
+
+ // IRadioClient
+
+RECEIVERS:
+ bool noticePowerChanged(bool on);
+ bool noticeStationChanged (const RadioStation &, int idx);
+ bool noticeStationsChanged(const StationList &sl);
+ bool noticePresetFileChanged(const TQString &/*f*/) { return false; }
+
+ bool noticeCurrentSoundStreamIDChanged(SoundStreamID id);
+
+ // IRadioDevicePoolClient
+
+RECEIVERS:
+ bool noticeActiveDeviceChanged(IRadioDevice *rd);
+ bool noticeDevicesChanged(const TQPtrList<IRadioDevice> &) { return false; }
+ bool noticeDeviceDescriptionChanged(const TQString &) { return false; }
+
+ // ISoundStreamClient
+
+RECEIVERS:
+ void noticeConnectedI (ISoundStreamServer *s, bool pointer_valid);
+
+ bool startRecordingWithFormat(SoundStreamID /*id*/,
+ const SoundFormat &/*proposed_format*/,
+ SoundFormat &/*real_format*/);
+ bool stopRecording(SoundStreamID /*id*/);
+
+ bool noticeSoundStreamChanged(SoundStreamID id);
+
+ // ITimeControlClient
+
+RECEIVERS:
+ bool noticeAlarmsChanged(const AlarmVector &) { return false; }
+ bool noticeAlarm(const Alarm &) { return false; }
+ bool noticeNextAlarmChanged(const Alarm *) { return false; }
+ bool noticeCountdownStarted(const TQDateTime &end);
+ bool noticeCountdownStopped();
+ bool noticeCountdownZero();
+ bool noticeCountdownSecondsChanged(int) { return false; }
+
+protected slots:
+
+ void slotPower (bool on);
+ void slotPause();
+ void slotConfigure (bool show);
+ void slotRecord ();
+ void slotSnooze (bool start);
+ void slotSnooze (int time);
+ void slotRecordingMenu(int i);
+ void slotBtnPluginsClicked();
+ void slotComboStationSelected(int);
+
+ void slotConfigPageDeleted(TQObject*);
+ void slotElementConfigPageDeleted(TQObject*);
+
+public slots:
+
+ void toggleShown() { WidgetPluginBase::pToggleShown(); }
+ void showOnOrgDesktop();
+ void show();
+ void hide();
+
+protected:
+ virtual void showEvent(TQShowEvent *);
+ virtual void hideEvent(TQHideEvent *);
+
+ virtual void autoSetCaption();
+
+ const TQWidget *getWidget() const { return this; }
+ TQWidget *getWidget() { return this; }
+
+ void addConfigurationTabFor(RadioViewElement *, TQTabWidget *);
+ void addCommonConfigurationTab(TQTabWidget *);
+
+protected:
+ bool enableToolbarFlag;
+
+ TQToolButton *btnPower;
+ TQToolButton *btnConfigure;
+ TQToolButton *btnQuit;
+ TQToolButton *btnRecording;
+ TQToolButton *btnSnooze;
+ TQToolButton *btnPlugins;
+ KComboBox *comboStations;
+
+ struct ElementCfg
+ {
+ RadioViewElement *element;
+ TQObject *cfg;
+ ElementCfg() : element(NULL), cfg(NULL) {}
+ ElementCfg(RadioViewElement *e, TQObject *w) : element(e), cfg(w) {}
+ ElementCfg(RadioViewElement *e) : element(e), cfg(NULL) {}
+ ElementCfg(TQObject *w) : element(NULL), cfg(w) {}
+ bool operator == (const ElementCfg &x) const;
+ };
+
+ typedef TQPtrList<RadioViewElement> ElementList;
+ typedef TQPtrListIterator<RadioViewElement> ElementListIterator;
+ typedef TQValueList<ElementCfg> ElementCfgList;
+ typedef TQValueListIterator<ElementCfg> ElementCfgListIterator;
+
+ ElementList elements;
+ ElementCfgList elementConfigPages;
+ TQObjectList configPages;
+ TQWidgetStack * widgetStacks[clsClassMAX];
+ float maxUsability[clsClassMAX];
+
+ IRadioDevice *currentDevice;
+
+ TDEPopupMenu *m_RecordingMenu;
+ TDEPopupMenu *m_pauseMenu;
+ TDEPopupMenu *m_SnoozeMenu;
+ int m_NextRecordingMenuID;
+ TQMap<int, SoundStreamID> m_MenuID2StreamID;
+ TQMap<SoundStreamID, int> m_StreamID2MenuID;
+
+ TDEPopupMenu *m_PluginMenu;
+ TQMap<WidgetPluginBase *, int> m_Plugins2MenuID;
+};
+
+
+
+
+#endif
diff --git a/plugins/gui-standard-display/radioview_element.cpp b/plugins/gui-standard-display/radioview_element.cpp
new file mode 100644
index 0000000..7ad8bb1
--- /dev/null
+++ b/plugins/gui-standard-display/radioview_element.cpp
@@ -0,0 +1,34 @@
+/***************************************************************************
+ radioview_element.cpp - description
+ -------------------
+ begin : Fre Jun 20 2003
+ copyright : (C) 2003 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 "radioview_element.h"
+
+RadioViewElement::RadioViewElement (TQWidget * /*parent*/, const TQString & /*name*/,
+ RadioViewClass cls)
+ : myClass(cls)
+{
+}
+
+
+RadioViewElement::~RadioViewElement()
+{
+}
+
+
+
+
+#include "radioview_element.moc"
diff --git a/plugins/gui-standard-display/radioview_element.h b/plugins/gui-standard-display/radioview_element.h
new file mode 100644
index 0000000..cab2c89
--- /dev/null
+++ b/plugins/gui-standard-display/radioview_element.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+ radioview_element.h - description
+ -------------------
+ begin : Fre Jun 20 2003
+ copyright : (C) 2003 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_RADIOVIEW_ELEMENT_H
+#define KRADIO_RADIOVIEW_ELEMENT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tqframe.h>
+#include "../../src/include/interfaces.h"
+#include "../../src/include/plugins.h"
+
+enum RadioViewClass { clsRadioSound = 0,
+ clsRadioSeek,
+ clsRadioDisplay,
+ clsClassMAX
+ };
+
+
+// Defaults to an empty element
+class RadioViewElement : public TQFrame,
+ public virtual Interface
+{
+Q_OBJECT
+
+public:
+ RadioViewElement (TQWidget *parent, const TQString &name, RadioViewClass myClass);
+ virtual ~RadioViewElement();
+
+ bool connectI (Interface *) { return false; } // default behaviour, please overwrite in derived class
+ bool disconnectI(Interface *) { return false; } // default behaviour, please overwrite in derived class
+
+ float getUsability (Interface *) const { return 0.01; } // 0 <= Usability <= 1, used to decide wich Element to use
+ // should be overwritten ;)
+
+ RadioViewClass getClass() const { return myClass; }
+
+ // Configuration ??
+ virtual ConfigPageInfo createConfigurationPage() { return ConfigPageInfo(); }
+
+ virtual void saveState (TDEConfig *) const {}
+ virtual void restoreState (TDEConfig *) {}
+
+
+protected :
+
+ RadioViewClass myClass;
+};
+
+
+#endif
diff --git a/plugins/gui-standard-display/radioview_frequencyradio.cpp b/plugins/gui-standard-display/radioview_frequencyradio.cpp
new file mode 100644
index 0000000..5ea255e
--- /dev/null
+++ b/plugins/gui-standard-display/radioview_frequencyradio.cpp
@@ -0,0 +1,443 @@
+/***************************************************************************
+ tderadiodisplay.cpp - description
+ -------------------
+ begin : Mit Jan 29 2003
+ copyright : (C) 2003 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 "../../src/include/utils.h"
+
+#include <tqpainter.h>
+#include <tqimage.h>
+#include <tqpixmap.h>
+#include <kimageeffect.h> // fading, blending, ...
+#include <kpixmapio.h> // fast conversion between TQPixmap/TQImage
+#include "radioview_frequencyradio.h"
+#include "displaycfg.h"
+
+RadioViewFrequencyRadio::RadioViewFrequencyRadio(TQWidget *parent, const TQString &name )
+ : RadioViewElement(parent, name, clsRadioDisplay),
+ m_power(false),
+ m_valid(false),
+ m_frequency(0),
+ m_quality(0.0),
+ m_stereo(false)
+{
+ setFrameStyle(Box | Sunken);
+ setLineWidth(1);
+ setMidLineWidth(1);
+
+
+ // set some sensless default colors
+ // real values are read in restoreState
+ setDisplayColors(TQColor(20, 244, 20),
+ TQColor(10, 117, 10).light(75),
+ TQColor(10, 117, 10));
+ setDisplayFont(TQFont("Helvetica"));
+
+}
+
+
+RadioViewFrequencyRadio::~RadioViewFrequencyRadio(){
+}
+
+
+float RadioViewFrequencyRadio::getUsability (Interface *i) const
+{
+ if (dynamic_cast<IFrequencyRadio*>(i))
+ return 1.0;
+ else
+ return 0.0;
+}
+
+
+void RadioViewFrequencyRadio::saveState (TDEConfig *config) const
+{
+ config->writeEntry("frequency-view-colorActiveText", m_colorActiveText);
+ config->writeEntry("frequency-view-colorInactiveText", m_colorInactiveText);
+ config->writeEntry("frequency-view-colorButton", m_colorButton);
+ config->writeEntry("frequency-view-font", m_font);
+}
+
+
+void RadioViewFrequencyRadio::restoreState (TDEConfig *config)
+{
+ TQColor defaultActive (20, 244, 20),
+ defaultInactive(TQColor(10, 117, 10).light(75)),
+ defaultButton (10, 117, 10);
+ TQFont defaultFont ("Helvetica");
+ TQColor a, b, c;
+ TQFont f;
+ a = config->readColorEntry ("frequency-view-colorActiveText",
+ &defaultActive);
+ b = config->readColorEntry ("frequency-view-colorInactiveText",
+ &defaultInactive);
+ c = config->readColorEntry ("frequency-view-colorButton",
+ &defaultButton);
+ f = config->readFontEntry ("frequency-view-font",
+ &defaultFont);
+ setDisplayColors(a, b, c);
+ setDisplayFont(f);
+}
+
+
+ConfigPageInfo RadioViewFrequencyRadio::createConfigurationPage()
+{
+ DisplayConfiguration *a = new DisplayConfiguration(NULL);
+ connectI(a);
+ return ConfigPageInfo (a,
+ i18n("Frequency Display"),
+ i18n("Frequency Display"),
+ TQString()
+ );
+}
+
+
+// Interface
+
+bool RadioViewFrequencyRadio::connectI(Interface *i)
+{
+ bool o = IDisplayCfg::connectI(i);
+ bool c = ISoundStreamClient::connectI(i);
+ if (dynamic_cast<IFrequencyRadio *>(i)) {
+
+ bool a = IRadioDeviceClient::connectI(i);
+ bool b = IFrequencyRadioClient::connectI(i);
+ return o || a || b || c;
+
+ } else {
+ return o || c;
+ }
+}
+
+
+bool RadioViewFrequencyRadio::disconnectI(Interface *i)
+{
+ // no check for IFrequencyRadio, it's just a disconnect
+
+ bool a = IRadioDeviceClient::disconnectI(i);
+ bool b = IFrequencyRadioClient::disconnectI(i);
+ bool c = ISoundStreamClient::disconnectI(i);
+ bool o = IDisplayCfg::disconnectI(i);
+
+ return a || b || c || o;
+}
+
+void RadioViewFrequencyRadio::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid)
+{
+ ISoundStreamClient::noticeConnectedI(s, pointer_valid);
+ if (s && pointer_valid) {
+ s->register4_notifySignalQualityChanged(this);
+ s->register4_notifyStereoChanged(this);
+ }
+}
+
+// IDisplayCfg
+
+bool RadioViewFrequencyRadio::setDisplayColors(const TQColor &activeText,
+ const TQColor &inactiveText,
+ const TQColor &button)
+{
+ bool change = (activeText != m_colorActiveText || inactiveText != m_colorInactiveText || button != m_colorButton);
+
+ m_colorActiveText = activeText;
+ m_colorInactiveText = inactiveText;
+ m_colorButton = button;
+
+ TQPalette pl = palette();
+ TQColorGroup cg = pl.inactive();
+
+ TQBrush fg = cg.brush(TQColorGroup::Foreground),
+ btn = cg.brush(TQColorGroup::Button),
+ lgt = cg.brush(TQColorGroup::Light),
+ drk = cg.brush(TQColorGroup::Dark),
+ mid = cg.brush(TQColorGroup::Mid),
+ txt = cg.brush(TQColorGroup::Text),
+ btx = cg.brush(TQColorGroup::BrightText),
+ bas = cg.brush(TQColorGroup::Base),
+ bg = cg.brush(TQColorGroup::Background);
+
+ fg.setColor (m_colorActiveText);
+ btn.setColor(m_colorButton);
+ lgt.setColor(m_colorButton.light(180));
+ drk.setColor(m_colorButton.light( 50));
+ mid.setColor(m_colorInactiveText);
+ txt.setColor(m_colorActiveText);
+ btx.setColor(m_colorActiveText);
+ bas.setColor(m_colorButton);
+ bg.setColor (m_colorButton);
+
+ TQColorGroup ncg(fg, btn, lgt, drk, mid, txt, btx, bas, bg);
+ pl.setInactive(ncg);
+ pl.setActive(ncg);
+ setPalette(pl);
+
+ if (parentWidget() && parentWidget()->backgroundPixmap() ){
+ KPixmapIO io;
+ TQImage i = io.convertToImage(*parentWidget()->backgroundPixmap());
+ KImageEffect::fade(i, 0.5, colorGroup().color(TQColorGroup::Dark));
+ setPaletteBackgroundPixmap(io.convertToPixmap(i));
+ setBackgroundOrigin(WindowOrigin);
+ } else {
+ setBackgroundColor(colorGroup().color(TQColorGroup::Button));
+ }
+
+ if (change)
+ notifyDisplayColorsChanged(m_colorActiveText, m_colorInactiveText, m_colorButton);
+ return true;
+}
+
+bool RadioViewFrequencyRadio::setDisplayFont (const TQFont &f)
+{
+ if (m_font != f) {
+ m_font = f;
+ notifyDisplayFontChanged(m_font);
+ RadioViewElement::setFont(f);
+ }
+ return true;
+}
+
+// IRadioDeviceClient
+
+
+bool RadioViewFrequencyRadio::noticePowerChanged (bool on, const IRadioDevice */*sender*/)
+{
+ m_power = on;
+
+ SoundStreamID ssid = queryCurrentSoundStreamID();
+ float q = 0.0;
+ bool s = false;
+ querySignalQuality(ssid, q);
+ noticeSignalQualityChanged(ssid, q);
+ queryIsStereo(ssid, s);
+ noticeStereoChanged(ssid, s);
+
+ repaint();
+ return true;
+}
+
+
+bool RadioViewFrequencyRadio::noticeStationChanged (const RadioStation &, const IRadioDevice */*sender*/)
+{
+ return false; // we don't care
+}
+
+
+bool RadioViewFrequencyRadio::noticeDescriptionChanged (const TQString &, const IRadioDevice */*sender*/)
+{
+ return false; // we don't care
+}
+
+
+// IRadioSoundClient
+
+bool RadioViewFrequencyRadio::noticeSignalQualityChanged(SoundStreamID id, float q)
+{
+ if (queryCurrentSoundStreamID() != id)
+ return false;
+ m_quality = q;
+ repaint ();
+ return true;
+}
+
+
+bool RadioViewFrequencyRadio::noticeStereoChanged(SoundStreamID id, bool s)
+{
+ if (queryCurrentSoundStreamID() != id)
+ return false;
+ m_stereo = s;
+ repaint ();
+ return true;
+}
+
+
+
+
+// IFrequencyRadioClient
+
+
+bool RadioViewFrequencyRadio::noticeFrequencyChanged(float f, const RadioStation *)
+{
+ m_frequency = f;
+ repaint ();
+ return true;
+}
+
+
+bool RadioViewFrequencyRadio::noticeMinMaxFrequencyChanged(float /*min*/, float /*max*/)
+{
+ return false; // we don't care
+}
+
+
+bool RadioViewFrequencyRadio::noticeDeviceMinMaxFrequencyChanged(float /*min*/, float /*max*/)
+{
+ return false; // we don't care
+}
+
+
+bool RadioViewFrequencyRadio::noticeScanStepChanged(float /*s*/)
+{
+ return false; // we don't care
+}
+
+
+
+void RadioViewFrequencyRadio::drawContents(TQPainter *paint)
+{
+ if (!paint) return;
+
+ TQRect r = contentsRect();
+
+ int margin = TQMAX(4, TQMIN(r.width() / 50, r.height() / 50)),
+ tmp = TQMIN(r.height(), (r.width() - 2*margin) / 4),
+ xd_st = TQMIN((r.height() - margin * 2) / 3, tmp/3),
+ xw = TQMIN(tmp / 2, xd_st * 3 / 2),
+ penw = TQMAX(1, xw / 25),
+ xh_st = xd_st,
+ xx_st = r.x() + margin + xw + 2 * margin + penw/2,
+ xy_st = r.y() + margin + penw/2,
+
+ xx_am = xx_st,
+ xy_am = xy_st + xh_st + margin / 2,
+ xh_am = (r.bottom() - margin - xy_am + 1 - margin/2) / 2,
+
+ xx_fm = xx_am,
+ xy_fm = xy_am + xh_am + margin/2,
+ xh_fm = xh_am,
+
+ xh_sg = r.height() - margin * 2,
+ xx_sg = r.x() + margin,
+ xy_sg = r.y() + margin;
+
+ TQPen activePen (colorGroup().color(TQColorGroup::Text), penw);
+ TQPen inactivePen (colorGroup().color(TQColorGroup::Mid), penw);
+ TQBrush activeBrush = colorGroup().brush(TQColorGroup::Text);
+ TQBrush inactiveBrush = colorGroup().brush(TQColorGroup::Mid);
+
+ // draw stereo symbol
+ paint->setPen( (m_stereo && m_power) ? activePen : inactivePen);
+ paint->drawArc((int)xx_st, (int)xy_st,
+ (int)(xd_st - penw), (int)(xd_st - penw),
+ 0, 360*16);
+ paint->drawArc((int)(xx_st + xd_st/2), (int)xy_st,
+ (int)(xd_st - penw), (int)(xd_st - penw),
+ 0, 360*16);
+
+ // draw signal quality symbol
+ float cx = xx_sg,
+ cy = xy_sg,
+ cw = xw,
+ ch = xw;
+
+ float open_a = 30.0;
+ // outer circle
+ paint->setPen( (m_quality > 0.75 && m_power) ? activePen : inactivePen);
+ paint->drawArc((int)rint(cx), (int)rint(cy),
+ (int)rint(cw), (int)rint(ch),
+ (int)(-90+open_a)*16, (int)(360 - 2*open_a)*16
+ );
+
+ // mid circle
+ paint->setPen( (m_quality > 0.50 && m_power) ? activePen : inactivePen);
+ cx += (float)xw/5.0; cy += (float)xw/5.0;
+ cw -= (float)xw/2.5; ch -= (float)xw/2.5;
+ paint->drawArc((int)rint(cx), (int)rint(cy),
+ (int)rint(cw), (int)rint(ch),
+ (int)(-90+open_a)*16, (int)(360 - 2*open_a)*16
+ );
+
+ // inner circle
+ paint->setPen( (m_quality > 0.25 && m_power) ? activePen : inactivePen);
+ cx += (float)xw/5.0; cy += (float)xw/5.0;
+ cw -= (float)xw/2.5; ch -= (float)xw/2.5;
+ paint->drawArc((int)rint(cx), (int)rint(cy),
+ (int)rint(cw), (int)rint(ch),
+ (int)(-90+open_a)*16, (int)(360 - 2*open_a)*16
+ );
+
+ // triangle
+ TQPen tmppen = (m_quality > 0.1 && m_power) ? activePen : inactivePen;
+ tmppen.setWidth(1);
+ paint->setPen(tmppen);
+ paint->setBrush( (m_quality > 0.1 && m_power) ? activeBrush : inactiveBrush);
+ TQPointArray pts(3);
+ pts.setPoint(0, (int)(xx_sg + xw / 4), (int)(xy_sg + xh_sg - penw/2));
+ pts.setPoint(1, (int)(xx_sg + xw *3/4), (int)(xy_sg + xh_sg - penw/2));
+ pts.setPoint(2, (int)(xx_sg + xw / 2), (int)(xy_sg + xw/2 + penw));
+ paint->drawConvexPolygon(pts);
+
+
+
+ // AM/FM display
+
+ TQFont f = m_font;
+ paint->setPen ( (m_frequency <= 10 && m_power) ? activePen : inactivePen);
+ f.setPixelSize(xh_am);
+ paint->setFont(f);
+ paint->drawText(xx_am, xy_am + xh_am - 1, i18n("AM"));
+ int xw_am = TQFontMetrics(f).width(i18n("AM"));
+
+ paint->setPen ( (m_frequency > 10 && m_power) ? activePen : inactivePen);
+ f.setPixelSize(xh_fm);
+ paint->setFont(f);
+ paint->drawText(xx_fm, xy_fm + xh_fm - 1, i18n("FM"));
+ int xw_fm = TQFontMetrics(f).width(i18n("FM"));
+
+ int xx_f = TQMAX(xx_fm + xw_fm, TQMAX(xw_am + xx_am, TQMAX(xx_st + xw, xw + xx_sg))) + margin,
+ xy_f = r.y() + margin,
+ xw_f = r.right() - margin - xx_f + 1,
+ xh_f = r.bottom() - margin - xy_f + 1;
+
+ // Frequency Display
+
+ TQString s;
+ if (m_frequency < 10) {
+ s = i18n("%1 kHz").arg(TDEGlobal::locale()->formatNumber((int)(m_frequency * 1000), 0));
+ } else {
+ s = i18n("%1 MHz").arg(TDEGlobal::locale()->formatNumber(m_frequency, 2));
+ }
+
+ float pxs = xh_f;
+ paint->setPen ( m_power ? activePen : inactivePen);
+ f.setPixelSize((int)pxs);
+ int n = 30;
+ while (1) {
+ TQFontMetrics fm(f);
+ int sw = fm.boundingRect(xx_f, xy_f, xw_f, xh_f, TQt::AlignRight | TQt::AlignVCenter, s).width();
+ if (sw <= xw_f || --n <= 0) break;
+
+ float fact = (float)xw_f / (float)sw;
+ pxs = TQMIN(pxs - 1, pxs * fact);
+ f.setPixelSize(TQMAX(1,(int)pxs));
+ }
+ paint->setFont(f);
+ paint->drawText(xx_f, xy_f, xw_f, xh_f, TQt::AlignRight | TQt::AlignVCenter, s);
+}
+
+
+
+
+
+
+void RadioViewFrequencyRadio::reparent (TQWidget *prnt,
+ WFlags f,
+ const TQPoint &p,
+ bool showIt)
+{
+ RadioViewElement::reparent(prnt, f, p, showIt);
+ setDisplayColors(m_colorActiveText, m_colorInactiveText, m_colorButton);
+}
+
+
+#include "radioview_frequencyradio.moc"
diff --git a/plugins/gui-standard-display/radioview_frequencyradio.h b/plugins/gui-standard-display/radioview_frequencyradio.h
new file mode 100644
index 0000000..fb3bd59
--- /dev/null
+++ b/plugins/gui-standard-display/radioview_frequencyradio.h
@@ -0,0 +1,109 @@
+/***************************************************************************
+ tderadiodisplay.h - description
+ -------------------
+ begin : Mit Jan 29 2003
+ copyright : (C) 2003 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_RADIOVIEW_FREQUENCYRADIO_H
+#define KRADIO_RADIOVIEW_FREQUENCYRADIO_H
+
+#include "../../src/include/radiodevice_interfaces.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+#include "radioview_element.h"
+#include "displaycfg_interfaces.h"
+
+/**
+ *@author Martin Witte
+ */
+
+class RadioViewFrequencyRadio : public RadioViewElement, // is a TQObject, must be first
+ public IRadioDeviceClient,
+ public IFrequencyRadioClient,
+ public ISoundStreamClient,
+ public IDisplayCfg
+{
+Q_OBJECT
+
+public:
+ RadioViewFrequencyRadio(TQWidget *parent, const TQString &name);
+ ~RadioViewFrequencyRadio();
+
+ float getUsability (Interface *) const;
+
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+ ConfigPageInfo createConfigurationPage();
+
+// Interface
+
+ bool connectI (Interface *);
+ bool disconnectI(Interface *);
+
+// IDisplayCfg
+
+RECEIVERS:
+ bool setDisplayColors(const TQColor &activeColor, const TQColor &inactiveColor, const TQColor &bkgnd);
+ bool setDisplayFont (const TQFont &f);
+
+ANSWERS:
+ const TQColor &getDisplayActiveColor() const { return m_colorActiveText; }
+ const TQColor &getDisplayInactiveColor() const { return m_colorInactiveText; }
+ const TQColor &getDisplayBkgndColor() const { return m_colorButton; }
+ const TQFont &getDisplayFont() const { return m_font; }
+
+// IRadioDeviceClient
+RECEIVERS:
+ bool noticePowerChanged (bool on, const IRadioDevice *sender = NULL);
+ bool noticeStationChanged (const RadioStation &, const IRadioDevice *sender = NULL);
+ bool noticeDescriptionChanged (const TQString &, const IRadioDevice *sender = NULL);
+ bool noticeCurrentSoundStreamIDChanged(SoundStreamID /*id*/, const IRadioDevice */*sender*/) { return false; }
+
+// ISoundStreamClient
+RECEIVERS:
+ void noticeConnectedI (ISoundStreamServer *s, bool pointer_valid);
+
+ bool noticeSignalQualityChanged(SoundStreamID id, float q);
+ bool noticeStereoChanged(SoundStreamID id, bool s);
+
+// IFrequencyRadioClient
+RECEIVERS:
+ bool noticeFrequencyChanged(float f, const RadioStation *s);
+ bool noticeMinMaxFrequencyChanged(float min, float max);
+ bool noticeDeviceMinMaxFrequencyChanged(float min, float max);
+ bool noticeScanStepChanged(float s);
+
+// own stuff ;)
+
+public:
+
+ void reparent (TQWidget *parent, WFlags f, const TQPoint &p, bool showIt = FALSE);
+
+protected:
+
+ void drawContents(TQPainter *p);
+
+protected:
+
+ TQColor m_colorActiveText, m_colorInactiveText, m_colorButton;
+ TQFont m_font;
+
+ bool m_power;
+ bool m_valid;
+ float m_frequency;
+ float m_quality;
+ bool m_stereo;
+};
+
+#endif
diff --git a/plugins/gui-standard-display/radioview_frequencyseeker.cpp b/plugins/gui-standard-display/radioview_frequencyseeker.cpp
new file mode 100644
index 0000000..2534dbe
--- /dev/null
+++ b/plugins/gui-standard-display/radioview_frequencyseeker.cpp
@@ -0,0 +1,250 @@
+/***************************************************************************
+ radioview_frequencyseeker.cpp - description
+ -------------------
+ begin : Fre Jun 20 2003
+ copyright : (C) 2003 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 <math.h>
+#include <tqlayout.h>
+#include <tqslider.h>
+#include <tqtoolbutton.h>
+#include <tqaccel.h>
+#include <tqtooltip.h>
+
+#include <kiconloader.h>
+#include <tdelocale.h>
+
+#include "radioview_frequencyseeker.h"
+
+RadioViewFrequencySeeker::RadioViewFrequencySeeker(TQWidget *parent, const TQString &name)
+ : RadioViewElement(parent, name, clsRadioSeek),
+ m_btnSearchLeft(NULL),
+ m_btnStepLeft(NULL),
+ m_btnStepRight(NULL),
+ m_btnSearchRight(NULL),
+ m_sldFrequency(NULL),
+ m_ignoreChanges(false)
+{
+ TQBoxLayout *l = new TQBoxLayout(this, TQBoxLayout::LeftToRight, /*spacing=*/ 3);
+ l->setMargin(0);
+
+ m_sldFrequency = new TQSlider(Qt::Horizontal, this);
+ m_btnSearchLeft = new TQToolButton(this);
+ m_btnSearchRight = new TQToolButton(this);
+ m_btnStepLeft = new TQToolButton(this);
+ m_btnStepRight = new TQToolButton(this);
+
+ m_btnSearchLeft ->setToggleButton(true);
+ m_btnSearchRight->setToggleButton(true);
+ m_sldFrequency->setPageStep(1);
+
+ m_btnSearchLeft ->setIconSet(SmallIconSet("2leftarrow"));
+ m_btnSearchRight->setIconSet(SmallIconSet("2rightarrow"));
+ m_btnStepLeft ->setIconSet(SmallIconSet("1leftarrow"));
+ m_btnStepRight ->setIconSet(SmallIconSet("1rightarrow"));
+
+ l->addWidget (m_btnSearchLeft);
+ l->addWidget (m_btnStepLeft);
+ l->addWidget (m_sldFrequency);
+ l->addWidget (m_btnStepRight);
+ l->addWidget (m_btnSearchRight);
+
+ TQObject::connect(m_sldFrequency, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotSliderChanged(int)));
+ TQObject::connect(m_btnSearchLeft, TQT_SIGNAL(toggled(bool)),
+ this, TQT_SLOT(slotSearchLeft(bool)));
+ TQObject::connect(m_btnSearchRight, TQT_SIGNAL(toggled(bool)),
+ this, TQT_SLOT(slotSearchRight(bool)));
+ TQObject::connect(m_btnStepLeft, TQT_SIGNAL(clicked()),
+ m_sldFrequency, TQT_SLOT(subtractStep()));
+ TQObject::connect(m_btnStepRight, TQT_SIGNAL(clicked()),
+ m_sldFrequency, TQT_SLOT(addStep()));
+
+ // Tooltips
+
+ TQToolTip::add(m_btnSearchLeft, i18n("Search for previous Radio Station"));
+ TQToolTip::add(m_btnSearchRight, i18n("Search for next Radio Station"));
+ TQToolTip::add(m_btnStepLeft, i18n("Decrement Frequency"));
+ TQToolTip::add(m_btnStepRight, i18n("Increment Frequency"));
+ TQToolTip::add(m_sldFrequency, i18n("Change Frequency"));
+
+ // Accelerators
+
+ TQAccel *Accel = new TQAccel (this);
+ Accel->insertItem (Key_Left, 100);
+ Accel->insertItem (Key_Right, 101);
+ Accel->connectItem (100, m_sldFrequency, TQT_SLOT(subtractStep()));
+ Accel->connectItem (101, m_sldFrequency, TQT_SLOT(addStep()));
+}
+
+
+RadioViewFrequencySeeker::~RadioViewFrequencySeeker()
+{
+}
+
+
+float RadioViewFrequencySeeker::getUsability (Interface *i) const
+{
+ if (dynamic_cast<IFrequencyRadio*>(i))
+ return 0.9;
+ else
+ return 0.0;
+}
+
+
+// Interface
+
+bool RadioViewFrequencySeeker::connectI (Interface *i)
+{
+ if (IFrequencyRadioClient::connectI(i)) {
+ ISeekRadioClient::connectI(i);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool RadioViewFrequencySeeker::disconnectI(Interface *i)
+{
+ bool a = IFrequencyRadioClient::disconnectI(i);
+ bool b = ISeekRadioClient::disconnectI(i);
+ return a || b;
+}
+
+
+
+// ISeekRadioClient
+
+bool RadioViewFrequencySeeker::noticeSeekStarted (bool up)
+{
+ m_ignoreChanges = true;
+ m_btnSearchLeft->setOn(!up);
+ m_btnSearchRight->setOn(up);
+ m_ignoreChanges = false;
+ return true;
+}
+
+
+bool RadioViewFrequencySeeker::noticeSeekStopped ()
+{
+ m_ignoreChanges = true;
+ m_btnSearchLeft->setOn(false);
+ m_btnSearchRight->setOn(false);
+ m_ignoreChanges = false;
+ return true;
+}
+
+
+bool RadioViewFrequencySeeker::noticeSeekFinished (const RadioStation &/*s*/, bool /*goodQuality*/)
+{
+ m_ignoreChanges = true;
+ m_btnSearchLeft->setOn(false);
+ m_btnSearchRight->setOn(false);
+ m_ignoreChanges = false;
+ return true;
+}
+
+
+
+// IFrequencyRadioClient
+
+bool RadioViewFrequencySeeker::noticeFrequencyChanged(float f, const RadioStation */*s*/)
+{
+ float step = queryScanStep();
+ if (step == 0) step = 0.000001;
+
+ m_ignoreChanges = true;
+ m_sldFrequency->setValue((int)rint(f / step));
+ m_ignoreChanges = false;
+ return true;
+}
+
+
+bool RadioViewFrequencySeeker::noticeMinMaxFrequencyChanged(float min, float max)
+{
+ float step = queryScanStep();
+ if (step == 0) step = 0.000001;
+
+ m_ignoreChanges = true;
+ m_sldFrequency->setMinValue((int)rint(min / step));
+ m_sldFrequency->setMaxValue((int)rint(max / step));
+ m_sldFrequency->setValue ((int)rint(queryFrequency() / step));
+ m_ignoreChanges = false;
+ return true;
+}
+
+
+bool RadioViewFrequencySeeker::noticeDeviceMinMaxFrequencyChanged(float /*min*/, float /*max*/)
+{
+ return false; // we don't care
+}
+
+
+bool RadioViewFrequencySeeker::noticeScanStepChanged(float s)
+{
+ if (s == 0) s = 0.000001;
+ m_ignoreChanges = true;
+ m_sldFrequency->setMinValue((int)rint(queryMinFrequency() / s));
+ m_sldFrequency->setMaxValue((int)rint(queryMaxFrequency() / s));
+ m_sldFrequency->setValue ((int)rint(queryFrequency() / s));
+ m_ignoreChanges = false;
+ return true;
+}
+
+
+void RadioViewFrequencySeeker::slotSearchLeft(bool on)
+{
+ if (m_ignoreChanges) return;
+ if (on) {
+ if (queryIsSeekUpRunning())
+ sendStopSeek();
+ if (!queryIsSeekRunning())
+ sendStartSeekDown();
+ } else {
+ if (queryIsSeekDownRunning())
+ sendStopSeek();
+ }
+ if (!queryIsSeekDownRunning())
+ m_btnSearchLeft->setOn(false);
+}
+
+
+void RadioViewFrequencySeeker::slotSearchRight(bool on)
+{
+ if (m_ignoreChanges) return;
+ if (on) {
+ if (queryIsSeekDownRunning())
+ sendStopSeek();
+ if (!queryIsSeekRunning())
+ sendStartSeekUp();
+ } else {
+ if (queryIsSeekUpRunning())
+ sendStopSeek();
+ }
+ if (!queryIsSeekUpRunning())
+ m_btnSearchRight->setOn(false);
+}
+
+
+void RadioViewFrequencySeeker::slotSliderChanged(int val)
+{
+ if (m_ignoreChanges) return;
+ sendFrequency(val * queryScanStep());
+}
+
+
+
+
+#include "radioview_frequencyseeker.moc"
diff --git a/plugins/gui-standard-display/radioview_frequencyseeker.h b/plugins/gui-standard-display/radioview_frequencyseeker.h
new file mode 100644
index 0000000..651ef7f
--- /dev/null
+++ b/plugins/gui-standard-display/radioview_frequencyseeker.h
@@ -0,0 +1,79 @@
+/***************************************************************************
+ radioview_frequencyseeker.h - description
+ -------------------
+ begin : Fre Jun 20 2003
+ copyright : (C) 2003 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_RADIOVIEW_FREQUENCYSEEKER_H
+#define KRADIO_RADIOVIEW_FREQUENCYSEEKER_H
+
+#include "../../src/include/radiodevice_interfaces.h"
+#include "radioview_element.h"
+
+class TQToolButton;
+class TQSlider;
+
+class RadioViewFrequencySeeker : public RadioViewElement, // is a TQObject, must be first
+ public ISeekRadioClient,
+ public IFrequencyRadioClient
+{
+Q_OBJECT
+
+public:
+ RadioViewFrequencySeeker(TQWidget *parent, const TQString &name);
+ ~RadioViewFrequencySeeker();
+
+ float getUsability(Interface *) const;
+
+// Interface
+
+ bool connectI (Interface *);
+ bool disconnectI(Interface *);
+
+// ISeekRadioClient
+RECEIVERS:
+ bool noticeSeekStarted (bool up);
+ bool noticeSeekStopped ();
+ bool noticeSeekFinished (const RadioStation &s, bool goodQuality);
+ bool noticeProgress (float ) { return false; }
+
+// IFrequencyRadioClient
+RECEIVERS:
+ bool noticeFrequencyChanged(float f, const RadioStation *s);
+ bool noticeMinMaxFrequencyChanged(float min, float max);
+ bool noticeDeviceMinMaxFrequencyChanged(float min, float max);
+ bool noticeScanStepChanged(float s);
+
+// own stuff ;)
+
+protected slots:
+
+ void slotSearchLeft(bool on);
+ void slotSearchRight(bool on);
+ void slotSliderChanged(int val);
+
+protected:
+
+ TQToolButton *m_btnSearchLeft,
+ *m_btnStepLeft,
+ *m_btnStepRight,
+ *m_btnSearchRight;
+ TQSlider *m_sldFrequency;
+
+ bool m_ignoreChanges;
+};
+
+
+
+#endif
diff --git a/plugins/gui-standard-display/radioview_seekinterface.ui b/plugins/gui-standard-display/radioview_seekinterface.ui
new file mode 100644
index 0000000..29542f9
--- /dev/null
+++ b/plugins/gui-standard-display/radioview_seekinterface.ui
@@ -0,0 +1,167 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>RadioView_SeekerUI</class>
+<author>Ernst Martin Witte</author>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>RadioView_SeekerUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>477</width>
+ <height>43</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>RadioView_SeekInterface</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQToolButton" row="0" column="0">
+ <property name="name">
+ <cstring>btnSearchDown</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>TabFocus</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"2rightarrow"</iconset>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>search previous station</string>
+ </property>
+ </widget>
+ <widget class="TQToolButton" row="0" column="1">
+ <property name="name">
+ <cstring>btnStepDown</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>TabFocus</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="autoRepeat">
+ <bool>true</bool>
+ </property>
+ <property name="iconSet">
+ <iconset>"2rightarrow"</iconset>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>decrease freq. by 0.05 MHz</string>
+ </property>
+ </widget>
+ <widget class="TQSlider" row="0" column="2">
+ <property name="name">
+ <cstring>sldRange</cstring>
+ </property>
+ <property name="minValue">
+ <number>8700</number>
+ </property>
+ <property name="maxValue">
+ <number>10900</number>
+ </property>
+ <property name="lineStep">
+ <number>5</number>
+ </property>
+ <property name="pageStep">
+ <number>5</number>
+ </property>
+ <property name="value">
+ <number>8700</number>
+ </property>
+ <property name="tracking">
+ <bool>true</bool>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="tickmarks">
+ <enum>NoMarks</enum>
+ </property>
+ <property name="tickInterval">
+ <number>100</number>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Frequency control</string>
+ <comment>Frequency</comment>
+ </property>
+ </widget>
+ <widget class="TQToolButton" row="0" column="3">
+ <property name="name">
+ <cstring>btnStepUp</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>TabFocus</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="autoRepeat">
+ <bool>true</bool>
+ </property>
+ <property name="iconSet">
+ <iconset>"2rightarrow"</iconset>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>increase freq. by 0.05 MHz</string>
+ </property>
+ </widget>
+ <widget class="TQToolButton" row="0" column="4">
+ <property name="name">
+ <cstring>btnSearchUp</cstring>
+ </property>
+ <property name="focusPolicy">
+ <enum>TabFocus</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"2rightarrow"</iconset>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>search next station</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>btnSearchDown</tabstop>
+ <tabstop>btnStepDown</tabstop>
+ <tabstop>sldRange</tabstop>
+ <tabstop>btnStepUp</tabstop>
+ <tabstop>btnSearchUp</tabstop>
+</tabstops>
+<includes>
+ <include location="local" impldecl="in implementation">radioview_seekinterface.ui.h</include>
+</includes>
+<functions>
+ <function access="protected">init()</function>
+ <function>destroy()</function>
+</functions>
+<pixmapfunction>SmallIconSet</pixmapfunction>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/plugins/gui-standard-display/radioview_seekinterface.ui.h b/plugins/gui-standard-display/radioview_seekinterface.ui.h
new file mode 100644
index 0000000..c13c945
--- /dev/null
+++ b/plugins/gui-standard-display/radioview_seekinterface.ui.h
@@ -0,0 +1,21 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** TQt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+void RadioView_SeekerUI::init()
+{
+ Accel = new TQAccel (this);
+ Accel->insertItem (Key_Left, 100);
+ Accel->insertItem (Key_Right, 101);
+ Accel->connectItem (100, sldRange, TQT_SLOT(subtractStep()));
+ Accel->connectItem (101, sldRange, TQT_SLOT(addStep()));
+}
+
+void RadioView_SeekerUI::destroy()
+{
+}
diff --git a/plugins/gui-standard-display/radioview_volume.cpp b/plugins/gui-standard-display/radioview_volume.cpp
new file mode 100644
index 0000000..683ef82
--- /dev/null
+++ b/plugins/gui-standard-display/radioview_volume.cpp
@@ -0,0 +1,141 @@
+/***************************************************************************
+ radioview_volume.cpp - description
+ -------------------
+ begin : Don Jun 19 2003
+ copyright : (C) 2003 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 <math.h>
+#include <tqslider.h>
+#include <tqlayout.h>
+#include <tqaccel.h>
+#include <tqtooltip.h>
+
+#include <tdelocale.h>
+
+#include "radioview_volume.h"
+#include "../../src/include/plugins.h"
+
+#define SLIDER_MINVAL 0
+#define SLIDER_MAXVAL 32768
+#define SLIDER_RANGE (SLIDER_MAXVAL - SLIDER_MINVAL)
+
+RadioViewVolume::RadioViewVolume(TQWidget *parent, const TQString &name)
+ : RadioViewElement (parent, name, clsRadioSound),
+ m_slider(NULL),
+ m_handlingSlot(false)
+{
+ float v = 0;
+ SoundStreamID ssid = queryCurrentSoundStreamID();
+ sendLogDebug (TQString ("RadioViewVolume: ssid=%1").arg(ssid.getID()));
+ queryPlaybackVolume(ssid, v);
+ m_slider = new TQSlider(SLIDER_MINVAL,
+ SLIDER_MAXVAL,
+ SLIDER_RANGE/10,
+ getSlider4Volume(v),
+ Qt::Vertical, this);
+
+ TQObject::connect(m_slider, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotVolumeChanged(int)));
+
+ TQBoxLayout *l = new TQBoxLayout(this, TQBoxLayout::LeftToRight);
+ l->addWidget(m_slider);
+
+ // Tooltips
+
+ TQToolTip::add(m_slider, i18n("Change Volume"));
+
+ // Accelerators
+ TQAccel *Accel = new TQAccel (this);
+ Accel->insertItem (Key_Up, 100);
+ Accel->insertItem (Key_Down, 101);
+ Accel->connectItem (100, m_slider, TQT_SLOT(subtractStep()));
+ Accel->connectItem (101, m_slider, TQT_SLOT(addStep()));
+
+}
+
+
+RadioViewVolume::~RadioViewVolume()
+{
+}
+
+
+float RadioViewVolume::getUsability (Interface */*i*/) const
+{
+ return 0.5; // there could be more features like mute control, capture settings, ...
+}
+
+
+bool RadioViewVolume::connectI (Interface *i)
+{
+ bool a = IRadioDeviceClient::connectI(i);
+ bool b = ISoundStreamClient::connectI(i);
+ return a || b;
+}
+
+
+bool RadioViewVolume::disconnectI(Interface *i)
+{
+ bool a = IRadioDeviceClient::disconnectI(i);
+ bool b = ISoundStreamClient::disconnectI(i);
+ return a || b;
+}
+
+void RadioViewVolume::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid)
+{
+ ISoundStreamClient::noticeConnectedI(s, pointer_valid);
+ if (s && pointer_valid) {
+ s->register4_notifyPlaybackVolumeChanged(this);
+ }
+}
+
+// ISoundStreamClient
+
+bool RadioViewVolume::noticePlaybackVolumeChanged(SoundStreamID id, float v)
+{
+ if (queryCurrentSoundStreamID() != id)
+ return false;
+ m_slider->setValue(getSlider4Volume(v));
+ return true;
+}
+
+
+
+void RadioViewVolume::slotVolumeChanged(int val)
+{
+ if (m_handlingSlot) return;
+ m_handlingSlot = true;
+ SoundStreamID ssid = queryCurrentSoundStreamID();
+ sendPlaybackVolume(ssid, getVolume4Slider(val));
+ m_handlingSlot = false;
+}
+
+
+int RadioViewVolume::getSlider4Volume(float volume)
+{
+ if (volume >= 1) volume = 1;
+ if (volume < 0) volume = 0;
+ return SLIDER_MAXVAL - (int)rint(SLIDER_RANGE * volume);
+}
+
+
+float RadioViewVolume::getVolume4Slider(int sl)
+{
+ if (sl > SLIDER_MAXVAL) sl = SLIDER_MAXVAL;
+ if (sl < SLIDER_MINVAL) sl = SLIDER_MINVAL;
+ return (float)(SLIDER_MAXVAL - sl) / (float)SLIDER_RANGE;
+}
+
+
+
+#include "radioview_volume.moc"
diff --git a/plugins/gui-standard-display/radioview_volume.h b/plugins/gui-standard-display/radioview_volume.h
new file mode 100644
index 0000000..581fc7c
--- /dev/null
+++ b/plugins/gui-standard-display/radioview_volume.h
@@ -0,0 +1,76 @@
+/***************************************************************************
+ radioview_volume.h - description
+ -------------------
+ begin : Don Jun 19 2003
+ copyright : (C) 2003 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_RADIOVIEW_VOLUME_H
+#define KRADIO_RADIOVIEW_VOLUME_H
+
+#include "../../src/include/radiodevice_interfaces.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+#include "radioview_element.h"
+
+/**
+ *@author Martin Witte
+ */
+
+class TQSlider;
+
+class RadioViewVolume : public RadioViewElement, // is a TQObject, must be first
+ public IRadioDeviceClient,
+ public ISoundStreamClient,
+ public IErrorLogClient
+{
+Q_OBJECT
+
+public:
+ RadioViewVolume(TQWidget *parent, const TQString &name);
+ ~RadioViewVolume();
+
+ float getUsability(Interface *) const;
+
+// Interface
+
+ bool connectI (Interface *);
+ bool disconnectI(Interface *);
+
+// IRadioDeviceClient
+RECEIVERS:
+ bool noticePowerChanged (bool /*on*/, const IRadioDevice */*sender*/) { return false; }
+ bool noticeStationChanged (const RadioStation &, const IRadioDevice */*sender*/) { return false; }
+ bool noticeDescriptionChanged (const TQString &, const IRadioDevice */*sender*/) { return false; }
+ bool noticeCurrentSoundStreamIDChanged(SoundStreamID /*id*/, const IRadioDevice */*sender*/) { return false; }
+
+// ISoundStreamClient
+RECEIVERS:
+ void noticeConnectedI (ISoundStreamServer *s, bool pointer_valid);
+ bool noticePlaybackVolumeChanged(SoundStreamID id, float v);
+
+// own stuff
+protected slots:
+
+ void slotVolumeChanged(int val);
+
+protected:
+
+ int getSlider4Volume(float volume);
+ float getVolume4Slider(int sl);
+
+ TQSlider *m_slider;
+ bool m_handlingSlot;
+
+};
+
+#endif
diff --git a/plugins/lirc/CMakeL10n.txt b/plugins/lirc/CMakeL10n.txt
new file mode 100644
index 0000000..e864b38
--- /dev/null
+++ b/plugins/lirc/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-lirc"
+ DESTINATION "po"
+)
diff --git a/plugins/lirc/Makefile.am b/plugins/lirc/Makefile.am
new file mode 100644
index 0000000..1ede5f5
--- /dev/null
+++ b/plugins/lirc/Makefile.am
@@ -0,0 +1,28 @@
+
+SUBDIRS = po .
+
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = liblirc.la
+liblirc_la_SOURCES = lircsupport.cpp lirc-configuration-ui.ui \
+ lirc-configuration.cpp listviewitem_lirc.cpp
+liblirc_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+liblirc_la_LIBADD = $(LIB_LIRC)
+
+noinst_HEADERS = lircsupport.h lirc-configuration.h listviewitem_lirc.h
+
+
+install-data-local:
+ $(mkinstalldirs) "$(DESTDIR)$(kde_datadir)/tderadio/"
+ $(INSTALL_DATA) "$(srcdir)/default-dot-lircrc" "$(DESTDIR)$(kde_datadir)/tderadio/default-dot-lircrc"
+
+uninstall-local:
+ -rm -f "$(DESTDIR)$(kde_datadir)/tderadio/default-dot-lircrc"
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-lirc.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-lirc.pot
diff --git a/plugins/lirc/default-dot-lircrc b/plugins/lirc/default-dot-lircrc
new file mode 100644
index 0000000..0462104
--- /dev/null
+++ b/plugins/lirc/default-dot-lircrc
@@ -0,0 +1,6 @@
+
+begin
+ prog = tderadio
+ config = eventmap
+ repeat = 1
+end
diff --git a/plugins/lirc/lirc-configuration-ui.ui b/plugins/lirc/lirc-configuration-ui.ui
new file mode 100644
index 0000000..ca0ce59
--- /dev/null
+++ b/plugins/lirc/lirc-configuration-ui.ui
@@ -0,0 +1,110 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>LIRCConfigurationUI</class>
+<author>Ernst Martin Witte</author>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>LIRCConfigurationUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>585</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>LIRCConfigurationUI</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TDEListView" row="0" column="0">
+ <column>
+ <property name="text">
+ <string>Action</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>LIRC String</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Alternative LIRC String</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_ActionList</cstring>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="itemMargin">
+ <number>2</number>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>AllColumns</enum>
+ </property>
+ <property name="defaultRenameAction">
+ <enum>Accept</enum>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="Line" row="1" column="0">
+ <property name="name">
+ <cstring>line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>m_LabelHints</cstring>
+ </property>
+ <property name="text">
+ <string>textLabel1</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<pixmapfunction>SmallIconSet</pixmapfunction>
+<layoutdefaults spacing="6" margin="0"/>
+<includes>
+ <include location="global" impldecl="in implementation">tdelistview.h</include>
+</includes>
+</UI>
diff --git a/plugins/lirc/lirc-configuration.cpp b/plugins/lirc/lirc-configuration.cpp
new file mode 100644
index 0000000..470b2ff
--- /dev/null
+++ b/plugins/lirc/lirc-configuration.cpp
@@ -0,0 +1,193 @@
+/***************************************************************************
+ lirc-configuration.cpp - description
+ -------------------
+ begin : Sat May 21 2005
+ copyright : (C) 2005 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 <tdelistview.h>
+#include <tdelocale.h>
+
+#include <tqlistview.h>
+#include <tqlabel.h>
+
+#include "lirc-configuration.h"
+#include "lircsupport.h"
+#include "listviewitem_lirc.h"
+
+LIRCConfiguration::LIRCConfiguration (TQWidget *parent, LircSupport *dev)
+ : LIRCConfigurationUI(parent),
+ m_LIRC (dev),
+ m_dirty(true),
+ m_ignore_gui_updates(false)
+{
+ m_descriptions[LIRC_DIGIT_0] = i18n("digit 0");
+ m_descriptions[LIRC_DIGIT_1] = i18n("digit 1");
+ m_descriptions[LIRC_DIGIT_2] = i18n("digit 2");
+ m_descriptions[LIRC_DIGIT_3] = i18n("digit 3");
+ m_descriptions[LIRC_DIGIT_4] = i18n("digit 4");
+ m_descriptions[LIRC_DIGIT_5] = i18n("digit 5");
+ m_descriptions[LIRC_DIGIT_6] = i18n("digit 6");
+ m_descriptions[LIRC_DIGIT_7] = i18n("digit 7");
+ m_descriptions[LIRC_DIGIT_8] = i18n("digit 8");
+ m_descriptions[LIRC_DIGIT_9] = i18n("digit 9");
+ m_descriptions[LIRC_POWER_ON] = i18n("Power On");
+ m_descriptions[LIRC_POWER_OFF] = i18n("Power Off");
+ m_descriptions[LIRC_PAUSE] = i18n("Pause");
+ m_descriptions[LIRC_RECORD_START] = i18n("Start Recording");
+ m_descriptions[LIRC_RECORD_STOP] = i18n("Stop Recording");
+ m_descriptions[LIRC_VOLUME_INC] = i18n("Increase Volume");
+ m_descriptions[LIRC_VOLUME_DEC] = i18n("Decrease Volume");
+ m_descriptions[LIRC_CHANNEL_NEXT] = i18n("Next Channel");
+ m_descriptions[LIRC_CHANNEL_PREV] = i18n("Previous Channel");
+ m_descriptions[LIRC_SEARCH_NEXT] = i18n("Search Next Channel");
+ m_descriptions[LIRC_SEARCH_PREV] = i18n("Search Previous Channel");
+ m_descriptions[LIRC_SLEEP] = i18n("Enable Sleep Countdown");
+ m_descriptions[LIRC_APPLICATION_QUIT] = i18n("Quit TDERadio");
+
+ int k = 0;
+ m_order[k++] = LIRC_DIGIT_0;
+ m_order[k++] = LIRC_DIGIT_1;
+ m_order[k++] = LIRC_DIGIT_2;
+ m_order[k++] = LIRC_DIGIT_3;
+ m_order[k++] = LIRC_DIGIT_4;
+ m_order[k++] = LIRC_DIGIT_5;
+ m_order[k++] = LIRC_DIGIT_6;
+ m_order[k++] = LIRC_DIGIT_7;
+ m_order[k++] = LIRC_DIGIT_8;
+ m_order[k++] = LIRC_DIGIT_9;
+ m_order[k++] = LIRC_POWER_ON;
+ m_order[k++] = LIRC_POWER_OFF;
+ m_order[k++] = LIRC_PAUSE;
+ m_order[k++] = LIRC_RECORD_START;
+ m_order[k++] = LIRC_RECORD_STOP;
+ m_order[k++] = LIRC_VOLUME_INC;
+ m_order[k++] = LIRC_VOLUME_DEC;
+ m_order[k++] = LIRC_CHANNEL_NEXT;
+ m_order[k++] = LIRC_CHANNEL_PREV;
+ m_order[k++] = LIRC_SEARCH_NEXT;
+ m_order[k++] = LIRC_SEARCH_PREV;
+ m_order[k++] = LIRC_SLEEP;
+ m_order[k++] = LIRC_APPLICATION_QUIT;
+
+ m_ActionList->setSorting(-1);
+ m_ActionList->setColumnWidthMode(0, TQListView::Maximum);
+ m_ActionList->setColumnWidthMode(1, TQListView::Maximum);
+ m_ActionList->setColumnWidthMode(2, TQListView::Maximum);
+
+ connect(m_ActionList, TQT_SIGNAL(itemRenamed(TQListViewItem*, int)), this, TQT_SLOT(slotSetDirty()));
+ slotCancel();
+}
+
+
+LIRCConfiguration::~LIRCConfiguration ()
+{
+}
+
+
+void LIRCConfiguration::slotOK()
+{
+ if (m_dirty && m_LIRC) {
+ TQListViewItem *item = m_ActionList->firstChild();
+
+ TQMap<LIRC_Actions, TQString> actions;
+ TQMap<LIRC_Actions, TQString> alt_actions;
+
+ for (int i = 0; item; ++i, item = item->nextSibling()) {
+ LIRC_Actions action = m_order[i];
+ actions[action] = item->text(1);
+ alt_actions[action] = item->text(2);
+ }
+ m_LIRC->setActions(actions, alt_actions);
+ }
+ m_dirty = false;
+}
+
+
+void LIRCConfiguration::slotCancel()
+{
+ if (m_dirty) {
+ m_ignore_gui_updates = true;
+ m_ActionList->clear();
+ if (m_LIRC) {
+ const TQMap<LIRC_Actions, TQString> &actions = m_LIRC->getActions();
+ const TQMap<LIRC_Actions, TQString> &alt_actions = m_LIRC->getAlternativeActions();
+
+ for (unsigned i = 0; m_order.contains(i) && i < m_order.count(); ++i) {
+ LIRC_Actions action = m_order[i];
+ addKey(m_descriptions[action], actions[action], alt_actions[action]);
+ }
+ }
+
+ slotRenamingStopped(NULL, -1);
+ m_ignore_gui_updates = false;
+ }
+ m_dirty = false;
+}
+
+
+void LIRCConfiguration::addKey(const TQString &descr, const TQString &key, const TQString &alt_key)
+{
+ ListViewItemLirc *item = new ListViewItemLirc(m_ActionList, m_ActionList->lastChild());
+ if (item) {
+ TQObject::connect(item, TQT_SIGNAL(sigRenamingStarted (ListViewItemLirc *, int)),
+ this, TQT_SLOT (slotRenamingStarted(ListViewItemLirc *, int)));
+ TQObject::connect(item, TQT_SIGNAL(sigRenamingStopped (ListViewItemLirc *, int)),
+ this, TQT_SLOT (slotRenamingStopped(ListViewItemLirc *, int)));
+ item->setText(0, descr);
+ item->setText(1, key);
+ item->setText(2, alt_key);
+ item->setRenameEnabled(1, true);
+ item->setRenameEnabled(2, true);
+ }
+}
+
+void LIRCConfiguration::slotUpdateConfig()
+{
+ slotSetDirty();
+ slotCancel();
+}
+
+void LIRCConfiguration::slotRawLIRCSignal(const TQString &val, int /*repeat_counter*/, bool &consumed)
+{
+ TQListViewItem *_it = m_ActionList->currentItem();
+ ListViewItemLirc *it = static_cast<ListViewItemLirc*>(_it);
+ if (it->isRenamingInProcess()) {
+ int col = it->getRenamingColumn();
+ it->cancelRename(col);
+ it->setText(col, val);
+ consumed = true;
+ m_dirty = true;
+ }
+}
+
+void LIRCConfiguration::slotRenamingStarted(ListViewItemLirc */*sender*/, int /*col*/)
+{
+ m_LabelHints->setText(i18n("Enter the key string of your remote or just press the button on your remote control"));
+}
+
+
+void LIRCConfiguration::slotRenamingStopped(ListViewItemLirc */*sender*/, int /*col*/)
+{
+ m_LabelHints->setText(i18n("Double Click on the entries to change the assignments"));
+}
+
+
+void LIRCConfiguration::slotSetDirty()
+{
+ if (!m_ignore_gui_updates) {
+ m_dirty = true;
+ }
+}
+
+#include "lirc-configuration.moc"
diff --git a/plugins/lirc/lirc-configuration.h b/plugins/lirc/lirc-configuration.h
new file mode 100644
index 0000000..70c1ae2
--- /dev/null
+++ b/plugins/lirc/lirc-configuration.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ lirc-configuration.h - description
+ -------------------
+ begin : Sat May 21 2005
+ copyright : (C) 2005 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_LIRC_CONFIGURATION_H
+#define KRADIO_LIRC_CONFIGURATION_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "lirc-configuration-ui.h"
+#include "lircsupport.h"
+#include "listviewitem_lirc.h"
+
+class LIRCConfiguration : public LIRCConfigurationUI
+{
+Q_OBJECT
+
+public :
+ LIRCConfiguration (TQWidget *parent, LircSupport *);
+ ~LIRCConfiguration ();
+
+protected slots:
+
+ void slotOK();
+ void slotCancel();
+ void slotSetDirty();
+
+ void slotUpdateConfig();
+ void slotRawLIRCSignal(const TQString &val, int repeat_counter, bool &consumed);
+
+ void slotRenamingStarted(ListViewItemLirc *, int);
+ void slotRenamingStopped(ListViewItemLirc *, int);
+
+protected:
+ void addKey(const TQString &descr, const TQString &key, const TQString &alt_key);
+
+ LircSupport *m_LIRC;
+
+ TQMap<int, LIRC_Actions> m_order;
+ TQMap<LIRC_Actions, TQString> m_descriptions;
+
+ bool m_dirty;
+ bool m_ignore_gui_updates;
+};
+
+#endif
diff --git a/plugins/lirc/lircsupport.cpp b/plugins/lirc/lircsupport.cpp
new file mode 100644
index 0000000..8fef92f
--- /dev/null
+++ b/plugins/lirc/lircsupport.cpp
@@ -0,0 +1,553 @@
+/***************************************************************************
+ lircsupport.cpp - description
+ -------------------
+ begin : Mon Feb 4 2002
+ copyright : (C) 2002 by Martin Witte / Frank Schwanz
+ email : witte@kawo1.rwth-aachen.de / schwanz@fh-brandenburg.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 "lircsupport.h"
+
+#ifdef HAVE_LIRC
+#include <lirc/lirc_client.h>
+#endif
+
+#include <tqsocketnotifier.h>
+#include <tqtimer.h>
+#include <tqfile.h>
+
+#include <tdeapplication.h>
+#include <tdeaboutdata.h>
+#include <kstandarddirs.h>
+
+#include "../../src/include/errorlog-interfaces.h"
+#include "../../src/include/radiodevice_interfaces.h"
+#include "../../src/include/stationlist.h"
+#include "../../src/include/aboutwidget.h"
+
+#include "lirc-configuration.h"
+
+#include <cstdlib>
+
+#define LIRCRC ".lircrc"
+
+///////////////////////////////////////////////////////////////////////
+//// plugin library functions
+
+//#ifdef HAVE_LIRC
+PLUGIN_LIBRARY_FUNCTIONS(LircSupport, "tderadio-lirc", i18n("Linux Infrared Control (LIRC) Support"));
+//#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+LircSupport::LircSupport(const TQString &name)
+ : PluginBase(name, i18n("LIRC Plugin")),
+ m_TakeRawLIRC(false)
+{
+
+#ifdef HAVE_LIRC
+ logDebug(i18n("initializing tderadio lirc plugin"));
+ fprintf (stderr, "%s\n", (const char*)i18n("initializing tderadio lirc plugin").utf8());
+ char *prg = (char*)"tderadio";
+
+ TQString slircrc = getenv("HOME");
+ slircrc += "/" LIRCRC;
+
+ TQFile lircrc(slircrc);
+ if (!lircrc.exists()) {
+ logWarning(i18n("%1 does not exist. File was created with TDERadio's default .lircrc proposal").arg(LIRCRC));
+ TQFile default_lircrc(locate("data", "tderadio/default-dot-lircrc"));
+ lircrc.open(IO_WriteOnly);
+ default_lircrc.open(IO_ReadOnly);
+ char *buf = new char [default_lircrc.size() + 1];
+ default_lircrc.readBlock(buf, default_lircrc.size());
+ lircrc.writeBlock(buf, default_lircrc.size());
+ lircrc.close();
+ default_lircrc.close();
+ delete buf;
+ }
+
+ m_fd_lirc = lirc_init(prg, 1);
+ m_lirc_notify = 0;
+ m_lircConfig = 0;
+
+ if (m_fd_lirc != -1) {
+ if (lirc_readconfig (NULL, &m_lircConfig, NULL) == 0) {
+ m_lirc_notify = new TQSocketNotifier(m_fd_lirc, TQSocketNotifier::Read, this, "lirc_notifier");
+ if (m_lirc_notify)
+ TQObject::connect(m_lirc_notify, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotLIRC(int)));
+
+ // check config
+ lirc_config_entry *found = NULL;
+ for (lirc_config_entry *e = m_lircConfig->first; e; e = e->next) {
+ if (TQString(e->prog) == prg)
+ found = e;
+ }
+ if (!found) {
+ logWarning(i18n("There is no entry for tderadio in any of your .lircrc files."));
+ logWarning(i18n("Please setup your .lircrc files correctly."));
+ m_TakeRawLIRC = true;
+ }
+
+ } else {
+ lirc_deinit();
+ m_fd_lirc = -1;
+ }
+ }
+
+ if (m_fd_lirc == -1) {
+ logWarning(i18n("Initializing tderadio lirc plugin failed"));
+ fprintf (stderr, "%s\n", (const char*)i18n("Initializing tderadio lirc plugin failed").utf8());
+ } else {
+ logDebug(i18n("Initializing tderadio lirc plugin successful"));
+ fprintf (stderr, "%s\n", (const char*)i18n("Initializing tderadio lirc plugin successful").utf8());
+ }
+#endif
+
+ m_kbdTimer = new TQTimer (this);
+ TQObject::connect (m_kbdTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotKbdTimedOut()));
+
+ m_addIndex = 0;
+}
+
+
+LircSupport::~LircSupport()
+{
+#ifdef HAVE_LIRC
+ if (m_fd_lirc != -1)
+ lirc_deinit();
+ if (m_lircConfig)
+ lirc_freeconfig(m_lircConfig);
+ m_fd_lirc = -1;
+ m_lircConfig = 0;
+#endif
+}
+
+
+void LircSupport::slotLIRC(int /*socket*/ )
+{
+#ifdef HAVE_LIRC
+ if (!m_lircConfig || !m_lirc_notify || m_fd_lirc == -1)
+ return;
+
+ char *code = 0, *c = 0;
+ if (lirc_nextcode(&code) == 0) {
+ while(m_TakeRawLIRC || (lirc_code2char (m_lircConfig, code, &c) == 0 && c != NULL)) {
+
+ TQString x = c;
+ int repeat_counter = 1;
+ if (m_TakeRawLIRC || (TQString(c) == "eventmap")) {
+ TQStringList l = TQStringList::split(" ", code);
+ if (l.count() >=4) {
+ x = l[2];
+ repeat_counter = l[1].toInt(NULL, 16);
+ }
+ }
+
+ bool consumed = false;
+ logDebug(TQString("LIRC: ") + x);
+
+ emit sigRawLIRCSignal(x, repeat_counter, consumed);
+
+ if (!consumed) {
+ if (!checkActions(x, repeat_counter, m_Actions))
+ checkActions(x, repeat_counter, m_AlternativeActions);
+ }
+ }
+ }
+ else {
+ // some error has occurred on the socket => close lirc plugin
+ logWarning(i18n("Reading from LIRC socket failed. Disabling LIRC Functions till next start of tderadio"));
+ delete m_lirc_notify;
+ m_lirc_notify = NULL;
+ }
+
+ if (code)
+ free (code);
+#endif
+}
+
+
+void LircSupport::slotKbdTimedOut()
+{
+ activateStation (m_addIndex);
+ m_addIndex = 0;
+}
+
+
+void LircSupport::activateStation (int i)
+{
+ if (! sendActivateStation(i - 1))
+ sendActivateStation( (i + 9) % 10);
+}
+
+
+bool LircSupport::connectI (Interface *i)
+{
+ bool a = IRadioClient::connectI (i);
+ bool b = ITimeControlClient::connectI (i);
+ bool c = IRadioDevicePoolClient::connectI (i);
+ bool d = PluginBase::connectI(i);
+ bool e = ISoundStreamClient::connectI(i);
+ return a || b || c || d || e;
+}
+
+
+bool LircSupport::disconnectI (Interface *i)
+{
+ bool a = IRadioClient::disconnectI (i);
+ bool b = ITimeControlClient::disconnectI (i);
+ bool c = IRadioDevicePoolClient::disconnectI (i);
+ bool d = PluginBase::disconnectI(i);
+ bool e = ISoundStreamClient::disconnectI(i);
+ return a || b || c || d || e;
+}
+
+
+
+void LircSupport::saveState (TDEConfig *c) const
+{
+ c->writeEntry("LIRC_DIGIT_0", m_Actions[LIRC_DIGIT_0]);
+ c->writeEntry("LIRC_DIGIT_1", m_Actions[LIRC_DIGIT_1]);
+ c->writeEntry("LIRC_DIGIT_2", m_Actions[LIRC_DIGIT_2]);
+ c->writeEntry("LIRC_DIGIT_3", m_Actions[LIRC_DIGIT_3]);
+ c->writeEntry("LIRC_DIGIT_4", m_Actions[LIRC_DIGIT_4]);
+ c->writeEntry("LIRC_DIGIT_5", m_Actions[LIRC_DIGIT_5]);
+ c->writeEntry("LIRC_DIGIT_6", m_Actions[LIRC_DIGIT_6]);
+ c->writeEntry("LIRC_DIGIT_7", m_Actions[LIRC_DIGIT_7]);
+ c->writeEntry("LIRC_DIGIT_8", m_Actions[LIRC_DIGIT_8]);
+ c->writeEntry("LIRC_DIGIT_9", m_Actions[LIRC_DIGIT_9]);
+ c->writeEntry("LIRC_POWER_ON", m_Actions[LIRC_POWER_ON]);
+ c->writeEntry("LIRC_POWER_OFF", m_Actions[LIRC_POWER_OFF]);
+ c->writeEntry("LIRC_PAUSE", m_Actions[LIRC_PAUSE]);
+ c->writeEntry("LIRC_RECORD_START", m_Actions[LIRC_RECORD_START]);
+ c->writeEntry("LIRC_RECORD_STOP", m_Actions[LIRC_RECORD_STOP]);
+ c->writeEntry("LIRC_VOLUME_INC", m_Actions[LIRC_VOLUME_INC]);
+ c->writeEntry("LIRC_VOLUME_DEC", m_Actions[LIRC_VOLUME_DEC]);
+ c->writeEntry("LIRC_CHANNEL_NEXT", m_Actions[LIRC_CHANNEL_NEXT]);
+ c->writeEntry("LIRC_CHANNEL_PREV", m_Actions[LIRC_CHANNEL_PREV]);
+ c->writeEntry("LIRC_SEARCH_NEXT", m_Actions[LIRC_SEARCH_NEXT]);
+ c->writeEntry("LIRC_SEARCH_PREV", m_Actions[LIRC_SEARCH_PREV]);
+ c->writeEntry("LIRC_SLEEP", m_Actions[LIRC_SLEEP]);
+ c->writeEntry("LIRC_APPLICATION_QUIT", m_Actions[LIRC_APPLICATION_QUIT]);
+
+
+ c->writeEntry("ALT_LIRC_DIGIT_0", m_AlternativeActions[LIRC_DIGIT_0]);
+ c->writeEntry("ALT_LIRC_DIGIT_1", m_AlternativeActions[LIRC_DIGIT_1]);
+ c->writeEntry("ALT_LIRC_DIGIT_2", m_AlternativeActions[LIRC_DIGIT_2]);
+ c->writeEntry("ALT_LIRC_DIGIT_3", m_AlternativeActions[LIRC_DIGIT_3]);
+ c->writeEntry("ALT_LIRC_DIGIT_4", m_AlternativeActions[LIRC_DIGIT_4]);
+ c->writeEntry("ALT_LIRC_DIGIT_5", m_AlternativeActions[LIRC_DIGIT_5]);
+ c->writeEntry("ALT_LIRC_DIGIT_6", m_AlternativeActions[LIRC_DIGIT_6]);
+ c->writeEntry("ALT_LIRC_DIGIT_7", m_AlternativeActions[LIRC_DIGIT_7]);
+ c->writeEntry("ALT_LIRC_DIGIT_8", m_AlternativeActions[LIRC_DIGIT_8]);
+ c->writeEntry("ALT_LIRC_DIGIT_9", m_AlternativeActions[LIRC_DIGIT_9]);
+ c->writeEntry("ALT_LIRC_POWER_ON", m_AlternativeActions[LIRC_POWER_ON]);
+ c->writeEntry("ALT_LIRC_POWER_OFF", m_AlternativeActions[LIRC_POWER_OFF]);
+ c->writeEntry("ALT_LIRC_PAUSE", m_AlternativeActions[LIRC_PAUSE]);
+ c->writeEntry("ALT_LIRC_RECORD_START", m_AlternativeActions[LIRC_RECORD_START]);
+ c->writeEntry("ALT_LIRC_RECORD_STOP", m_AlternativeActions[LIRC_RECORD_STOP]);
+ c->writeEntry("ALT_LIRC_VOLUME_INC", m_AlternativeActions[LIRC_VOLUME_INC]);
+ c->writeEntry("ALT_LIRC_VOLUME_DEC", m_AlternativeActions[LIRC_VOLUME_DEC]);
+ c->writeEntry("ALT_LIRC_CHANNEL_NEXT", m_AlternativeActions[LIRC_CHANNEL_NEXT]);
+ c->writeEntry("ALT_LIRC_CHANNEL_PREV", m_AlternativeActions[LIRC_CHANNEL_PREV]);
+ c->writeEntry("ALT_LIRC_SEARCH_NEXT", m_AlternativeActions[LIRC_SEARCH_NEXT]);
+ c->writeEntry("ALT_LIRC_SEARCH_PREV", m_AlternativeActions[LIRC_SEARCH_PREV]);
+ c->writeEntry("ALT_LIRC_SLEEP", m_AlternativeActions[LIRC_SLEEP]);
+ c->writeEntry("ALT_LIRC_APPLICATION_QUIT", m_AlternativeActions[LIRC_APPLICATION_QUIT]);
+}
+
+void LircSupport::restoreState (TDEConfig *c)
+{
+ m_Actions[LIRC_DIGIT_0] = c->readEntry("LIRC_DIGIT_0", "0");
+ m_Actions[LIRC_DIGIT_1] = c->readEntry("LIRC_DIGIT_1", "1");
+ m_Actions[LIRC_DIGIT_2] = c->readEntry("LIRC_DIGIT_2", "2");
+ m_Actions[LIRC_DIGIT_3] = c->readEntry("LIRC_DIGIT_3", "3");
+ m_Actions[LIRC_DIGIT_4] = c->readEntry("LIRC_DIGIT_4", "4");
+ m_Actions[LIRC_DIGIT_5] = c->readEntry("LIRC_DIGIT_5", "5");
+ m_Actions[LIRC_DIGIT_6] = c->readEntry("LIRC_DIGIT_6", "6");
+ m_Actions[LIRC_DIGIT_7] = c->readEntry("LIRC_DIGIT_7", "7");
+ m_Actions[LIRC_DIGIT_8] = c->readEntry("LIRC_DIGIT_8", "8");
+ m_Actions[LIRC_DIGIT_9] = c->readEntry("LIRC_DIGIT_9", "9");
+ m_Actions[LIRC_POWER_ON] = c->readEntry("LIRC_POWER_ON", "RADIO");
+ m_Actions[LIRC_POWER_OFF] = c->readEntry("LIRC_POWER_OFF", "RADIO");
+ m_Actions[LIRC_PAUSE] = c->readEntry("LIRC_PAUSE", "FULL_SCREEN");
+ m_Actions[LIRC_RECORD_START] = c->readEntry("LIRC_RECORD_START", "");
+ m_Actions[LIRC_RECORD_STOP] = c->readEntry("LIRC_RECORD_STOP", "");
+ m_Actions[LIRC_VOLUME_INC] = c->readEntry("LIRC_VOLUME_INC", "VOL+");
+ m_Actions[LIRC_VOLUME_DEC] = c->readEntry("LIRC_VOLUME_DEC", "VOL-");
+ m_Actions[LIRC_CHANNEL_NEXT] = c->readEntry("LIRC_CHANNEL_NEXT", "CH+");
+ m_Actions[LIRC_CHANNEL_PREV] = c->readEntry("LIRC_CHANNEL_PREV", "CH-");
+ m_Actions[LIRC_SEARCH_NEXT] = c->readEntry("LIRC_SEARCH_NEXT", "SOURCE");
+ m_Actions[LIRC_SEARCH_PREV] = c->readEntry("LIRC_SEARCH_PREV", "MUTE");
+ m_Actions[LIRC_SLEEP] = c->readEntry("LIRC_SLEEP", "MINIMIZE");
+ m_Actions[LIRC_APPLICATION_QUIT] = c->readEntry("LIRC_APPLICATION_QUIT", "");
+
+
+ m_AlternativeActions[LIRC_DIGIT_0] = c->readEntry("ALT_LIRC_DIGIT_0", "");
+ m_AlternativeActions[LIRC_DIGIT_1] = c->readEntry("ALT_LIRC_DIGIT_1", "");
+ m_AlternativeActions[LIRC_DIGIT_2] = c->readEntry("ALT_LIRC_DIGIT_2", "");
+ m_AlternativeActions[LIRC_DIGIT_3] = c->readEntry("ALT_LIRC_DIGIT_3", "");
+ m_AlternativeActions[LIRC_DIGIT_4] = c->readEntry("ALT_LIRC_DIGIT_4", "");
+ m_AlternativeActions[LIRC_DIGIT_5] = c->readEntry("ALT_LIRC_DIGIT_5", "");
+ m_AlternativeActions[LIRC_DIGIT_6] = c->readEntry("ALT_LIRC_DIGIT_6", "");
+ m_AlternativeActions[LIRC_DIGIT_7] = c->readEntry("ALT_LIRC_DIGIT_7", "");
+ m_AlternativeActions[LIRC_DIGIT_8] = c->readEntry("ALT_LIRC_DIGIT_8", "");
+ m_AlternativeActions[LIRC_DIGIT_9] = c->readEntry("ALT_LIRC_DIGIT_9", "");
+ m_AlternativeActions[LIRC_POWER_ON] = c->readEntry("ALT_LIRC_POWER_ON", "");
+ m_AlternativeActions[LIRC_POWER_OFF] = c->readEntry("ALT_LIRC_POWER_OFF", "TV");
+ m_AlternativeActions[LIRC_PAUSE] = c->readEntry("ALT_LIRC_PAUSE", "");
+ m_AlternativeActions[LIRC_RECORD_START] = c->readEntry("ALT_LIRC_RECORD_START", "");
+ m_AlternativeActions[LIRC_RECORD_STOP] = c->readEntry("ALT_LIRC_RECORD_STOP", "");
+ m_AlternativeActions[LIRC_VOLUME_INC] = c->readEntry("ALT_LIRC_VOLUME_INC", "");
+ m_AlternativeActions[LIRC_VOLUME_DEC] = c->readEntry("ALT_LIRC_VOLUME_DEC", "");
+ m_AlternativeActions[LIRC_CHANNEL_NEXT] = c->readEntry("ALT_LIRC_CHANNEL_NEXT", "");
+ m_AlternativeActions[LIRC_CHANNEL_PREV] = c->readEntry("ALT_LIRC_CHANNEL_PREV", "");
+ m_AlternativeActions[LIRC_SEARCH_NEXT] = c->readEntry("ALT_LIRC_SEARCH_NEXT", "");
+ m_AlternativeActions[LIRC_SEARCH_PREV] = c->readEntry("ALT_LIRC_SEARCH_PREV", "");
+ m_AlternativeActions[LIRC_SLEEP] = c->readEntry("ALT_LIRC_SLEEP", "");
+ m_AlternativeActions[LIRC_APPLICATION_QUIT] = c->readEntry("ALT_LIRC_APPLICATION_QUIT", "");
+
+ emit sigUpdateConfig();
+}
+
+
+ConfigPageInfo LircSupport::createConfigurationPage()
+{
+ LIRCConfiguration *conf = new LIRCConfiguration(NULL, this);
+ TQObject::connect(this, TQT_SIGNAL(sigUpdateConfig()), conf, TQT_SLOT(slotUpdateConfig()));
+ TQObject::connect(this, TQT_SIGNAL(sigRawLIRCSignal(const TQString &, int, bool &)),
+ conf, TQT_SLOT (slotRawLIRCSignal(const TQString &, int, bool &)));
+ return ConfigPageInfo (conf,
+ i18n("LIRC Support"),
+ i18n("LIRC Plugin"),
+ "connect_creating");
+}
+
+
+AboutPageInfo LircSupport::createAboutPage()
+{
+/* TDEAboutData aboutData("tderadio",
+ NULL,
+ NULL,
+ I18N_NOOP("Linux Infrared Remote Control Support for TDERadio"),
+ TDEAboutData::License_GPL,
+ "(c) 2002-2005 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("LIRC Support"),
+ i18n("LIRC Plugin"),
+ "connect_creating"
+ );*/
+ return AboutPageInfo();
+}
+
+
+bool LircSupport::checkActions(const TQString &lirc_string, int repeat_counter, const TQMap<LIRC_Actions, TQString> &map)
+{
+ SoundStreamID streamID = queryCurrentSoundStreamID();
+
+ bool retval = false;
+ bool q = false;
+ SoundFormat sf;
+ ISeekRadio *seeker = NULL;
+
+ TQMapConstIterator<LIRC_Actions, TQString> it = map.begin();
+ TQMapConstIterator<LIRC_Actions, TQString> end = map.end();
+ for (; !retval && it != end; ++it) {
+ if ((*it).length() && lirc_string == *it) {
+ LIRC_Actions action = it.key();
+ int digit = -1;
+ switch (action) {
+ case LIRC_DIGIT_0 :
+ if (repeat_counter == 0) {
+ digit = 0;
+ retval = true;
+ }
+ break;
+ case LIRC_DIGIT_1 :
+ if (repeat_counter == 0) {
+ digit = 1;
+ retval = true;
+ }
+ break;
+ case LIRC_DIGIT_2 :
+ if (repeat_counter == 0) {
+ digit = 2;
+ retval = true;
+ }
+ break;
+ case LIRC_DIGIT_3 :
+ if (repeat_counter == 0) {
+ digit = 3;
+ retval = true;
+ }
+ break;
+ case LIRC_DIGIT_4 :
+ if (repeat_counter == 0) {
+ digit = 4;
+ retval = true;
+ }
+ break;
+ case LIRC_DIGIT_5 :
+ if (repeat_counter == 0) {
+ digit = 5;
+ retval = true;
+ }
+ break;
+ case LIRC_DIGIT_6 :
+ if (repeat_counter == 0) {
+ digit = 6;
+ retval = true;
+ }
+ break;
+ case LIRC_DIGIT_7 :
+ if (repeat_counter == 0) {
+ digit = 7;
+ retval = true;
+ }
+ break;
+ case LIRC_DIGIT_8 :
+ if (repeat_counter == 0) {
+ digit = 8;
+ retval = true;
+ }
+ break;
+ case LIRC_DIGIT_9 :
+ if (repeat_counter == 0) {
+ digit = 9;
+ retval = true;
+ }
+ break;
+ case LIRC_POWER_ON :
+ if (repeat_counter == 0 && !queryIsPowerOn()) {
+ retval = true;
+ sendPowerOn();
+ }
+ break;
+ case LIRC_POWER_OFF :
+ if (repeat_counter == 0 && queryIsPowerOn()) {
+ retval = true;
+ sendPowerOff();
+ }
+ break;
+ case LIRC_PAUSE :
+ if (repeat_counter == 0 && queryIsPowerOn()) {
+ retval = true;
+ sendPausePlayback(streamID);
+ }
+ break;
+ case LIRC_RECORD_START :
+ queryIsRecordingRunning(streamID, q = false, sf);
+ if (repeat_counter == 0 && !q) {
+ retval = true;
+ sendStartRecording(streamID);
+ }
+ break;
+ case LIRC_RECORD_STOP :
+ queryIsRecordingRunning(streamID, q = false, sf);
+ if (repeat_counter == 0 && q) {
+ retval = true;
+ sendStopRecording(streamID);
+ }
+ break;
+ case LIRC_VOLUME_INC :
+ if (queryIsPowerOn()) {
+ retval = true;
+ float oldVolume = 0;
+ queryPlaybackVolume(streamID, oldVolume);
+ sendPlaybackVolume (streamID, oldVolume + 1.0/32.0);
+ }
+ break;
+ case LIRC_VOLUME_DEC :
+ if (queryIsPowerOn()) {
+ retval = true;
+ float oldVolume = 0;
+ queryPlaybackVolume(streamID, oldVolume);
+ sendPlaybackVolume (streamID, oldVolume - 1.0/32.0);
+ }
+ break;
+ case LIRC_CHANNEL_NEXT :
+ if (repeat_counter == 0 && queryIsPowerOn()) {
+ retval = true;
+ int k = queryCurrentStationIdx() + 1;
+ if (k >= queryStations().count())
+ k = 0;
+ sendActivateStation(k);
+ }
+ break;
+ case LIRC_CHANNEL_PREV :
+ if (repeat_counter == 0 && queryIsPowerOn()) {
+ retval = true;
+ int k = queryCurrentStationIdx() - 1;
+ if (k < 0)
+ k = queryStations().count() - 1;
+ sendActivateStation(k);
+ }
+ break;
+ case LIRC_SEARCH_NEXT :
+ if (repeat_counter == 0 && queryIsPowerOn()) {
+ retval = true;
+ seeker = dynamic_cast<ISeekRadio*> (queryActiveDevice());
+ seeker->startSeekUp();
+ }
+ break;
+ case LIRC_SEARCH_PREV :
+ if (repeat_counter == 0 && queryIsPowerOn()) {
+ retval = true;
+ seeker = dynamic_cast<ISeekRadio*> (queryActiveDevice());
+ seeker->startSeekDown();
+ }
+ break;
+ case LIRC_SLEEP :
+ if (repeat_counter == 0 && queryIsPowerOn()) {
+ retval = true;
+ sendStartCountdown();
+ }
+ break;
+ case LIRC_APPLICATION_QUIT :
+ retval = true;
+ kapp->quit();
+ break;
+ default:
+ break;
+ }
+
+ if (digit >= 0) {
+ if (m_addIndex || digit == 0) {
+ activateStation(m_addIndex * 10 + digit);
+ m_kbdTimer->stop();
+ m_addIndex = 0;
+ } else {
+ m_addIndex = digit;
+ m_kbdTimer->start(500, true);
+ }
+ }
+ }
+ }
+ return retval;
+}
+
+
+void LircSupport::setActions(const TQMap<LIRC_Actions, TQString> &actions, const TQMap<LIRC_Actions, TQString> &alt_actions)
+{
+ m_Actions = actions;
+ m_AlternativeActions = alt_actions;
+}
+
+
+#include "lircsupport.moc"
diff --git a/plugins/lirc/lircsupport.h b/plugins/lirc/lircsupport.h
new file mode 100644
index 0000000..bd1ad8a
--- /dev/null
+++ b/plugins/lirc/lircsupport.h
@@ -0,0 +1,160 @@
+/***************************************************************************
+ lircsupport.h - description
+ -------------------
+ begin : Mon Feb 4 2002
+ copyright : (C) 2002 by Martin Witte / Frank Schwanz
+ email : witte@kawo1.rwth-aachen.de / schwanz@fh-brandenburg.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 LIRCSUPPORT_H
+#define LIRCSUPPORT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tqobject.h>
+#include "../../src/include/timecontrol_interfaces.h"
+#include "../../src/include/radio_interfaces.h"
+#include "../../src/include/radiodevicepool_interfaces.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+#include "../../src/include/plugins.h"
+
+
+enum LIRC_Actions {
+ LIRC_DIGIT_0,
+ LIRC_DIGIT_1,
+ LIRC_DIGIT_2,
+ LIRC_DIGIT_3,
+ LIRC_DIGIT_4,
+ LIRC_DIGIT_5,
+ LIRC_DIGIT_6,
+ LIRC_DIGIT_7,
+ LIRC_DIGIT_8,
+ LIRC_DIGIT_9,
+ LIRC_POWER_ON,
+ LIRC_POWER_OFF,
+ LIRC_PAUSE,
+ LIRC_RECORD_START,
+ LIRC_RECORD_STOP,
+ LIRC_VOLUME_INC,
+ LIRC_VOLUME_DEC,
+ LIRC_CHANNEL_NEXT,
+ LIRC_CHANNEL_PREV,
+ LIRC_SEARCH_NEXT,
+ LIRC_SEARCH_PREV,
+ LIRC_SLEEP,
+ LIRC_APPLICATION_QUIT
+};
+
+
+struct lirc_config;
+class TQSocketNotifier;
+class TQTimer;
+
+class LircSupport : public TQObject,
+ public PluginBase,
+ public IRadioClient,
+ public ITimeControlClient,
+ public ISoundStreamClient,
+ public IRadioDevicePoolClient
+{
+Q_OBJECT
+
+public:
+ LircSupport(const TQString &name);
+ ~LircSupport();
+
+ virtual bool connectI (Interface *);
+ virtual bool disconnectI (Interface *);
+
+ virtual TQString pluginClassName() const { return "LircSupport"; }
+
+ virtual const TQString &name() const { return PluginBase::name(); }
+ virtual TQString &name() { return PluginBase::name(); }
+
+
+ virtual void setActions(const TQMap<LIRC_Actions, TQString> &actions, const TQMap<LIRC_Actions, TQString> &alt_actions);
+ virtual const TQMap<LIRC_Actions, TQString> &getActions() const { return m_Actions; }
+ virtual const TQMap<LIRC_Actions, TQString> &getAlternativeActions() const { return m_AlternativeActions; }
+
+ // PluginBase
+
+public:
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+ virtual ConfigPageInfo createConfigurationPage();
+ virtual AboutPageInfo createAboutPage();
+
+ // IRadioClient methods
+
+RECEIVERS:
+ bool noticePowerChanged(bool /*on*/) { return false; }
+ bool noticeStationChanged (const RadioStation &, int /*idx*/) { return false; }
+ bool noticeStationsChanged(const StationList &/*sl*/) { return false; }
+ bool noticePresetFileChanged(const TQString &/*f*/) { return false; }
+
+ bool noticeCurrentSoundStreamIDChanged(SoundStreamID /*id*/) { return false; }
+
+ // ITimeControlClient
+
+RECEIVERS:
+ bool noticeAlarmsChanged(const AlarmVector &) { return false; }
+ bool noticeAlarm(const Alarm &) { return false; }
+ bool noticeNextAlarmChanged(const Alarm *) { return false; }
+ bool noticeCountdownStarted(const TQDateTime &/*end*/) { return false; }
+ bool noticeCountdownStopped() { return false; }
+ bool noticeCountdownZero() { return false; }
+ bool noticeCountdownSecondsChanged(int /*n*/) { return false; }
+
+ // IRadioDevicePoolClient
+
+RECEIVERS:
+ bool noticeActiveDeviceChanged(IRadioDevice *) { return false; }
+ bool noticeDevicesChanged(const TQPtrList<IRadioDevice> &) { return false; }
+ bool noticeDeviceDescriptionChanged(const TQString &) { return false; }
+
+
+protected:
+ void activateStation(int i);
+ bool checkActions(const TQString &string, int repeat_counter, const TQMap<LIRC_Actions, TQString> &map);
+
+protected slots:
+ void slotLIRC(int socket);
+ void slotKbdTimedOut();
+
+signals:
+
+ void sigUpdateConfig();
+
+ void sigRawLIRCSignal(const TQString &what, int repeat_counter, bool &consumed);
+
+protected:
+
+#ifdef HAVE_LIRC
+ TQSocketNotifier *m_lirc_notify;
+ int m_fd_lirc;
+ struct lirc_config *m_lircConfig;
+#endif
+
+ TQTimer *m_kbdTimer;
+ int m_addIndex;
+ bool m_TakeRawLIRC;
+
+ TQMap<LIRC_Actions, TQString> m_Actions;
+ TQMap<LIRC_Actions, TQString> m_AlternativeActions;
+};
+
+
+
+#endif
diff --git a/plugins/lirc/listviewitem_lirc.cpp b/plugins/lirc/listviewitem_lirc.cpp
new file mode 100644
index 0000000..20976c5
--- /dev/null
+++ b/plugins/lirc/listviewitem_lirc.cpp
@@ -0,0 +1,51 @@
+/***************************************************************************
+ listviewitem_lirc.cpp - description
+ -------------------
+ begin : Sun Aug 14 2005
+ copyright : (C) 2005 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 "listviewitem_lirc.h"
+
+ListViewItemLirc::ListViewItemLirc(TQListView *parent, TQListViewItem *after)
+ : TDEListViewItem(parent, after),
+ m_renamingInProcess(-1)
+{
+}
+
+ListViewItemLirc::~ListViewItemLirc()
+{
+}
+
+void ListViewItemLirc::startRename(int col)
+{
+ TDEListViewItem::startRename(col);
+ m_renamingInProcess = col;
+ emit sigRenamingStarted(this, col);
+}
+
+void ListViewItemLirc::okRename(int col)
+{
+ TDEListViewItem::okRename(col);
+ m_renamingInProcess = -1;
+ emit sigRenamingStopped(this, col);
+}
+
+void ListViewItemLirc::cancelRename(int col)
+{
+ TDEListViewItem::cancelRename(col);
+ m_renamingInProcess = -1;
+ emit sigRenamingStopped(this, col);
+}
+
+#include "listviewitem_lirc.moc"
diff --git a/plugins/lirc/listviewitem_lirc.h b/plugins/lirc/listviewitem_lirc.h
new file mode 100644
index 0000000..d0d7444
--- /dev/null
+++ b/plugins/lirc/listviewitem_lirc.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ listviewitem_lirc.cpp - description
+ -------------------
+ begin : Sun Aug 14 2005
+ copyright : (C) 2005 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 LISTVIEWITEM_LIRC_H
+#define LISTVIEWITEM_LIRC_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tdelistview.h>
+
+class ListViewItemLirc : public TQObject, public TDEListViewItem
+{
+Q_OBJECT
+
+public:
+ ListViewItemLirc(TQListView *parent, TQListViewItem *after);
+ ~ListViewItemLirc();
+
+ bool isRenamingInProcess() const { return m_renamingInProcess >= 0; }
+ int getRenamingColumn() const { return m_renamingInProcess; }
+
+ virtual void startRename(int col);
+ virtual void okRename(int col);
+ virtual void cancelRename(int col);
+
+signals:
+
+ void sigRenamingStarted(ListViewItemLirc *sender, int column);
+ void sigRenamingStopped(ListViewItemLirc *sender, int column);
+
+protected:
+
+ int m_renamingInProcess;
+};
+
+#endif
diff --git a/plugins/lirc/po/Makefile.am b/plugins/lirc/po/Makefile.am
new file mode 100644
index 0000000..eada139
--- /dev/null
+++ b/plugins/lirc/po/Makefile.am
@@ -0,0 +1,2 @@
+PACKAGE = tderadio-lirc
+POFILES = AUTO
diff --git a/plugins/lirc/po/de.po b/plugins/lirc/po/de.po
new file mode 100644
index 0000000..e07a6d2
--- /dev/null
+++ b/plugins/lirc/po/de.po
@@ -0,0 +1,208 @@
+# translation of de.po to
+# translation of tderadio-lirc.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-12-23 23:40+0000\n"
+"Last-Translator: Chris <xchrisx@uber.space>\n"
+"Language-Team: German <https://mirror.git.trinitydesktop.org/weblate/"
+"projects/applications/tderadio-lirc/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, Chris (TDE)"
+
+#. 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, (Keine Email)"
+
+#: lirc-configuration.cpp:34
+msgid "digit 0"
+msgstr "Ziffer 0"
+
+#: lirc-configuration.cpp:35
+msgid "digit 1"
+msgstr "Ziffer 1"
+
+#: lirc-configuration.cpp:36
+msgid "digit 2"
+msgstr "Ziffer 2"
+
+#: lirc-configuration.cpp:37
+msgid "digit 3"
+msgstr "Ziffer 3"
+
+#: lirc-configuration.cpp:38
+msgid "digit 4"
+msgstr "Ziffer 4"
+
+#: lirc-configuration.cpp:39
+msgid "digit 5"
+msgstr "Ziffer 5"
+
+#: lirc-configuration.cpp:40
+msgid "digit 6"
+msgstr "Ziffer 6"
+
+#: lirc-configuration.cpp:41
+msgid "digit 7"
+msgstr "Ziffer 7"
+
+#: lirc-configuration.cpp:42
+msgid "digit 8"
+msgstr "Ziffer 8"
+
+#: lirc-configuration.cpp:43
+msgid "digit 9"
+msgstr "Ziffer 9"
+
+#: lirc-configuration.cpp:44
+msgid "Power On"
+msgstr "Einschalten"
+
+#: lirc-configuration.cpp:45
+msgid "Power Off"
+msgstr "Ausschalten"
+
+#: lirc-configuration.cpp:46
+msgid "Pause"
+msgstr "Pause"
+
+#: lirc-configuration.cpp:47
+msgid "Start Recording"
+msgstr "Aufnahme starten"
+
+#: lirc-configuration.cpp:48
+msgid "Stop Recording"
+msgstr "Aufnahme beenden"
+
+#: lirc-configuration.cpp:49
+msgid "Increase Volume"
+msgstr "Lautstärke erhöhen"
+
+#: lirc-configuration.cpp:50
+msgid "Decrease Volume"
+msgstr "Lautstärke senken"
+
+#: lirc-configuration.cpp:51
+msgid "Next Channel"
+msgstr "Nächster Sender"
+
+#: lirc-configuration.cpp:52
+msgid "Previous Channel"
+msgstr "Vorheriger Sender"
+
+#: lirc-configuration.cpp:53
+msgid "Search Next Channel"
+msgstr "Suche nächsten Sender"
+
+#: lirc-configuration.cpp:54
+msgid "Search Previous Channel"
+msgstr "Suche vorherigen Sender"
+
+#: lirc-configuration.cpp:55
+msgid "Enable Sleep Countdown"
+msgstr "Schlummer-Countdown aktivieren"
+
+#: lirc-configuration.cpp:56
+msgid "Quit TDERadio"
+msgstr "TDERadio Beenden"
+
+#: lirc-configuration.cpp:176
+msgid ""
+"Enter the key string of your remote or just press the button on your remote "
+"control"
+msgstr ""
+"Geben Sie die Zeichenkette Ihrer Fernsteuerung ein oder drücken Sie die "
+"Taste auf Ihrer Fernsteuerung"
+
+#: lirc-configuration.cpp:182
+msgid "Double Click on the entries to change the assignments"
+msgstr "Doppelklicken Sie auf die Einträge um die Zuordnung zu ändern"
+
+#: lircsupport.cpp:47
+msgid "Linux Infrared Control (LIRC) Support"
+msgstr "Unterstützung für die Fernsteuerung (LIRC)"
+
+#: lircsupport.cpp:53 lircsupport.cpp:332
+msgid "LIRC Plugin"
+msgstr "Plugin für die Fernsteuerung (LIRC)"
+
+#: lircsupport.cpp:58 lircsupport.cpp:59
+msgid "initializing tderadio lirc plugin"
+msgstr "initialisiere das Plugin für die Fernsteuerung (LIRC)"
+
+#: lircsupport.cpp:67
+msgid ""
+"%1 does not exist. File was created with TDERadio's default .lircrc proposal"
+msgstr ""
+"Die Datei %1 existiert nicht. Die Datei wurde mit den Voreinstellungen für "
+"TDERadio erzeugt."
+
+#: lircsupport.cpp:96
+msgid "There is no entry for tderadio in any of your .lircrc files."
+msgstr "Es gibt keinen Eintrag für TDERadio in jeglichen .lirc-Dateien."
+
+#: lircsupport.cpp:97
+msgid "Please setup your .lircrc files correctly."
+msgstr "Bitte richten Sie Ihre .lirc-Dateien richtig ein."
+
+#: lircsupport.cpp:108 lircsupport.cpp:109
+msgid "Initializing tderadio lirc plugin failed"
+msgstr "Die Initialisierung des TDERadio LIRC Plugins schlug fehl"
+
+#: lircsupport.cpp:111 lircsupport.cpp:112
+msgid "Initializing tderadio lirc plugin successful"
+msgstr "Die Initialisierung des LIRC Plugins war erfolgreich"
+
+#: lircsupport.cpp:169
+msgid ""
+"Reading from LIRC socket failed. Disabling LIRC Functions till next start of "
+"tderadio"
+msgstr ""
+"Das Lesen vom LIRC-Socket ist fehlgeschlagen. Die LIRC-Funktion wird bis zum "
+"nächsten Start von TDERadio temporär abgeschaltet."
+
+#: lircsupport.cpp:331
+msgid "LIRC Support"
+msgstr "Fernsteuerung"
+
+#: lirc-configuration-ui.ui:17
+#, no-c-format
+msgid "LIRCConfigurationUI"
+msgstr "LIRCConfigurationUI"
+
+#: lirc-configuration-ui.ui:26
+#, no-c-format
+msgid "Action"
+msgstr "Aktion"
+
+#: lirc-configuration-ui.ui:37
+#, no-c-format
+msgid "LIRC String"
+msgstr "LIRC-Zeichenkette"
+
+#: lirc-configuration-ui.ui:48
+#, no-c-format
+msgid "Alternative LIRC String"
+msgstr "Alternative LIRC-Zeichenkette"
+
+#: lirc-configuration-ui.ui:98
+#, no-c-format
+msgid "textLabel1"
+msgstr "textLabel1"
diff --git a/plugins/lirc/po/pt.po b/plugins/lirc/po/pt.po
new file mode 100644
index 0000000..1a43cee
--- /dev/null
+++ b/plugins/lirc/po/pt.po
@@ -0,0 +1,195 @@
+# SOME DESCRIPTIVE TITLE.
+# Hugo Carvalho <hugokarvalho@hotmail.com>, 2020.
+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: Automatically generated\n"
+"Language-Team: none\n"
+"Language: pt\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).
+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 ""
+
+#: lirc-configuration.cpp:34
+msgid "digit 0"
+msgstr ""
+
+#: lirc-configuration.cpp:35
+msgid "digit 1"
+msgstr ""
+
+#: lirc-configuration.cpp:36
+msgid "digit 2"
+msgstr ""
+
+#: lirc-configuration.cpp:37
+msgid "digit 3"
+msgstr ""
+
+#: lirc-configuration.cpp:38
+msgid "digit 4"
+msgstr ""
+
+#: lirc-configuration.cpp:39
+msgid "digit 5"
+msgstr ""
+
+#: lirc-configuration.cpp:40
+msgid "digit 6"
+msgstr ""
+
+#: lirc-configuration.cpp:41
+msgid "digit 7"
+msgstr ""
+
+#: lirc-configuration.cpp:42
+msgid "digit 8"
+msgstr ""
+
+#: lirc-configuration.cpp:43
+msgid "digit 9"
+msgstr ""
+
+#: lirc-configuration.cpp:44
+msgid "Power On"
+msgstr ""
+
+#: lirc-configuration.cpp:45
+msgid "Power Off"
+msgstr ""
+
+#: lirc-configuration.cpp:46
+msgid "Pause"
+msgstr ""
+
+#: lirc-configuration.cpp:47
+msgid "Start Recording"
+msgstr ""
+
+#: lirc-configuration.cpp:48
+msgid "Stop Recording"
+msgstr ""
+
+#: lirc-configuration.cpp:49
+msgid "Increase Volume"
+msgstr ""
+
+#: lirc-configuration.cpp:50
+msgid "Decrease Volume"
+msgstr ""
+
+#: lirc-configuration.cpp:51
+msgid "Next Channel"
+msgstr ""
+
+#: lirc-configuration.cpp:52
+msgid "Previous Channel"
+msgstr ""
+
+#: lirc-configuration.cpp:53
+msgid "Search Next Channel"
+msgstr ""
+
+#: lirc-configuration.cpp:54
+msgid "Search Previous Channel"
+msgstr ""
+
+#: lirc-configuration.cpp:55
+msgid "Enable Sleep Countdown"
+msgstr ""
+
+#: lirc-configuration.cpp:56
+msgid "Quit TDERadio"
+msgstr ""
+
+#: lirc-configuration.cpp:176
+msgid ""
+"Enter the key string of your remote or just press the button on your remote "
+"control"
+msgstr ""
+
+#: lirc-configuration.cpp:182
+msgid "Double Click on the entries to change the assignments"
+msgstr ""
+
+#: lircsupport.cpp:47
+msgid "Linux Infrared Control (LIRC) Support"
+msgstr ""
+
+#: lircsupport.cpp:53 lircsupport.cpp:332
+msgid "LIRC Plugin"
+msgstr ""
+
+#: lircsupport.cpp:58 lircsupport.cpp:59
+msgid "initializing tderadio lirc plugin"
+msgstr ""
+
+#: lircsupport.cpp:67
+msgid ""
+"%1 does not exist. File was created with TDERadio's default .lircrc proposal"
+msgstr ""
+
+#: lircsupport.cpp:96
+msgid "There is no entry for tderadio in any of your .lircrc files."
+msgstr ""
+
+#: lircsupport.cpp:97
+msgid "Please setup your .lircrc files correctly."
+msgstr ""
+
+#: lircsupport.cpp:108 lircsupport.cpp:109
+msgid "Initializing tderadio lirc plugin failed"
+msgstr ""
+
+#: lircsupport.cpp:111 lircsupport.cpp:112
+msgid "Initializing tderadio lirc plugin successful"
+msgstr ""
+
+#: lircsupport.cpp:169
+msgid ""
+"Reading from LIRC socket failed. Disabling LIRC Functions till next start of "
+"tderadio"
+msgstr ""
+
+#: lircsupport.cpp:331
+msgid "LIRC Support"
+msgstr ""
+
+#: lirc-configuration-ui.ui:17
+#, no-c-format
+msgid "LIRCConfigurationUI"
+msgstr ""
+
+#: lirc-configuration-ui.ui:26
+#, no-c-format
+msgid "Action"
+msgstr ""
+
+#: lirc-configuration-ui.ui:37
+#, no-c-format
+msgid "LIRC String"
+msgstr ""
+
+#: lirc-configuration-ui.ui:48
+#, no-c-format
+msgid "Alternative LIRC String"
+msgstr ""
+
+#: lirc-configuration-ui.ui:98
+#, no-c-format
+msgid "textLabel1"
+msgstr ""
diff --git a/plugins/lirc/po/ru.po b/plugins/lirc/po/ru.po
new file mode 100644
index 0000000..0793f4e
--- /dev/null
+++ b/plugins/lirc/po/ru.po
@@ -0,0 +1,202 @@
+# translation of ru.po to
+# translation of tderadio-lirc.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:54+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"
+
+#: lirc-configuration.cpp:34
+msgid "digit 0"
+msgstr "ноль"
+
+#: lirc-configuration.cpp:35
+msgid "digit 1"
+msgstr "один"
+
+#: lirc-configuration.cpp:36
+msgid "digit 2"
+msgstr "два"
+
+#: lirc-configuration.cpp:37
+msgid "digit 3"
+msgstr "три"
+
+#: lirc-configuration.cpp:38
+msgid "digit 4"
+msgstr "четыре"
+
+#: lirc-configuration.cpp:39
+msgid "digit 5"
+msgstr "пять"
+
+#: lirc-configuration.cpp:40
+msgid "digit 6"
+msgstr "шесть"
+
+#: lirc-configuration.cpp:41
+msgid "digit 7"
+msgstr "семь"
+
+#: lirc-configuration.cpp:42
+msgid "digit 8"
+msgstr "восемь"
+
+#: lirc-configuration.cpp:43
+msgid "digit 9"
+msgstr "девять"
+
+#: lirc-configuration.cpp:44
+msgid "Power On"
+msgstr "Включить"
+
+#: lirc-configuration.cpp:45
+msgid "Power Off"
+msgstr "Выключить"
+
+#: lirc-configuration.cpp:46
+msgid "Pause"
+msgstr "Приостановить"
+
+#: lirc-configuration.cpp:47
+msgid "Start Recording"
+msgstr "Начать запись"
+
+#: lirc-configuration.cpp:48
+msgid "Stop Recording"
+msgstr "Остановить запись"
+
+#: lirc-configuration.cpp:49
+msgid "Increase Volume"
+msgstr "Увеличить громкость"
+
+#: lirc-configuration.cpp:50
+msgid "Decrease Volume"
+msgstr "Уменьшить громкость"
+
+#: lirc-configuration.cpp:51
+msgid "Next Channel"
+msgstr "Следующий канал"
+
+#: lirc-configuration.cpp:52
+msgid "Previous Channel"
+msgstr "Предыдущий канал"
+
+#: lirc-configuration.cpp:53
+msgid "Search Next Channel"
+msgstr "Поиск следующего канала"
+
+#: lirc-configuration.cpp:54
+msgid "Search Previous Channel"
+msgstr "Поиск предыдущего канала"
+
+#: lirc-configuration.cpp:55
+msgid "Enable Sleep Countdown"
+msgstr "Включить таймер отключения"
+
+#: lirc-configuration.cpp:56
+msgid "Quit TDERadio"
+msgstr "Закрыть TDERadio"
+
+#: lirc-configuration.cpp:176
+msgid ""
+"Enter the key string of your remote or just press the button on your remote "
+"control"
+msgstr "Введите ключевую строку вашего ПДУ либо просто нажмите кнопку на нём"
+
+#: lirc-configuration.cpp:182
+msgid "Double Click on the entries to change the assignments"
+msgstr "Для изменения привязки дважды щёлкните по ней мышью"
+
+#: lircsupport.cpp:47
+msgid "Linux Infrared Control (LIRC) Support"
+msgstr "Поддержка ПДУ в Linux (LIRC)"
+
+#: lircsupport.cpp:53 lircsupport.cpp:332
+msgid "LIRC Plugin"
+msgstr "Модуль ДУ (LIRC)"
+
+#: lircsupport.cpp:58 lircsupport.cpp:59
+msgid "initializing tderadio lirc plugin"
+msgstr "Инициализация модуля LIRC"
+
+#: lircsupport.cpp:67
+msgid ""
+"%1 does not exist. File was created with TDERadio's default .lircrc proposal"
+msgstr "%1 не существует. Был создан файл .lircrc для TDERadio по умолчанию"
+
+#: lircsupport.cpp:96
+msgid "There is no entry for tderadio in any of your .lircrc files."
+msgstr "Ни в одном из ваших файлов .lircrc нет упоминания о TDERadio."
+
+#: lircsupport.cpp:97
+msgid "Please setup your .lircrc files correctly."
+msgstr "Настройте файлы .lircrc"
+
+#: lircsupport.cpp:108 lircsupport.cpp:109
+msgid "Initializing tderadio lirc plugin failed"
+msgstr "Инициализация модуля LIRC не удалась"
+
+#: lircsupport.cpp:111 lircsupport.cpp:112
+msgid "Initializing tderadio lirc plugin successful"
+msgstr "Модуль LIRC инициализирован"
+
+#: lircsupport.cpp:169
+msgid ""
+"Reading from LIRC socket failed. Disabling LIRC Functions till next start of "
+"tderadio"
+msgstr ""
+"Чтение из сокета LIRC не удалось. Отключаю функции LIRC до следующего "
+"запуска TDERadio."
+
+#: lircsupport.cpp:331
+msgid "LIRC Support"
+msgstr "Поддержка LIRC"
+
+#: lirc-configuration-ui.ui:17
+#, no-c-format
+msgid "LIRCConfigurationUI"
+msgstr "LIRCConfigurationUI"
+
+#: lirc-configuration-ui.ui:26
+#, no-c-format
+msgid "Action"
+msgstr "Действие"
+
+#: lirc-configuration-ui.ui:37
+#, no-c-format
+msgid "LIRC String"
+msgstr "Строка LIRC"
+
+#: lirc-configuration-ui.ui:48
+#, no-c-format
+msgid "Alternative LIRC String"
+msgstr "Альтернативная строка LIRC"
+
+#: lirc-configuration-ui.ui:98
+#, no-c-format
+msgid "textLabel1"
+msgstr "textLabel1"
diff --git a/plugins/lirc/po/tderadio-lirc.pot b/plugins/lirc/po/tderadio-lirc.pot
new file mode 100644
index 0000000..9dfef8f
--- /dev/null
+++ b/plugins/lirc/po/tderadio-lirc.pot
@@ -0,0 +1,198 @@
+# 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 ""
+
+#: lirc-configuration.cpp:34
+msgid "digit 0"
+msgstr ""
+
+#: lirc-configuration.cpp:35
+msgid "digit 1"
+msgstr ""
+
+#: lirc-configuration.cpp:36
+msgid "digit 2"
+msgstr ""
+
+#: lirc-configuration.cpp:37
+msgid "digit 3"
+msgstr ""
+
+#: lirc-configuration.cpp:38
+msgid "digit 4"
+msgstr ""
+
+#: lirc-configuration.cpp:39
+msgid "digit 5"
+msgstr ""
+
+#: lirc-configuration.cpp:40
+msgid "digit 6"
+msgstr ""
+
+#: lirc-configuration.cpp:41
+msgid "digit 7"
+msgstr ""
+
+#: lirc-configuration.cpp:42
+msgid "digit 8"
+msgstr ""
+
+#: lirc-configuration.cpp:43
+msgid "digit 9"
+msgstr ""
+
+#: lirc-configuration.cpp:44
+msgid "Power On"
+msgstr ""
+
+#: lirc-configuration.cpp:45
+msgid "Power Off"
+msgstr ""
+
+#: lirc-configuration.cpp:46
+msgid "Pause"
+msgstr ""
+
+#: lirc-configuration.cpp:47
+msgid "Start Recording"
+msgstr ""
+
+#: lirc-configuration.cpp:48
+msgid "Stop Recording"
+msgstr ""
+
+#: lirc-configuration.cpp:49
+msgid "Increase Volume"
+msgstr ""
+
+#: lirc-configuration.cpp:50
+msgid "Decrease Volume"
+msgstr ""
+
+#: lirc-configuration.cpp:51
+msgid "Next Channel"
+msgstr ""
+
+#: lirc-configuration.cpp:52
+msgid "Previous Channel"
+msgstr ""
+
+#: lirc-configuration.cpp:53
+msgid "Search Next Channel"
+msgstr ""
+
+#: lirc-configuration.cpp:54
+msgid "Search Previous Channel"
+msgstr ""
+
+#: lirc-configuration.cpp:55
+msgid "Enable Sleep Countdown"
+msgstr ""
+
+#: lirc-configuration.cpp:56
+msgid "Quit TDERadio"
+msgstr ""
+
+#: lirc-configuration.cpp:176
+msgid ""
+"Enter the key string of your remote or just press the button on your remote "
+"control"
+msgstr ""
+
+#: lirc-configuration.cpp:182
+msgid "Double Click on the entries to change the assignments"
+msgstr ""
+
+#: lircsupport.cpp:47
+msgid "Linux Infrared Control (LIRC) Support"
+msgstr ""
+
+#: lircsupport.cpp:53 lircsupport.cpp:332
+msgid "LIRC Plugin"
+msgstr ""
+
+#: lircsupport.cpp:58 lircsupport.cpp:59
+msgid "initializing tderadio lirc plugin"
+msgstr ""
+
+#: lircsupport.cpp:67
+msgid ""
+"%1 does not exist. File was created with TDERadio's default .lircrc proposal"
+msgstr ""
+
+#: lircsupport.cpp:96
+msgid "There is no entry for tderadio in any of your .lircrc files."
+msgstr ""
+
+#: lircsupport.cpp:97
+msgid "Please setup your .lircrc files correctly."
+msgstr ""
+
+#: lircsupport.cpp:108 lircsupport.cpp:109
+msgid "Initializing tderadio lirc plugin failed"
+msgstr ""
+
+#: lircsupport.cpp:111 lircsupport.cpp:112
+msgid "Initializing tderadio lirc plugin successful"
+msgstr ""
+
+#: lircsupport.cpp:169
+msgid ""
+"Reading from LIRC socket failed. Disabling LIRC Functions till next start of "
+"tderadio"
+msgstr ""
+
+#: lircsupport.cpp:331
+msgid "LIRC Support"
+msgstr ""
+
+#: lirc-configuration-ui.ui:17
+#, no-c-format
+msgid "LIRCConfigurationUI"
+msgstr ""
+
+#: lirc-configuration-ui.ui:26
+#, no-c-format
+msgid "Action"
+msgstr ""
+
+#: lirc-configuration-ui.ui:37
+#, no-c-format
+msgid "LIRC String"
+msgstr ""
+
+#: lirc-configuration-ui.ui:48
+#, no-c-format
+msgid "Alternative LIRC String"
+msgstr ""
+
+#: lirc-configuration-ui.ui:98
+#, no-c-format
+msgid "textLabel1"
+msgstr ""
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 ""
diff --git a/plugins/radio/CMakeL10n.txt b/plugins/radio/CMakeL10n.txt
new file mode 100644
index 0000000..e47b1d1
--- /dev/null
+++ b/plugins/radio/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-radio"
+ DESTINATION "po"
+)
diff --git a/plugins/radio/Makefile.am b/plugins/radio/Makefile.am
new file mode 100644
index 0000000..79b5cac
--- /dev/null
+++ b/plugins/radio/Makefile.am
@@ -0,0 +1,18 @@
+SUBDIRS = po .
+
+INCLUDES = -I$(top_builddir)/src -I$(top_srcdir) $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = libradio.la
+libradio_la_SOURCES = radio-configuration.cpp radio-configuration-ui.ui \
+ radio.cpp
+libradio_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+
+noinst_HEADERS = radio-configuration.h radio.h
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-radio.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-radio.pot
diff --git a/plugins/radio/po/Makefile.am b/plugins/radio/po/Makefile.am
new file mode 100644
index 0000000..b5baba9
--- /dev/null
+++ b/plugins/radio/po/Makefile.am
@@ -0,0 +1,2 @@
+PACKAGE = tderadio-radio
+POFILES = AUTO
diff --git a/plugins/radio/po/de.po b/plugins/radio/po/de.po
new file mode 100644
index 0000000..7709106
--- /dev/null
+++ b/plugins/radio/po/de.po
@@ -0,0 +1,168 @@
+# translation of de.po to
+# translation of tderadio-radio.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: 2006-11-06 01:18+0100\n"
+"Last-Translator: Ernst Martin Witte <emw@nocabal.de>\n"
+"Language-Team: <de@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.11.4\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 "witte@kawo1.rwth-aachen.de"
+
+#: radio-configuration.cpp:350
+msgid "Image Selection"
+msgstr "Symbolauswahl"
+
+#: radio-configuration.cpp:355
+msgid "ignoring non-local image"
+msgstr "Ignoriere nicht-lokale Symbole"
+
+#: radio-configuration.cpp:450 radio-configuration.cpp:470
+msgid "TDERadio Preset Files"
+msgstr "Senderdateien für TDERadio"
+
+#: radio-configuration.cpp:452 radio-configuration.cpp:472
+msgid "Preset File Selection"
+msgstr "Auswahl der Senderdatei"
+
+#: radio-configuration.cpp:455
+msgid "Select Preset File"
+msgstr "Wählen Sie eine Senderdatei aus"
+
+#: radio-configuration.cpp:475
+msgid "Store Preset File"
+msgstr "Speichern der Senderdatei"
+
+#: radio.cpp:34
+msgid "Central Radio Device Multiplexer"
+msgstr "Zentraler Radio-Multiplexer"
+
+#: radio.cpp:39
+msgid "Radio Multiplexer Plugin"
+msgstr "Plugin für den Radio-Gerätemultiplexer"
+
+#: radio.cpp:116
+msgid "Radio Stations"
+msgstr "Radiosender"
+
+#: radio.cpp:117
+msgid "Setup Radio Stations"
+msgstr "Einstellung der Radiosender"
+
+#: radio.cpp:351
+msgid "unknown"
+msgstr "unbekannt"
+
+#: radio-configuration-ui.ui:28
+#, no-c-format
+msgid "Station &Presets"
+msgstr "&Voreingestellte Sender"
+
+#: radio-configuration-ui.ui:53
+#, no-c-format
+msgid "Stations"
+msgstr "Sender"
+
+#: radio-configuration-ui.ui:179
+#, no-c-format
+msgid "&Search Stations"
+msgstr "&Sendersuche"
+
+#: radio-configuration-ui.ui:198
+#, no-c-format
+msgid "Load"
+msgstr "Öffnen"
+
+#: radio-configuration-ui.ui:263
+#, no-c-format
+msgid "Name"
+msgstr "Name"
+
+#: radio-configuration-ui.ui:294
+#, no-c-format
+msgid "Short Name"
+msgstr "Kurzname"
+
+#: radio-configuration-ui.ui:325
+#, no-c-format
+msgid "Pixmap File"
+msgstr "Bilddatei"
+
+#: radio-configuration-ui.ui:457
+#, no-c-format
+msgid " %"
+msgstr " %"
+
+#: radio-configuration-ui.ui:471
+#, no-c-format
+msgid "Volume Preset"
+msgstr "Lautstärke"
+
+#: radio-configuration-ui.ui:508
+#, no-c-format
+msgid "Personal Preset File"
+msgstr "Persönliche Senderdatei"
+
+#: radio-configuration-ui.ui:564
+#, no-c-format
+msgid "City"
+msgstr "Stadt"
+
+#: radio-configuration-ui.ui:577
+#, no-c-format
+msgid "Country"
+msgstr "Land"
+
+#: radio-configuration-ui.ui:617
+#, no-c-format
+msgid "&Now"
+msgstr "&Jetzt"
+
+#: radio-configuration-ui.ui:627
+#, no-c-format
+msgid "Comment"
+msgstr "Kommentar"
+
+#: radio-configuration-ui.ui:640
+#, no-c-format
+msgid "Media"
+msgstr "Medium"
+
+#: radio-configuration-ui.ui:648
+#, no-c-format
+msgid "Maintainer"
+msgstr "Maintainer"
+
+#: radio-configuration-ui.ui:661
+#, no-c-format
+msgid "Last Change"
+msgstr "Letzte Änderung"
+
+#: radio-configuration-ui.ui:698
+#, no-c-format
+msgid ""
+"<p align=\"center\">Click on the link below to contribute this station "
+"preset file to the tderadio project.</p>"
+msgstr ""
+"<p align=\"center\">Klicke auf den folgenden Link um mit deinen "
+"Senderinformationen zum TDERadio-Projekt beizutragen.</p>"
diff --git a/plugins/radio/po/ru.po b/plugins/radio/po/ru.po
new file mode 100644
index 0000000..39d0881
--- /dev/null
+++ b/plugins/radio/po/ru.po
@@ -0,0 +1,171 @@
+# translation of ru.po to
+# translation of tderadio-radio.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: 2020-01-03 16:07+0000\n"
+"Last-Translator: Serg Bormant <bormant@mail.ru>\n"
+"Language-Team: Russian <https://mirror.git.trinitydesktop.org/weblate/"
+"projects/applications/tderadio-radio/ru/>\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Generator: Weblate 3.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"
+
+#: radio-configuration.cpp:350
+msgid "Image Selection"
+msgstr "Выбор картинки"
+
+#: radio-configuration.cpp:355
+msgid "ignoring non-local image"
+msgstr "Пропускать не локальные файлы"
+
+#: radio-configuration.cpp:450 radio-configuration.cpp:470
+msgid "TDERadio Preset Files"
+msgstr "Файлы TDERadio"
+
+#: radio-configuration.cpp:452 radio-configuration.cpp:472
+msgid "Preset File Selection"
+msgstr "Выбор файла радиостанций"
+
+#: radio-configuration.cpp:455
+msgid "Select Preset File"
+msgstr "Выбор файла радиостанций"
+
+#: radio-configuration.cpp:475
+msgid "Store Preset File"
+msgstr "Сохранить файл радиостанций"
+
+#: radio.cpp:34
+msgid "Central Radio Device Multiplexer"
+msgstr "Главный мультиплексор устройства радио"
+
+#: radio.cpp:39
+msgid "Radio Multiplexer Plugin"
+msgstr "Модуль мультиплексирования для TDERadio"
+
+#: radio.cpp:116
+msgid "Radio Stations"
+msgstr "Радиостанции"
+
+#: radio.cpp:117
+msgid "Setup Radio Stations"
+msgstr "Настройка радиостанции"
+
+#: radio.cpp:351
+msgid "unknown"
+msgstr "низвестно"
+
+#: radio-configuration-ui.ui:28
+#, no-c-format
+msgid "Station &Presets"
+msgstr "Параметры &радиостанций"
+
+#: radio-configuration-ui.ui:53
+#, no-c-format
+msgid "Stations"
+msgstr "Список"
+
+#: radio-configuration-ui.ui:179
+#, no-c-format
+msgid "&Search Stations"
+msgstr "&Поиск"
+
+#: radio-configuration-ui.ui:198
+#, no-c-format
+msgid "Load"
+msgstr "Из файла"
+
+#: radio-configuration-ui.ui:263
+#, no-c-format
+msgid "Name"
+msgstr "Название"
+
+#: radio-configuration-ui.ui:294
+#, no-c-format
+msgid "Short Name"
+msgstr "Сокращённое название"
+
+#: radio-configuration-ui.ui:325
+#, no-c-format
+msgid "Pixmap File"
+msgstr "Пиктограмма"
+
+#: radio-configuration-ui.ui:457
+#, no-c-format
+msgid " %"
+msgstr " %"
+
+#: radio-configuration-ui.ui:471
+#, no-c-format
+msgid "Volume Preset"
+msgstr "Установить громкость (-1=не менять)"
+
+#: radio-configuration-ui.ui:508
+#, no-c-format
+msgid "Personal Preset File"
+msgstr "Пользовательский файл настроек"
+
+#: radio-configuration-ui.ui:564
+#, no-c-format
+msgid "City"
+msgstr "Город"
+
+#: radio-configuration-ui.ui:577
+#, no-c-format
+msgid "Country"
+msgstr "Страна"
+
+#: radio-configuration-ui.ui:617
+#, no-c-format
+msgid "&Now"
+msgstr "&Текущее время"
+
+#: radio-configuration-ui.ui:627
+#, no-c-format
+msgid "Comment"
+msgstr "Описание"
+
+#: radio-configuration-ui.ui:640
+#, no-c-format
+msgid "Media"
+msgstr "Носитель"
+
+#: radio-configuration-ui.ui:648
+#, no-c-format
+msgid "Maintainer"
+msgstr "Сопровождающий"
+
+#: radio-configuration-ui.ui:661
+#, fuzzy, no-c-format
+msgid "Last Change"
+msgstr "Последнее изменение"
+
+#: radio-configuration-ui.ui:698
+#, no-c-format
+msgid ""
+"<p align=\"center\">Click on the link below to contribute this station "
+"preset file to the tderadio project.</p>"
+msgstr ""
+"<p align=\"center\"> Чтобы добавить этот файл в проект TDERadio, щёлкните по "
+"ссылке ниже</p>"
diff --git a/plugins/radio/po/tderadio-radio.pot b/plugins/radio/po/tderadio-radio.pot
new file mode 100644
index 0000000..352caab
--- /dev/null
+++ b/plugins/radio/po/tderadio-radio.pot
@@ -0,0 +1,164 @@
+# 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 ""
+
+#: radio-configuration.cpp:350
+msgid "Image Selection"
+msgstr ""
+
+#: radio-configuration.cpp:355
+msgid "ignoring non-local image"
+msgstr ""
+
+#: radio-configuration.cpp:450 radio-configuration.cpp:470
+msgid "TDERadio Preset Files"
+msgstr ""
+
+#: radio-configuration.cpp:452 radio-configuration.cpp:472
+msgid "Preset File Selection"
+msgstr ""
+
+#: radio-configuration.cpp:455
+msgid "Select Preset File"
+msgstr ""
+
+#: radio-configuration.cpp:475
+msgid "Store Preset File"
+msgstr ""
+
+#: radio.cpp:34
+msgid "Central Radio Device Multiplexer"
+msgstr ""
+
+#: radio.cpp:39
+msgid "Radio Multiplexer Plugin"
+msgstr ""
+
+#: radio.cpp:116
+msgid "Radio Stations"
+msgstr ""
+
+#: radio.cpp:117
+msgid "Setup Radio Stations"
+msgstr ""
+
+#: radio.cpp:351
+msgid "unknown"
+msgstr ""
+
+#: radio-configuration-ui.ui:28
+#, no-c-format
+msgid "Station &Presets"
+msgstr ""
+
+#: radio-configuration-ui.ui:53
+#, no-c-format
+msgid "Stations"
+msgstr ""
+
+#: radio-configuration-ui.ui:179
+#, no-c-format
+msgid "&Search Stations"
+msgstr ""
+
+#: radio-configuration-ui.ui:198
+#, no-c-format
+msgid "Load"
+msgstr ""
+
+#: radio-configuration-ui.ui:263
+#, no-c-format
+msgid "Name"
+msgstr ""
+
+#: radio-configuration-ui.ui:294
+#, no-c-format
+msgid "Short Name"
+msgstr ""
+
+#: radio-configuration-ui.ui:325
+#, no-c-format
+msgid "Pixmap File"
+msgstr ""
+
+#: radio-configuration-ui.ui:457
+#, no-c-format
+msgid " %"
+msgstr ""
+
+#: radio-configuration-ui.ui:471
+#, no-c-format
+msgid "Volume Preset"
+msgstr ""
+
+#: radio-configuration-ui.ui:508
+#, no-c-format
+msgid "Personal Preset File"
+msgstr ""
+
+#: radio-configuration-ui.ui:564
+#, no-c-format
+msgid "City"
+msgstr ""
+
+#: radio-configuration-ui.ui:577
+#, no-c-format
+msgid "Country"
+msgstr ""
+
+#: radio-configuration-ui.ui:617
+#, no-c-format
+msgid "&Now"
+msgstr ""
+
+#: radio-configuration-ui.ui:627
+#, no-c-format
+msgid "Comment"
+msgstr ""
+
+#: radio-configuration-ui.ui:640
+#, no-c-format
+msgid "Media"
+msgstr ""
+
+#: radio-configuration-ui.ui:648
+#, no-c-format
+msgid "Maintainer"
+msgstr ""
+
+#: radio-configuration-ui.ui:661
+#, no-c-format
+msgid "Last Change"
+msgstr ""
+
+#: radio-configuration-ui.ui:698
+#, no-c-format
+msgid ""
+"<p align=\"center\">Click on the link below to contribute this station "
+"preset file to the tderadio project.</p>"
+msgstr ""
diff --git a/plugins/radio/radio-configuration-ui.ui b/plugins/radio/radio-configuration-ui.ui
new file mode 100644
index 0000000..63ea82f
--- /dev/null
+++ b/plugins/radio/radio-configuration-ui.ui
@@ -0,0 +1,771 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>RadioConfigurationUI</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>RadioConfigurationUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>490</width>
+ <height>348</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget3</cstring>
+ </property>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>stations</cstring>
+ </property>
+ <attribute name="title">
+ <string>Station &amp;Presets</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout32</cstring>
+ </property>
+ <property name="margin" stdset="0">
+ <number>6</number>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelStationList</cstring>
+ </property>
+ <property name="text">
+ <string>Stations</string>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout22</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout9</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="RadioStationListView">
+ <property name="name">
+ <cstring>listStations</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonNewStation</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"filenew2"</iconset>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonDeleteStation</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"edit-delete"</iconset>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonStationUp</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"1uparrow"</iconset>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonStationDown</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"1downarrow"</iconset>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout21</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonSearchStations</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Search Stations</string>
+ </property>
+ <property name="iconSet">
+ <iconset>"edit-find"</iconset>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonLoadPresets</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Load</string>
+ </property>
+ <property name="iconSet">
+ <iconset>"document-open"</iconset>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonStorePresets</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Save As</string>
+ </property>
+ <property name="iconSet">
+ <iconset>"document-save-as"</iconset>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout18</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQWidgetStack">
+ <property name="name">
+ <cstring>stackStationEdit</cstring>
+ </property>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>page</cstring>
+ </property>
+ <attribute name="id">
+ <number>0</number>
+ </attribute>
+ </widget>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelStationName</cstring>
+ </property>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ </widget>
+ <widget class="TQLineEdit">
+ <property name="name">
+ <cstring>editStationName</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout32</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelStationShortName</cstring>
+ </property>
+ <property name="text">
+ <string>Short Name</string>
+ </property>
+ </widget>
+ <widget class="TQLineEdit">
+ <property name="name">
+ <cstring>editStationShortName</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelPixmapFile</cstring>
+ </property>
+ <property name="text">
+ <string>Pixmap File</string>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLineEdit">
+ <property name="name">
+ <cstring>editPixmapFile</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonSelectPixmapFile</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"document-open"</iconset>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout19</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>pixmapStation</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>10</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer4_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout20</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>editVolumePreset</cstring>
+ </property>
+ <property name="suffix">
+ <string> %</string>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="minValue">
+ <number>-1</number>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelVolumePreset</cstring>
+ </property>
+ <property name="text">
+ <string>Volume Preset</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer12</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout25</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>editLabelPresetFile</cstring>
+ </property>
+ <property name="text">
+ <string>Personal Preset File</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>editPresetFile</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>About</cstring>
+ </property>
+ <attribute name="title">
+ <string>A&amp;bout</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <spacer row="5" column="1">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLayoutWidget" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>layout21</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>labelCity</cstring>
+ </property>
+ <property name="text">
+ <string>City</string>
+ </property>
+ </widget>
+ <widget class="TQLineEdit" row="2" column="1">
+ <property name="name">
+ <cstring>editCountry</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>labelCountry</cstring>
+ </property>
+ <property name="text">
+ <string>Country</string>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget" row="1" column="1">
+ <property name="name">
+ <cstring>layout19</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQDateTimeEdit">
+ <property name="name">
+ <cstring>editLastChange</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>StrongFocus</enum>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonLastChangeNow</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Now</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLabel" row="5" column="0">
+ <property name="name">
+ <cstring>labelComment</cstring>
+ </property>
+ <property name="text">
+ <string>Comment</string>
+ </property>
+ </widget>
+ <widget class="TQLineEdit" row="5" column="1">
+ <property name="name">
+ <cstring>editComment</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="4" column="0">
+ <property name="name">
+ <cstring>labelMedia</cstring>
+ </property>
+ <property name="text">
+ <string>Media</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>labelMaintainer</cstring>
+ </property>
+ <property name="text">
+ <string>Maintainer</string>
+ </property>
+ </widget>
+ <widget class="TQLineEdit" row="3" column="1">
+ <property name="name">
+ <cstring>editCity</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>labelLastChange</cstring>
+ </property>
+ <property name="text">
+ <string>Last Change</string>
+ </property>
+ </widget>
+ <widget class="TQLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>editMaintainer</cstring>
+ </property>
+ </widget>
+ <widget class="TQLineEdit" row="4" column="1">
+ <property name="name">
+ <cstring>editMedia</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="1" column="1">
+ <property name="name">
+ <cstring>spacer7_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLabel" row="2" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;p align="center"&gt;Click on the link below to contribute this station preset file to the tderadio project.&lt;/p&gt;</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="KURLLabel" row="4" column="1">
+ <property name="name">
+ <cstring>mailLabel</cstring>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>RadioStationListView</class>
+ <header location="local">src/include/radiostation-listview.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="2782">789c8dd4df53e2481007f077ff0aca7eb3ae7a4948425257f78080a2828baebbea5eddc32493c80f110414f1eafef7eb7437dcdd9cd95a478afad47ca733193af97454bb1b0e6a479f0e566bb31e67b56c6496b523fb329b6d7fffe3b73f0f0e7dbf46ff5e3dacf987bf1c1c5ead6b59ed72fe9497800b02d4f9af34cefe6be83b1e3879ebb8e5b8edb8703c743c760c8e73c7a9e389e347c799733fe7cefc83e39163e378eaf8461d68fd253b26c73c1faa637550daab9783f3bc7fbf5e0e9eafab03f57776e2677ec2fe52ba9134e2061b36e2a0ae7e2e1d78413df038ff591d8881cf3730411c18f6bc74e88761c8cd02a84ec4f8956dc8923f565b319e958efcd046b2fe451c8562ecb14d642359cfe7dd6c34bd6683e7afd5a11846ea44bd65a7944fd96fea44fd543a6ec45e2cf5eed9691cc63c8f57ea44eda9ad3a12279e9afb2309923009b87e5b9da8b9ff928c9c713e515b31f07998a0e9697f6cd4a17aab4ed49762131aae8f7c7e26dbe7dfd4bbfcf1dedc4fb0101b63e4faafe2d4579f944effb9debbdaaa9b6293a7727f569cfaea5c6dd4fc7ba6968e437eff85da6abf5c88d328b5ecbedaa84fd5b99a9f972c349ef6d35aadfd03469ce659c87e17679118b9df33bb5f3f57effaef556da4ff70a5ceb51f3b3b6b3f36c4545ff637501b31acd5b9cec762ebeb3cdf1f3d1cbbfadd9db59f3371965bb99f99d8faea953a1223f7b7cdb348fb8bdf3f7964f33c6217e272709e7fef9c667379dfb7d4468cdfd4b9da2f5d44b929647d479d8b612c2e7c35bf5f8b825c70beab8ed4776aa3be5517e2abb53b10d0608a195a77e6a33ca7732cf0014738fe288f139cfec478c499e6a7f884735ce0332e3ffcac708d2f94b2fbfc2b6ef0adf2b3c577fa9e626b9f5ff0faea71ccf3ed7d7eceeb3bd8c5133cc51e9ee1395e601f0778899ff7f3c37d7ec9ebaff01abfe00d7ec56f784be38ed6dee3f7fdfcd0a92fe306ebe8a18f0daa1c90c3cafa534a46b49326c6543ba1da97800095f57b60781f3c20a5dddc4206b6b27e0f72bae33b4a15d8850718c118c674bd8afa30c17b9852e61166d8812798c302afe1b9aa3e2ce90a2baadd410f524a4fe87b0d2fd5e70300af74e62730a3dd4c60036fd88055e5fe6f30802dbcd39e0a68d1d91cd38a0db4ff5f1f3ad4233fe807e83af5d770423d52d19f700a3d67ffd5bda91f38fb57bf3dfeccf302e7fb7e9ea1c516b671f883d1a6843e2f708133e8c38056550e18409f9ec7bf7e3df81bd372939b</data>
+ </image>
+</images>
+<tabstops>
+ <tabstop>tabWidget3</tabstop>
+ <tabstop>listStations</tabstop>
+ <tabstop>buttonNewStation</tabstop>
+ <tabstop>buttonDeleteStation</tabstop>
+ <tabstop>buttonStationUp</tabstop>
+ <tabstop>buttonStationDown</tabstop>
+ <tabstop>buttonSearchStations</tabstop>
+ <tabstop>buttonLoadPresets</tabstop>
+ <tabstop>editStationName</tabstop>
+ <tabstop>editStationShortName</tabstop>
+ <tabstop>editPixmapFile</tabstop>
+ <tabstop>buttonSelectPixmapFile</tabstop>
+ <tabstop>editVolumePreset</tabstop>
+ <tabstop>editMaintainer</tabstop>
+ <tabstop>editLastChange</tabstop>
+ <tabstop>editCountry</tabstop>
+ <tabstop>editCity</tabstop>
+ <tabstop>editMedia</tabstop>
+ <tabstop>editComment</tabstop>
+</tabstops>
+<pixmapfunction>SmallIconSet</pixmapfunction>
+<layoutdefaults spacing="6" margin="0"/>
+<includes>
+ <include location="global" impldecl="in implementation">kiconloader.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">src/include/radiostation-listview.h</include>
+ <include location="global" impldecl="in implementation">tqwidgetstack.h</include>
+</includes>
+</UI>
diff --git a/plugins/radio/radio-configuration.cpp b/plugins/radio/radio-configuration.cpp
new file mode 100644
index 0000000..a08d458
--- /dev/null
+++ b/plugins/radio/radio-configuration.cpp
@@ -0,0 +1,592 @@
+/***************************************************************************
+ radio-configuration.cpp - description
+ -------------------
+ begin : Son Aug 3 2003
+ copyright : (C) 2003 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 "../../src/include/radiostation.h"
+#include "../../src/include/stationlist.h"
+#include "../../src/include/plugins.h"
+#include "../../src/include/radiodevice_interfaces.h"
+#include "../../src/include/standardscandialog.h"
+#include "../../src/include/radiostation-listview.h"
+#include "../../src/include/radiostation-config.h"
+#include "../../src/include/errorlog-interfaces.h"
+
+#include "radio-configuration.h"
+
+#include <math.h>
+
+#include <tqlistbox.h>
+#include <tdelistbox.h>
+#include <tqdatetimeedit.h>
+#include <tqlineedit.h>
+#include <tqlabel.h>
+#include <tqspinbox.h>
+#include <tqpushbutton.h>
+#include <tqpopupmenu.h>
+#include <tqtoolbutton.h>
+#include <tqwidgetstack.h>
+#include <tqimage.h>
+
+#include <tdefiledialog.h>
+#include <kstandarddirs.h>
+#include <kurllabel.h>
+#include <tqregexp.h>
+#include <krun.h>
+#include <kurlrequester.h>
+#include <tdelocale.h>
+
+RadioConfiguration::RadioConfiguration (TQWidget *parent, const IErrorLogClient &logger)
+ : RadioConfigurationUI(parent),
+ ignoreChanges(false),
+ devicePopup(NULL),
+ m_logger(logger),
+ m_dirty(true)
+{
+ TQObject::connect(listStations, TQT_SIGNAL(sigCurrentStationChanged(int)),
+ this, TQT_SLOT(slotStationSelectionChanged(int)));
+ TQObject::connect(buttonSelectPixmapFile, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotSelectPixmap()));
+ TQObject::connect(buttonNewStation, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotNewStation()));
+ TQObject::connect(buttonDeleteStation, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotDeleteStation()));
+ TQObject::connect(editPixmapFile, TQT_SIGNAL(textChanged(const TQString &)),
+ this, TQT_SLOT(slotPixmapChanged(const TQString &)));
+ TQObject::connect(editStationName, TQT_SIGNAL(textChanged(const TQString &)),
+ this, TQT_SLOT(slotStationNameChanged(const TQString &)));
+ TQObject::connect(editStationShortName, TQT_SIGNAL(textChanged(const TQString &)),
+ this, TQT_SLOT(slotStationShortNameChanged(const TQString &)));
+ TQObject::connect(editVolumePreset, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotVolumePresetChanged(int)));
+ TQObject::connect(buttonStationUp, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotStationUp()));
+ TQObject::connect(buttonStationDown, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotStationDown()));
+ TQObject::connect(listStations, TQT_SIGNAL(sigStationActivated(int)),
+ this, TQT_SLOT(slotActivateStation( int )));
+ TQObject::connect(buttonLoadPresets, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotLoadPresets()));
+ TQObject::connect(buttonStorePresets, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotStorePresets()));
+ TQObject::connect(buttonLastChangeNow, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotLastChangeNow()));
+
+ connect(editMaintainer, TQT_SIGNAL(textChanged(const TQString &)), TQT_SLOT(slotSetDirty()));
+ connect(editLastChange, TQT_SIGNAL(valueChanged(const TQDateTime &)), TQT_SLOT(slotSetDirty()));
+ connect(editCountry, TQT_SIGNAL(textChanged(const TQString &)), TQT_SLOT(slotSetDirty()));
+ connect(editCity, TQT_SIGNAL(textChanged(const TQString &)), TQT_SLOT(slotSetDirty()));
+ connect(editMedia, TQT_SIGNAL(textChanged(const TQString &)), TQT_SLOT(slotSetDirty()));
+ connect(editComment, TQT_SIGNAL(textChanged(const TQString &)), TQT_SLOT(slotSetDirty()));
+ connect(editPresetFile, TQT_SIGNAL(textChanged(const TQString &)), TQT_SLOT(slotSetDirty()));
+
+ mailLabel->setText("mailto:witte-presets@kawo1.rwth-aachen.de");
+ mailLabel->setURL ("mailto:witte-presets@kawo1.rwth-aachen.de");
+ TQObject::connect(mailLabel, TQT_SIGNAL(leftClickedURL(const TQString &)),
+ this, TQT_SLOT(slotSendPresetsByMail(const TQString &)));
+
+ TQObject::connect(buttonSearchStations, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotSearchStations0()));
+
+ devicePopup = new TQPopupMenu(buttonSearchStations);
+ buttonSearchStations->setPopup(devicePopup);
+ TQObject::connect(devicePopup, TQT_SIGNAL(activated(int)),
+ this, TQT_SLOT(slotSearchStations(int)));
+}
+
+
+RadioConfiguration::~RadioConfiguration ()
+{
+}
+
+
+bool RadioConfiguration::connectI (Interface *i)
+{
+ bool a = IRadioClient::connectI(i);
+ bool b = IRadioDevicePoolClient::connectI(i);
+
+ return a || b;
+}
+
+bool RadioConfiguration::disconnectI (Interface *i)
+{
+ bool a = IRadioClient::disconnectI(i);
+ bool b = IRadioDevicePoolClient::disconnectI(i);
+
+ return a || b;
+}
+
+// IRadioDevicePoolClient
+
+bool RadioConfiguration::noticeDevicesChanged(const TQPtrList<IRadioDevice> &l)
+{
+ TQPtrListIterator<IRadioDevice> it(l);
+ devices.clear();
+ devicePopup->clear();
+ int id = 0;
+ for (; it.current(); ++it) {
+ IRadioDevice *d = it.current();
+ if (dynamic_cast<ISeekRadio*>(d)) {
+ devicePopup->insertItem(d->getDescription(), id++);
+ devices.append(d);
+ }
+ }
+ return true;
+}
+
+
+bool RadioConfiguration::noticeDeviceDescriptionChanged(const TQString &)
+{
+ noticeDevicesChanged(queryDevices());
+ return true;
+}
+
+
+// IRadioClient
+
+bool RadioConfiguration::noticeStationsChanged(const StationList &sl)
+{
+ ignoreChanges = true;
+
+ m_stations = sl;
+
+ listStations->setStations(sl);
+
+ StationListMetaData &info = m_stations.metaData();
+
+ editMaintainer->setText(info.maintainer);
+ editLastChange->setDateTime(info.lastChange);
+ editCountry->setText(info.country);
+ editCity->setText(info.city);
+ editMedia->setText(info.media);
+ editComment->setText(info.comment);
+
+ ignoreChanges = false;
+
+ slotStationSelectionChanged(listStations->currentStationIndex());
+
+ return true;
+}
+
+
+bool RadioConfiguration::noticePresetFileChanged(const TQString &f)
+{
+ ignoreChanges = true;
+ editPresetFile->setURL(f);
+ ignoreChanges = false;
+ return true;
+}
+
+
+void RadioConfiguration::slotStationSelectionChanged(int idx)
+{
+ RadioStation *s = NULL;
+
+ if (idx >= 0 && idx < m_stations.count()) {
+ s = &m_stations.at(idx);
+ }
+
+ editStationName ->setDisabled(!s);
+ labelStationName ->setDisabled(!s);
+ editPixmapFile ->setDisabled(!s);
+ labelPixmapFile ->setDisabled(!s);
+ editStationShortName ->setDisabled(!s);
+ labelStationShortName ->setDisabled(!s);
+ editVolumePreset ->setDisabled(!s);
+ labelVolumePreset ->setDisabled(!s);
+ buttonSelectPixmapFile->setDisabled(!s);
+ buttonDeleteStation ->setDisabled(!s);
+
+ buttonStationUp ->setDisabled(!s || idx == 0);
+ buttonStationDown ->setDisabled(!s || idx == m_stations.count()-1);
+
+ if (ignoreChanges) return;
+ ignoreChanges = true;
+
+ editStationName ->setText (s ? s->name() : TQString());
+ editStationShortName ->setText (s ? s->shortName() : TQString());
+ editPixmapFile ->setText (s ? s->iconName() : TQString());
+ editVolumePreset ->setValue (s ? (int)rint(s->initialVolume()*100) : -1);
+
+ TQPixmap pixmap(s ? s->iconName() : TQString());
+ if (!pixmap.isNull()) {
+ pixmapStation->setPixmap(pixmap);
+ } else {
+ pixmapStation->setText("");
+ }
+
+
+ stackStationEdit->setDisabled(!s);
+ if (s) {
+ RadioStationConfig *c = stationEditors.find(s->getClassName());
+ if (!c) {
+ c = s->createEditor();
+ if (c) {
+ c->reparent(this, TQPoint(0,0), true);
+ TQObject::connect(c, TQT_SIGNAL(changed(RadioStationConfig*)),
+ this, TQT_SLOT(slotStationEditorChanged(RadioStationConfig*)));
+ stationEditors.insert(s->getClassName(), c);
+ stackStationEdit->addWidget(c);
+ }
+ }
+ if (c) {
+ c->setStationData(*s);
+ stackStationEdit->raiseWidget(c);
+ }
+ }
+
+ ignoreChanges = false;
+}
+
+
+void RadioConfiguration::slotNewStation()
+{
+ slotSetDirty();
+ const RadioStation *st = &queryCurrentStation();
+ int n = m_stations.count();
+ m_stations.all().append(st);
+ if (m_stations.count() == n) {
+ st = st->copyNewID();
+ m_stations.all().append(st);
+ }
+ if (m_stations.count() > n) {
+ listStations->appendStation(*st);
+ listStations->setCurrentStation (listStations->count()-1);
+ slotStationSelectionChanged(listStations->count()-1);
+ listStations->ensureItemVisible(listStations->selectedItem());
+ }
+}
+
+
+void RadioConfiguration::slotDeleteStation()
+{
+ int idx = listStations->currentStationIndex();
+
+ if (idx >= 0 && idx < m_stations.count()) {
+ slotSetDirty();
+ m_stations.all().remove(idx);
+ listStations->removeStation(idx);
+ }
+}
+
+
+void RadioConfiguration::slotStationEditorChanged(RadioStationConfig *c)
+{
+ if (!c) return;
+ if (ignoreChanges) return;
+
+
+ int idx = listStations->currentStationIndex();
+ if (idx >= 0 && idx < m_stations.count()) {
+ slotSetDirty();
+ RadioStation &st = m_stations.at(idx);
+
+ ignoreChanges = true;
+ bool o = listStations->signalsBlocked();
+ listStations->blockSignals(true);
+
+ c->storeStationData(st);
+ listStations->setStation(idx, st);
+
+ listStations->blockSignals(o);
+ ignoreChanges = false;
+ }
+}
+
+
+void RadioConfiguration::slotStationNameChanged( const TQString & s)
+{
+ if (ignoreChanges) return;
+
+ int idx = listStations->currentStationIndex();
+ if (idx >= 0 && idx < m_stations.count()) {
+ slotSetDirty();
+ RadioStation &st = m_stations.at(idx);
+ st.setName(s);
+ ignoreChanges = true;
+ bool o = listStations->signalsBlocked();
+ listStations->blockSignals(true);
+ listStations->setStation(idx, st);
+ listStations->blockSignals(o);
+ ignoreChanges = false;
+ }
+}
+
+
+void RadioConfiguration::slotStationShortNameChanged( const TQString & sn)
+{
+ if (ignoreChanges) return;
+
+ int idx = listStations->currentStationIndex();
+ if (idx >= 0 && idx < m_stations.count()) {
+ slotSetDirty();
+ RadioStation &st = m_stations.at(idx);
+ st.setShortName(sn);
+ ignoreChanges = true;
+ bool o = listStations->signalsBlocked();
+ listStations->blockSignals(true);
+ listStations->setStation(idx, st);
+ listStations->blockSignals(o);
+ ignoreChanges = false;
+ }
+}
+
+
+void RadioConfiguration::slotSelectPixmap()
+{
+ KURL url = KFileDialog::getImageOpenURL(TQString(), this,
+ i18n("Image Selection"));
+ if (!url.isEmpty()) {
+ if (url.isLocalFile()) {
+ editPixmapFile->setText(url.path());
+ } else {
+ m_logger.logWarning(i18n("ignoring non-local image"));
+ }
+ }
+}
+
+
+void RadioConfiguration::slotPixmapChanged( const TQString &s )
+{
+ if (ignoreChanges) return;
+
+ int idx = listStations->currentStationIndex();
+ if (idx >= 0 && idx < m_stations.count()) {
+ slotSetDirty();
+ RadioStation &st = m_stations.at(idx);
+ st.setIconName(s);
+ ignoreChanges = true;
+ pixmapStation->setPixmap(TQPixmap(s));
+ bool o = listStations->signalsBlocked();
+ listStations->blockSignals(true);
+ listStations->setStation(idx, st);
+ listStations->blockSignals(o);
+ ignoreChanges = false;
+ }
+}
+
+
+void RadioConfiguration::slotVolumePresetChanged(int v)
+{
+ int idx = listStations->currentStationIndex();
+ if (idx >= 0 && idx < m_stations.count()) {
+ slotSetDirty();
+ RadioStation &s = m_stations.at(idx);
+ s.setInitialVolume(0.01 * (double)v);
+ }
+}
+
+
+
+void RadioConfiguration::slotStationUp()
+{
+ int idx = listStations->currentStationIndex();
+ if (idx > 0 && idx < m_stations.count()) {
+ slotSetDirty();
+ RawStationList &sl = m_stations.all();
+
+ RadioStation *st = sl.take(idx-1);
+ sl.insert(idx, st);
+ delete st;
+
+ ignoreChanges = true;
+// bool o = listStations->signalsBlocked();
+// listStations->blockSignals(true);
+ listStations->setStation(idx-1, *sl.at(idx-1));
+ listStations->setStation(idx, *sl.at(idx));
+ listStations->setCurrentStation(idx-1);
+// listStations->blockSignals(o);
+ ignoreChanges = false;
+ }
+}
+
+
+void RadioConfiguration::slotStationDown()
+{
+ int idx = listStations->currentStationIndex();
+ if (idx >= 0 && idx < m_stations.count() - 1) {
+ slotSetDirty();
+ RawStationList &sl = m_stations.all();
+
+ RadioStation *st = sl.take(idx);
+ sl.insert(idx+1, st);
+ delete st;
+
+ ignoreChanges = true;
+// bool o = listStations->signalsBlocked();
+// listStations->blockSignals(true);
+ listStations->setStation(idx, *sl.at(idx));
+ listStations->setStation(idx+1, *sl.at(idx+1));
+ listStations->setCurrentStation(idx+1);
+// listStations->blockSignals(o);
+ ignoreChanges = false;
+ }
+}
+
+
+void RadioConfiguration::slotActivateStation(int idx)
+{
+ if (idx >= 0 && idx < m_stations.count()) {
+ sendActivateStation(m_stations.at(idx));
+ sendPowerOn();
+ }
+}
+
+void RadioConfiguration::slotLoadPresets()
+{
+ KFileDialog fd(locate("data", "tderadio/presets/"),
+ ("*.krp|" + i18n("TDERadio Preset Files")).ascii(),
+ this,
+ i18n("Preset File Selection").ascii(),
+ true);
+ fd.setMode(KFile::File | KFile::ExistingOnly);
+ fd.setCaption (i18n("Select Preset File"));
+
+ if (fd.exec() == TQDialog::Accepted) {
+ slotSetDirty();
+ StationList sl;
+ if (sl.readXML(fd.selectedURL(), m_logger)) {
+ noticeStationsChanged(sl);
+ }
+ }
+}
+
+
+void RadioConfiguration::slotStorePresets()
+{
+ KFileDialog fd("",
+ ("*.krp|" + i18n("TDERadio Preset Files")).ascii(),
+ this,
+ i18n("Preset File Selection").ascii(),
+ true);
+ fd.setMode(KFile::File);
+ fd.setCaption (i18n("Store Preset File"));
+
+ if (fd.exec() == TQDialog::Accepted) {
+ editPresetFile->setURL(fd.selectedURL().url());
+ m_stations.writeXML(fd.selectedURL(), m_logger);
+ }
+}
+
+
+void RadioConfiguration::slotLastChangeNow()
+{
+ slotSetDirty();
+ editLastChange->setDateTime(TQDateTime::currentDateTime());
+}
+
+
+static TQString &urlEscapes(TQString &s)
+{
+ s.replace(TQRegExp("%"), "%25");
+ s.replace(TQRegExp("\t"), "%09");
+ s.replace(TQRegExp("\n"), "%0A");
+ s.replace(TQRegExp("\n"), "%0D");
+ s.replace(TQRegExp(" "), "%20");
+ s.replace(TQRegExp("\\!"), "%21");
+ s.replace(TQRegExp("\""), "%22");
+ s.replace(TQRegExp("#"), "%23");
+ s.replace(TQRegExp("\\$"), "%24");
+ s.replace(TQRegExp("\\&"), "%26");
+ s.replace(TQRegExp("'"), "%27");
+ s.replace(TQRegExp(","), "%2C");
+ s.replace(TQRegExp(":"), "%3A");
+ s.replace(TQRegExp(";"), "%3B");
+ s.replace(TQRegExp("="), "%3D");
+ s.replace(TQRegExp("\\?"), "%3F");
+ return s;
+}
+
+void RadioConfiguration::slotSendPresetsByMail( const TQString &url )
+{
+ TQString presets = m_stations.writeXML(m_logger);
+
+ urlEscapes(presets);
+
+ // documentation says, krun object deletes itself,
+ // so we do not need to store the pointer
+
+ TQString country = m_stations.metaData().country;
+ TQString city = m_stations.metaData().city;
+ TQString location = city + "/" + country;
+ urlEscapes(location);
+
+ TQString cmd = url + "?subject=station preset file for " + location + "&body=";
+
+ cmd += presets;
+ new KRun (cmd);
+}
+
+
+void RadioConfiguration::slotSearchStations(int idev)
+{
+ if (idev >= 0 && (unsigned)idev < devices.count()) {
+ IRadioDevice *dev = devices.at(idev);
+
+ StandardScanDialog *x = new StandardScanDialog(NULL);
+ x->connectI(dev); // connect device
+ x->connectI(IRadioDevicePoolClient::iConnections.at(0)); // connect radio to get verbous station information
+ sendActiveDevice(dev);
+ x->show();
+ x->start();
+ if (x->exec() == TQDialog::Accepted) {
+ slotSetDirty();
+ m_stations.merge(x->getStations());
+ noticeStationsChanged(m_stations);
+ }
+ delete x;
+// logDebug("scan finished");
+ }
+// logDebug("scan finished completely");
+}
+
+
+void RadioConfiguration::slotOK()
+{
+ if (m_dirty) {
+ StationListMetaData &i = m_stations.metaData();
+
+ i.maintainer = editMaintainer->text();
+ i.lastChange = editLastChange->dateTime();
+ i.country = editCountry->text();
+ i.city = editCity->text();
+ i.media = editMedia->text();
+ i.comment = editComment->text();
+
+ sendStations(m_stations);
+ sendPresetFile(editPresetFile->url());
+ m_dirty = false;
+ }
+}
+
+void RadioConfiguration::slotCancel()
+{
+ if (m_dirty) {
+ noticeStationsChanged(queryStations());
+ noticePresetFileChanged(queryPresetFile());
+ m_dirty = false;
+ }
+}
+
+
+void RadioConfiguration::slotSetDirty()
+{
+ if (!ignoreChanges) {
+ m_dirty = true;
+ }
+}
+
+
+#include "radio-configuration.moc"
diff --git a/plugins/radio/radio-configuration.h b/plugins/radio/radio-configuration.h
new file mode 100644
index 0000000..4e01ad9
--- /dev/null
+++ b/plugins/radio/radio-configuration.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ radio-configuration.h - description
+ -------------------
+ begin : Son Aug 3 2003
+ copyright : (C) 2003 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_RADIO_CONFIGURATION_H
+#define KRADIO_RADIO_CONFIGURATION_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tqdict.h>
+
+#include "../../src/include/radio_interfaces.h"
+#include "../../src/include/stationlist.h"
+#include "../../src/include/radiodevicepool_interfaces.h"
+#include "radio-configuration-ui.h"
+
+class TQPopupMenu;
+class RadioStationConfig;
+
+class RadioConfiguration : public RadioConfigurationUI,
+ public IRadioClient,
+ public IRadioDevicePoolClient
+{
+Q_OBJECT
+
+public :
+ RadioConfiguration (TQWidget *parent, const IErrorLogClient &m_logger);
+ ~RadioConfiguration ();
+
+ bool connectI (Interface *i);
+ bool disconnectI (Interface *i);
+
+ // IRadioDevicePoolClient
+
+RECEIVERS:
+ bool noticeActiveDeviceChanged(IRadioDevice *) { return false; }
+ bool noticeDevicesChanged(const TQPtrList<IRadioDevice> &);
+ bool noticeDeviceDescriptionChanged(const TQString &);
+
+ // IRadioClient
+
+RECEIVERS:
+ bool noticePowerChanged(bool /*on*/) { return false; } // don't care
+ bool noticeStationChanged (const RadioStation &, int /*idx*/) { return false; } // don't care
+ bool noticeStationsChanged(const StationList &sl);
+ bool noticePresetFileChanged(const TQString &f);
+
+ bool noticeCurrentSoundStreamIDChanged(SoundStreamID /*id*/) { return false; }
+
+protected slots:
+
+ void slotStationSelectionChanged(int idx);
+ void slotNewStation();
+ void slotDeleteStation();
+ void slotStationEditorChanged(RadioStationConfig *c);
+ void slotStationNameChanged( const TQString & s);
+ void slotStationShortNameChanged( const TQString & sn);
+ void slotPixmapChanged( const TQString &s );
+ void slotSelectPixmap();
+ void slotVolumePresetChanged(int v);
+ void slotStationUp();
+ void slotStationDown();
+ void slotActivateStation( int );
+ void slotLoadPresets();
+ void slotStorePresets();
+ void slotLastChangeNow();
+ void slotSendPresetsByMail( const TQString &url );
+
+ void slotSearchStations(int i);
+ void slotSearchStations0() { slotSearchStations(0); }
+
+ void slotOK();
+ void slotCancel();
+ void slotSetDirty();
+
+
+protected:
+
+ StationList m_stations;
+ bool ignoreChanges;
+
+ TQPopupMenu *devicePopup;
+ TQPtrList<IRadioDevice> devices;
+
+ TQDict<RadioStationConfig> stationEditors;
+
+ const IErrorLogClient &m_logger;
+ bool m_dirty;
+};
+
+#endif
+
diff --git a/plugins/radio/radio.cpp b/plugins/radio/radio.cpp
new file mode 100644
index 0000000..4e853ce
--- /dev/null
+++ b/plugins/radio/radio.cpp
@@ -0,0 +1,497 @@
+/***************************************************************************
+ radio.cpp - description
+ -------------------
+ begin : Sat March 29 2003
+ copyright : (C) 2003 by Klas Kalass, Ernst Martin Witte
+ email : klas@kde.org, 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 "../../src/include/radiostation.h"
+#include "../../src/include/aboutwidget.h"
+#include "../../src/include/radiodevice_interfaces.h"
+#include "radio.h"
+#include "radio-configuration.h"
+
+#include <kstandarddirs.h>
+#include <kurl.h>
+#include <tdeaboutdata.h>
+#include <tdeconfig.h>
+
+#include "../../src/include/debug-profiler.h"
+
+///////////////////////////////////////////////////////////////////////
+//// plugin library functions
+
+PLUGIN_LIBRARY_FUNCTIONS(Radio, "tderadio-radio", i18n("Central Radio Device Multiplexer"));
+
+/////////////////////////////////////////////////////////////////////////////
+
+Radio::Radio(const TQString &name)
+ : PluginBase(name, i18n("Radio Multiplexer Plugin")),
+ IRadioDeviceClient(-1),
+ m_presetFile(locateLocal("data", "tderadio/stations.krp")),
+ m_activeDevice (NULL)
+{
+}
+
+
+Radio::~Radio()
+{
+}
+
+
+bool Radio::connectI (Interface *i)
+{
+ bool a = IRadio::connectI(i);
+ bool b = IRadioDeviceClient::connectI(i);
+ bool c = IRadioDevicePool::connectI(i);
+ bool d = PluginBase::connectI(i);
+ bool e = ISoundStreamClient::connectI(i);
+
+ // no "return IA::connectI() | return IB::connnectI to
+ // prevent "early termination" optimization in boolean expressions
+ return a || b || c || d || e;
+}
+
+
+bool Radio::disconnectI (Interface *i)
+{
+ bool a = IRadio::disconnectI(i);
+ bool b = IRadioDeviceClient::disconnectI(i);
+ bool c = IRadioDevicePool::disconnectI(i);
+ bool d = PluginBase::disconnectI(i);
+ bool e = ISoundStreamClient::disconnectI(i);
+
+ // no "return IA::disconnectI() | return IB::disconnnectI to
+ // prevent "early termination" optimization in boolean expressions
+ return a || b || c || d || e;
+}
+
+
+void Radio::saveState (TDEConfig *config) const
+{
+ config->setGroup(TQString("radio-") + name());
+
+ config->writeEntry("presetfile", m_presetFile);
+
+ m_stationList.writeXML(m_presetFile, *this);
+}
+
+
+void Radio::restoreState (TDEConfig *config)
+{
+ config->setGroup(TQString("radio-") + name());
+
+ m_presetFile = config->readEntry("presetfile",
+ TQString());
+ bool first_restore = false;
+ if (m_presetFile.isNull() || m_presetFile.length() == 0) {
+ m_presetFile = locateLocal("data", "tderadio/stations.krp");
+ first_restore = true;
+ }
+
+ m_stationList.readXML(KURL(m_presetFile), *this, /*enable-messagebox*/ !first_restore);
+
+ notifyStationsChanged(m_stationList);
+ notifyPresetFileChanged(m_presetFile);
+}
+
+
+
+ConfigPageInfo Radio::createConfigurationPage()
+{
+ RadioConfiguration *conf = new RadioConfiguration (NULL, *this);
+ connectI (conf);
+ return ConfigPageInfo(
+ conf,
+ i18n("Radio Stations"),
+ i18n("Setup Radio Stations"),
+ "tderadio"
+ );
+}
+
+
+AboutPageInfo Radio::createAboutPage()
+{
+/* TDEAboutData aboutData("tderadio",
+ NULL,
+ NULL,
+ I18N_NOOP("Radio Device Multiplexer and Station Management for TDERadio"),
+ TDEAboutData::License_GPL,
+ "(c) 2002-2005 Martin Witte, Klas Kalass",
+ 0,
+ "http://sourceforge.net/projects/tderadio",
+ 0);
+ aboutData.addAuthor("Martin Witte", "", "witte@kawo1.rwth-aachen.de");
+ aboutData.addAuthor("Klas Kalass", "", "klas.kalass@gmx.de");
+
+ return AboutPageInfo(
+ new TDERadioAboutWidget(aboutData, TDERadioAboutWidget::AbtTabbed),
+ i18n("Device and Station Management"),
+ i18n("Radio Device Multiplexer and Station Management"),
+ "tderadio"
+ );
+*/
+ return AboutPageInfo();
+}
+
+
+
+
+
+
+/* IRadio Interface Methods
+*/
+
+/* offer new station to current device.
+ if that does not accept, try all other devices.
+ Any device will be powered off if it does not accept the station
+*/
+
+bool Radio::activateStation (const RadioStation &rs) {
+
+ if (sendActivateStation(rs)) { // first try activeDevice
+
+ return true;
+
+ } else { // hmm... active device did not want it. Try others...
+
+ int n = 0;
+
+ for (IRadioDeviceClient::IFIterator it(IRadioDeviceClient::iConnections); it.current(); ++it) {
+
+ if (it.current()->activateStation(rs)) {
+
+ setActiveDevice(it.current()); // select new device
+ ++n;
+
+ } else {
+
+ it.current()->powerOff();
+
+ }
+ }
+
+ return n > 0;
+ }
+}
+
+
+bool Radio::activateStation(int index)
+{
+ if (index < 0 || index >= m_stationList.count())
+ return false;
+
+ return activateStation(m_stationList.at(index));
+}
+
+
+bool Radio::setStations(const StationList &sl)
+{
+ if (true/*m_stationList != sl*/) {
+ BlockProfiler("Radio::setStations");
+ m_stationList = sl;
+ notifyStationsChanged(m_stationList);
+ }
+ return true;
+}
+
+bool Radio::setPresetFile(const TQString &presetFile)
+{
+ if (m_presetFile != presetFile) {
+ m_presetFile = presetFile;
+ notifyPresetFileChanged(m_presetFile);
+ }
+ return true;
+}
+
+int Radio::getStationIdx(const RadioStation &rs) const
+{
+ RawStationList &sl = const_cast<RawStationList&>(m_stationList.all());
+ return sl.find(&rs);
+}
+
+int Radio::getCurrentStationIdx() const
+{
+ return getStationIdx(getCurrentStation());
+}
+
+SoundStreamID Radio::getCurrentSoundStreamID() const
+{
+ return queryCurrentSoundStreamID();
+}
+
+
+/* IRadioDevicePool Interface Methods
+
+*/
+
+
+bool Radio::setActiveDevice(IRadioDevice *rd, bool keepPower)
+{
+ // do nothing if old == new
+ if (m_activeDevice == rd)
+ return true;
+
+ // check if new station is in "connections"
+ // special case: rd == NULL: power off active device, new active device = NULL
+
+ if (!rd || IRadioDeviceClient::iConnections.containsRef(rd)) { // new device is ok
+
+ // save old power state and power off old device
+ bool oldPowerOn = false;
+ if (m_activeDevice) {
+ oldPowerOn = m_activeDevice->isPowerOn();
+ m_activeDevice->powerOff();
+ }
+
+ // setup new active device && send notifications
+ m_activeDevice = rd;
+
+ // send notifications
+ notifyActiveDeviceChanged(m_activeDevice);
+ notifyCurrentSoundStreamIDChanged(queryCurrentSoundStreamID());
+ const RadioStation &rs = queryCurrentStation();
+ notifyStationChanged(rs, getStationIdx(rs));
+
+ if (keepPower)
+ oldPowerOn ? sendPowerOn() : sendPowerOff();
+
+ return true;
+
+ } else {
+ return false;
+ }
+}
+
+
+IRadioDevice *Radio::getActiveDevice() const
+{
+ return m_activeDevice;
+}
+
+
+const TQPtrList<IRadioDevice> &Radio::getDevices() const
+{
+ return IRadioDeviceClient::iConnections;
+}
+
+
+const TQString &Radio::getDeviceDescription() const
+{
+ return queryDescription();
+}
+
+
+
+/* IRadioDeviceClient Interface Methods
+
+ Many things are overwritten, particularly all sending methods
+
+*/
+
+int Radio::sendPowerOn() const
+{
+ return m_activeDevice ? m_activeDevice->powerOn() : 0;
+}
+
+
+int Radio::sendPowerOff() const
+{
+ return m_activeDevice ? m_activeDevice->powerOff() : 0;
+}
+
+int Radio::sendActivateStation (const RadioStation &rs) const
+{
+ return m_activeDevice ? m_activeDevice->activateStation(rs) : 0;
+}
+
+
+
+bool Radio::queryIsPowerOn() const
+{
+ return m_activeDevice ? m_activeDevice->isPowerOn() : false;
+}
+
+
+bool Radio::queryIsPowerOff() const
+{
+ return m_activeDevice ? m_activeDevice->isPowerOff() : true;
+}
+
+
+const RadioStation & Radio::queryCurrentStation() const
+{
+ if (m_activeDevice) {
+ RadioStation &rs = const_cast<RadioStation&>(m_activeDevice->getCurrentStation());
+ int idx = getStationIdx(rs);
+
+ if (idx >= 0) {
+ rs.copyDescriptionFrom(m_stationList.at(idx));
+ } else {
+ rs.copyDescriptionFrom(undefinedRadioStation);
+ }
+
+ return rs;
+ } else {
+ return undefinedRadioStation;
+ }
+}
+
+
+static TQString qstrUnknown(I18N_NOOP("unknown"));
+static TQString i18nqstrUnknown;
+const TQString &Radio::queryDescription() const
+{
+ return m_activeDevice ? m_activeDevice->getDescription() : (i18nqstrUnknown = i18n(qstrUnknown.ascii()));
+}
+
+
+
+bool Radio::noticePowerChanged (bool on, const IRadioDevice *sender)
+{
+ if (on) {
+ setActiveDevice(const_cast<IRadioDevice*>(sender), false);
+ // false: do not set power state on new device
+ // constcast valid because power-state of sender is not changed
+ notifyPowerChanged(true);
+ return true;
+
+ } else {
+ if (sender == m_activeDevice) {
+ sendStopCountdown();
+ notifyPowerChanged(false);
+ return true;
+ }
+ return false;
+ }
+}
+
+
+bool Radio::noticeStationChanged (const RadioStation &_rs, const IRadioDevice *sender)
+{
+ RadioStation &rs = const_cast<RadioStation&>(_rs);
+ int idx = getStationIdx(rs);
+
+ RadioStation &known = (idx >= 0) ? (RadioStation&)m_stationList.at(idx) :
+ (RadioStation&)undefinedRadioStation;
+ rs.copyDescriptionFrom(known);
+
+ if (sender == m_activeDevice)
+ notifyStationChanged(rs, idx);
+ return true;
+}
+
+
+bool Radio::noticeDescriptionChanged (const TQString &s, const IRadioDevice *sender)
+{
+ if (sender == m_activeDevice)
+ notifyDeviceDescriptionChanged(s);
+ return true;
+}
+
+
+bool Radio::noticeCurrentSoundStreamIDChanged(SoundStreamID id, const IRadioDevice *sender)
+{
+ if (sender == m_activeDevice)
+ notifyCurrentSoundStreamIDChanged(id);
+ return true;
+}
+
+
+SoundStreamID Radio::queryCurrentSoundStreamID() const
+{
+ return m_activeDevice ? m_activeDevice->getCurrentSoundStreamID() : SoundStreamID::InvalidID;
+}
+
+
+
+void Radio::noticeConnectedI(IRadioDeviceClient::cmplInterface *dev, bool pointer_valid)
+{
+ IRadioDeviceClient::noticeConnectedI(dev, pointer_valid);
+
+ if (! m_activeDevice && pointer_valid)
+ setActiveDevice (dev, false);
+
+ notifyDevicesChanged(IRadioDeviceClient::iConnections);
+}
+
+
+void Radio::noticeDisconnectI(IRadioDeviceClient::cmplInterface *rd, bool pointer_valid)
+{
+ IRadioDeviceClient::noticeDisconnectI(rd, pointer_valid);
+
+ if (rd == m_activeDevice) {
+
+ // search a new active device
+ if (IRadioDeviceClient::iConnections.findRef(rd) >= 0) {
+
+ IRadioDevice *new_rd = NULL;
+
+ new_rd = IRadioDeviceClient::iConnections.next(); // choose next device as active device if next exists
+ if (!new_rd) {
+ IRadioDeviceClient::iConnections.findRef(rd);
+ new_rd = IRadioDeviceClient::iConnections.prev(); // otherwise try prev then, may be NULL (no connections)
+ }
+ setActiveDevice(new_rd);
+
+ } else {
+ // strange error occurred, m_activeDevice not in connections... set to first.
+
+ setActiveDevice(IRadioDeviceClient::iConnections.first());
+ }
+ }
+ notifyDevicesChanged(IRadioDeviceClient::iConnections);
+}
+
+
+// ITimeControlClient
+
+bool Radio::noticeAlarm(const Alarm &a)
+{
+ if (a.alarmType() == Alarm::StartPlaying ||
+ a.alarmType() == Alarm::StartRecording)
+ {
+ const RawStationList &sl = getStations().all();
+ const RadioStation &rs = sl.stationWithID(a.stationID());
+ activateStation(rs);
+ powerOn();
+
+ if (a.volumePreset() >= 0)
+ sendPlaybackVolume(getCurrentSoundStreamID(), a.volumePreset());
+
+ SoundStreamID id = getCurrentSoundStreamID();
+ bool r = false;
+ SoundFormat sf;
+ queryIsRecordingRunning(id, r, sf);
+ if (a.alarmType() == Alarm::StartRecording && !r)
+ sendStartRecording(id);
+
+ } else {
+ powerOff();
+ }
+ return true;
+}
+
+
+bool Radio::noticeCountdownZero()
+{
+ powerOff();
+ return true;
+}
+
+
+void Radio::aboutToQuit()
+{
+ sendPowerOff();
+}
+
diff --git a/plugins/radio/radio.h b/plugins/radio/radio.h
new file mode 100644
index 0000000..66798fb
--- /dev/null
+++ b/plugins/radio/radio.h
@@ -0,0 +1,167 @@
+/***************************************************************************
+ radio.h - description
+ -------------------
+ begin : Sat March 29 2003
+ copyright : (C) 2003 by Klas Kalass, Ernst Martin Witte
+ email : klas@kde.org, 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_RADIO_H
+#define KRADIO_RADIO_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include "../../src/include/radio_interfaces.h"
+#include "../../src/include/radiodevicepool_interfaces.h"
+#include "../../src/include/radiodevice_interfaces.h"
+#include "../../src/include/timecontrol_interfaces.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+#include "../../src/include/stationlist.h"
+#include "../../src/include/plugins.h"
+
+/**
+ * The main Radio class, which is used as the interface of the radio functionality
+ * to the GUI parts of the application
+ * @author Klas Kalass, Ernst Martin Witte
+ */
+
+/////////////////////////////////////////////////////////////////////////////
+
+/* A class, that is able to manage more than one radio device, one of those
+ is active at a time. This class behaves represents the active device,
+ the active devices can be changed either by selecting a station or by
+ explicitly changing the devices.
+
+ At any time a valid active device exists as long as any device is connected.
+
+*/
+
+class Radio : public PluginBase,
+ public IRadio,
+ public IRadioDevicePool,
+ public IRadioDeviceClient,
+ public ITimeControlClient,
+ public ISoundStreamClient
+{
+public:
+ Radio(const TQString &name);
+ ~Radio();
+
+
+ // PluginBase
+
+public:
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+ virtual TQString pluginClassName() const { return "Radio"; }
+
+ virtual const TQString &name() const { return PluginBase::name(); }
+ virtual TQString &name() { return PluginBase::name(); }
+
+ virtual ConfigPageInfo createConfigurationPage();
+ virtual AboutPageInfo createAboutPage();
+
+ virtual void aboutToQuit();
+
+ // IRadio methods
+
+RECEIVERS:
+ bool powerOn() { return sendPowerOn() > 0; }
+ bool powerOff() { return sendPowerOff() > 0; }
+ bool activateStation(const RadioStation &rs);
+ bool activateStation(int index);
+ bool setStations(const StationList &sl);
+ bool setPresetFile(const TQString &presetFile);
+
+ANSWERS:
+ bool isPowerOn() const { return queryIsPowerOn(); }
+ bool isPowerOff() const { return queryIsPowerOff(); }
+ const RadioStation & getCurrentStation() const { return queryCurrentStation(); }
+ int getStationIdx(const RadioStation &) const;
+ int getCurrentStationIdx() const;
+ const StationList & getStations() const { return m_stationList; }
+ const TQString & getPresetFile() const { return m_presetFile; }
+
+ SoundStreamID getCurrentSoundStreamID() const;
+
+
+public:
+ bool connectI (Interface *i);
+ bool disconnectI (Interface *i);
+
+ void noticeConnectedI (IRadioDeviceClient::cmplInterface *i, bool pointer_valid);
+ void noticeDisconnectI(IRadioDeviceClient::cmplInterface *i, bool pointer_valid);
+
+ // IRadioDevicePool methods
+
+RECEIVERS:
+ bool setActiveDevice(IRadioDevice *rd, bool keepPower = true);
+
+ANSWERS:
+ IRadioDevice * getActiveDevice() const;
+ const TQPtrList<IRadioDevice> & getDevices() const;
+ const TQString & getDeviceDescription() const;
+
+
+
+ // IRadioDeviceClient methods, even sending methods overwritten
+ // to provide "1-of-N" functionality
+
+SENDERS:
+ IF_SENDER ( sendPowerOn() )
+ IF_SENDER ( sendPowerOff() )
+ IF_SENDER ( sendActivateStation (const RadioStation &rs) )
+
+QUERIES:
+ IF_QUERY ( bool queryIsPowerOn() )
+ IF_QUERY ( bool queryIsPowerOff() )
+ IF_QUERY ( const RadioStation & queryCurrentStation() )
+ IF_QUERY ( const TQString & queryDescription() )
+ IF_QUERY ( SoundStreamID queryCurrentSoundStreamID() )
+
+RECEIVERS:
+ virtual bool noticePowerChanged (bool on, const IRadioDevice *sender = NULL);
+ virtual bool noticeStationChanged (const RadioStation &rs, const IRadioDevice *sender = NULL);
+ virtual bool noticeDescriptionChanged (const TQString &, const IRadioDevice *sender = NULL);
+
+ virtual bool noticeCurrentSoundStreamIDChanged(SoundStreamID id, const IRadioDevice *sender = NULL);
+
+ // ITimeControlClient
+
+RECEIVERS:
+ bool noticeAlarmsChanged(const AlarmVector &) { return false; } // ignore
+ bool noticeAlarm(const Alarm &);
+ bool noticeNextAlarmChanged(const Alarm *) { return false; } // ignore
+ bool noticeCountdownStarted(const TQDateTime &/*end*/){ return false; } // ignore
+ bool noticeCountdownStopped() { return false; } // ignore
+ bool noticeCountdownZero();
+ bool noticeCountdownSecondsChanged(int /*n*/) { return false; } // ignore
+
+ // ISoundStreamClient
+
+RECEIVERS:
+
+ // ...
+
+protected:
+
+ TQString m_presetFile;
+ StationList m_stationList;
+ IRadioDevice *m_activeDevice;
+};
+
+
+#endif
diff --git a/plugins/recording/CMakeL10n.txt b/plugins/recording/CMakeL10n.txt
new file mode 100644
index 0000000..11d0cab
--- /dev/null
+++ b/plugins/recording/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-recording"
+ DESTINATION "po"
+)
diff --git a/plugins/recording/Makefile.am b/plugins/recording/Makefile.am
new file mode 100644
index 0000000..f45f5fb
--- /dev/null
+++ b/plugins/recording/Makefile.am
@@ -0,0 +1,22 @@
+SUBDIRS = po icons .
+
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = librecording.la
+librecording_la_SOURCES = recording-configuration.cpp \
+ recording-configuration-ui.ui recording.cpp recording-config.cpp reccfg_interfaces.cpp encoder.cpp \
+ recording-datamonitor.cpp recording-monitor.cpp encoder_mp3.cpp encoder_ogg.cpp encoder_pcm.cpp
+librecording_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+librecording_la_LIBADD = $(LIB_OGG) $(LIB_LAME)
+
+noinst_HEADERS = recording-configuration.h recording.h recording-config.h \
+ reccfg_interfaces.h encoder.h soundstreamevent.h recording-datamonitor.h \
+ recording-monitor.h encoder_mp3.h encoder_ogg.h encoder_pcm.h
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-recording.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-recording.pot
diff --git a/plugins/recording/encoder.cpp b/plugins/recording/encoder.cpp
new file mode 100644
index 0000000..b1c054f
--- /dev/null
+++ b/plugins/recording/encoder.cpp
@@ -0,0 +1,172 @@
+/***************************************************************************
+ encoder.cpp - description
+ -------------------
+ begin : Thu May 05 2005
+ copyright : (C) 2005 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 "../../src/include/radiostation.h"
+#include "../../src/include/errorlog-interfaces.h"
+#include "../../src/include/aboutwidget.h"
+
+#include "recording.h"
+#include "recording-configuration.h"
+#include "soundstreamevent.h"
+
+#include <tqsocketnotifier.h>
+#include <tqevent.h>
+#include <tqapplication.h>
+#include <tqregexp.h>
+
+#include <tdeconfig.h>
+#include <tdeversion.h>
+#include <tdelocale.h>
+
+RecordingEncoding::RecordingEncoding(TQObject *parent, SoundStreamID ssid,
+ const RecordingConfig &cfg, const RadioStation *rs,
+ const TQString &filename)
+ :
+ m_parent(parent),
+ m_config(cfg),
+ m_RadioStation(rs ? rs->copy() : NULL),
+ m_SoundStreamID(ssid),
+ m_error(false),
+ m_errorString(TQString()),
+ m_done(false),
+ m_InputBuffers(m_config.m_EncodeBufferCount < 3 ? 3 : m_config.m_EncodeBufferCount,
+ m_config.m_EncodeBufferSize < 4096 ? 4096 : m_config.m_EncodeBufferSize),
+ m_buffersMetaData(NULL),
+ m_encodedSize(0),
+ m_InputStartTime(0),
+ m_InputStartPosition(0),
+ m_outputURL(filename)
+{
+
+ if (m_config.m_EncodeBufferCount < 3)
+ m_config.m_EncodeBufferCount = 3;
+ if (m_config.m_EncodeBufferSize < 4096)
+ m_config.m_EncodeBufferSize = 4096;
+
+ m_buffersMetaData = new TQPtrList<BufferSoundMetaData> *[m_config.m_EncodeBufferCount];
+ for (size_t i = 0; i < m_config.m_EncodeBufferCount; ++i) {
+ m_buffersMetaData [i] = new TQPtrList<BufferSoundMetaData>;
+ m_buffersMetaData [i]->setAutoDelete(true);
+ }
+}
+
+
+RecordingEncoding::~RecordingEncoding()
+{
+ for (size_t i = 0; i < m_config.m_EncodeBufferCount; ++i) {
+ delete m_buffersMetaData[i];
+ }
+ delete m_buffersMetaData;
+ delete m_RadioStation;
+}
+
+
+char *RecordingEncoding::lockInputBuffer(size_t &bufferSize)
+{
+ if (m_done || m_error)
+ return NULL;
+ char * retval = m_InputBuffers.lockWriteBuffer(bufferSize);
+
+ m_error |= m_InputBuffers.hasError();
+ m_errorString += m_InputBuffers.getErrorString();
+ m_InputBuffers.resetError();
+
+ return retval;
+}
+
+
+void RecordingEncoding::unlockInputBuffer(size_t bufferSize, const SoundMetaData &md)
+{
+ if (m_done)
+ return;
+ size_t bufidx = m_InputBuffers.getCurrentWriteBufferIdx();
+ size_t buffill = m_InputBuffers.getWriteBufferFill();
+ m_InputBuffers.unlockWriteBuffer(bufferSize);
+
+ if (!m_InputBuffers.hasError()) {
+ if (!m_InputStartTime) {
+ m_InputStartTime = md.absoluteTimestamp();
+ m_InputStartPosition = md.position();
+ }
+ BufferSoundMetaData *bmd = new BufferSoundMetaData(
+ md.position() - m_InputStartPosition,
+ md.absoluteTimestamp() - m_InputStartTime,
+ md.absoluteTimestamp(),
+ md.url(),
+ buffill);
+ m_buffersMetaData[bufidx]->append(bmd);
+ } else {
+ m_error = true;
+ m_errorString += m_InputBuffers.getErrorString();
+ m_InputBuffers.resetError();
+ }
+}
+
+
+void RecordingEncoding::setDone()
+{
+ m_done = true;
+ m_InputBuffers.unlockAllWriteBuffers();
+}
+
+
+
+void RecordingEncoding::run()
+{
+ BufferSoundMetaData last_md;
+
+ while (!m_error) {
+ char *buffer = NULL;
+ size_t buffer_fill = 0;
+ if (!m_done) {
+ buffer = m_InputBuffers.wait4ReadBuffer(buffer_fill);
+ }
+
+ if (!buffer_fill) {
+ if (m_done)
+ break;
+ else
+ continue;
+ }
+
+ char *export_buffer = NULL;
+ size_t export_buffer_size = 0;
+
+ TQ_UINT64 old_pos = m_encodedSize;
+
+ encode(buffer, buffer_fill, export_buffer, export_buffer_size);
+
+ SoundStreamEncodingStepEvent *step_event = NULL;
+
+ if (!m_error) {
+ last_md = *m_buffersMetaData[m_InputBuffers.getCurrentReadBufferIdx()]->first();
+ SoundMetaData md(old_pos, last_md.relativeTimestamp(), last_md.absoluteTimestamp(), m_outputURL);
+ step_event = new SoundStreamEncodingStepEvent(m_SoundStreamID, export_buffer, export_buffer_size, md);
+ }
+
+ if (step_event)
+ TQApplication::postEvent(m_parent, step_event);
+ }
+ m_done = true;
+ closeOutput();
+
+ SoundMetaData md(m_encodedSize, last_md.relativeTimestamp(), last_md.absoluteTimestamp(), m_outputURL);
+ TQApplication::postEvent(m_parent, new SoundStreamEncodingStepEvent(m_SoundStreamID, NULL, 0, md));
+
+ TQApplication::postEvent(m_parent, new SoundStreamEncodingTerminatedEvent(m_SoundStreamID));
+}
+
diff --git a/plugins/recording/encoder.h b/plugins/recording/encoder.h
new file mode 100644
index 0000000..b0c442d
--- /dev/null
+++ b/plugins/recording/encoder.h
@@ -0,0 +1,101 @@
+/***************************************************************************
+ encoder.h - description
+ -------------------
+ begin : Thu May 05 2005
+ copyright : (C) 2005 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_RECORDING_ENCODER_H
+#define KRADIO_RECORDING_ENCODER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <tqobject.h>
+#include <tqstring.h>
+#include <tqthread.h>
+
+#include "../../src/include/radiostation.h"
+#include "../../src/include/multibuffer.h"
+#include "../../src/include/sound_metadata.h"
+#include "../../src/include/soundstreamid.h"
+#include "recording-config.h"
+
+class BufferSoundMetaData : public SoundMetaData
+{
+public:
+ BufferSoundMetaData()
+ : SoundMetaData(0, 0, 0, KURL()), m_BufferPosition(0) {}
+ BufferSoundMetaData(const SoundMetaData &md, size_t bufferpos)
+ : SoundMetaData(md), m_BufferPosition(bufferpos) {}
+ BufferSoundMetaData(TQ_INT64 pos, time_t rel, time_t abs, const KURL &url, size_t bufferpos)
+ : SoundMetaData(pos, rel, abs, url), m_BufferPosition(bufferpos) {}
+
+ size_t bufferPosition() const { return m_BufferPosition; }
+
+protected:
+ size_t m_BufferPosition;
+};
+
+
+class RecordingEncoding : public TQThread
+{
+public:
+ RecordingEncoding(TQObject *parent, SoundStreamID id, const RecordingConfig &cfg, const RadioStation *rs, const TQString &filename);
+ virtual ~RecordingEncoding();
+
+ void run();
+
+ char *lockInputBuffer(size_t &bufferSize); // bytes we whish to write, returns number of bytes available
+ void unlockInputBuffer(size_t bufferSize, const SoundMetaData &md); // bytes we actually wrote
+
+ bool error() const { return m_error; }
+ const TQString &errorString() const { return m_errorString; }
+
+ void setDone();
+ bool IsDone() { return m_done; }
+
+ virtual bool openOutput(const TQString &outputFile) = 0;
+ virtual void closeOutput() = 0;
+
+ TQ_UINT64 encodedSize() const { return m_encodedSize; }
+
+ const RecordingConfig &config() const { return m_config; }
+
+protected:
+ virtual void encode(const char *_buffer, size_t buffer_size, char *&export_buffer, size_t &export_buffer_size) = 0;
+
+ TQObject *m_parent;
+ RecordingConfig m_config;
+ RadioStation *m_RadioStation;
+ SoundStreamID m_SoundStreamID;
+
+ bool m_error;
+ TQString m_errorString;
+ bool m_done;
+
+ MultiBuffer m_InputBuffers;
+ TQPtrList<BufferSoundMetaData>
+ **m_buffersMetaData;
+ TQ_UINT64 m_encodedSize;
+
+ time_t m_InputStartTime;
+ TQ_UINT64 m_InputStartPosition;
+
+ KURL m_outputURL;
+};
+
+
+#endif
diff --git a/plugins/recording/encoder_mp3.cpp b/plugins/recording/encoder_mp3.cpp
new file mode 100644
index 0000000..456850f
--- /dev/null
+++ b/plugins/recording/encoder_mp3.cpp
@@ -0,0 +1,214 @@
+/***************************************************************************
+ encoder_mp3.cpp
+ -------------------
+ begin : Sat Aug 20 2005
+ copyright : (C) 2005 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 "encoder_mp3.h"
+
+#include <tqmutex.h>
+#include <tdelocale.h>
+
+RecordingEncodingMP3::RecordingEncodingMP3(TQObject *parent, SoundStreamID ssid,
+ const RecordingConfig &cfg, const RadioStation *rs,
+ const TQString &filename)
+ : RecordingEncoding(parent, ssid, cfg, rs, filename)
+#ifdef HAVE_LAME
+ ,
+ m_MP3Buffer(NULL),
+ m_MP3BufferSize(0),
+ m_MP3Output(NULL),
+ m_ID3Tags(NULL),
+ m_LAMEFlags(NULL),
+ m_MP3LBuffer(NULL),
+ m_MP3RBuffer(NULL)
+#endif
+{
+ m_config.m_OutputFormat = RecordingConfig::outputMP3;
+ m_config.m_SoundFormat.m_Encoding = "mp3";
+ openOutput(filename);
+}
+
+
+RecordingEncodingMP3::~RecordingEncodingMP3()
+{
+ closeOutput();
+}
+
+
+static TQMutex lameSerialization;
+
+void RecordingEncodingMP3::encode(const char *_buffer, size_t buffer_size, char *&export_buffer, size_t &export_buffer_size)
+{
+ if (m_error)
+ return;
+
+#ifdef HAVE_LAME
+ short int *buffer = (short int*)_buffer;
+ size_t j = 0,
+ j_inc = (m_config.m_SoundFormat.m_Channels == 1) ? 1 : 2,
+ dj = (m_config.m_SoundFormat.m_Channels == 1) ? 0 : 1,
+ samples = buffer_size / m_config.m_SoundFormat.frameSize();
+
+ for (size_t i = 0; i < samples; ++i, j+=j_inc) {
+ m_MP3LBuffer[i] = buffer[j];
+ m_MP3RBuffer[i] = buffer[j+dj];
+ }
+
+ int n = 0;
+ lameSerialization.lock();
+ n = lame_encode_buffer(m_LAMEFlags,
+ m_MP3LBuffer,
+ m_MP3RBuffer,
+ samples,
+ m_MP3Buffer,
+ m_MP3BufferSize);
+ lameSerialization.unlock();
+ if (n < 0) {
+ m_errorString += i18n("Error %1 while encoding mp3. ").arg(TQString().setNum(n));
+ m_error = true;
+ } else if (n > 0) {
+ m_encodedSize += n;
+
+ export_buffer = (char*)m_MP3Buffer;
+ export_buffer_size = n;
+ int r = fwrite(m_MP3Buffer, 1, n, m_MP3Output);
+
+ if (r <= 0) {
+ m_errorString += i18n("Error %1 writing output. ").arg(TQString().setNum(r));
+ m_error = true;
+ }
+ }
+#endif
+}
+
+
+
+bool RecordingEncodingMP3::openOutput(const TQString &output)
+{
+#ifdef HAVE_LAME
+// m_output = NULL;
+ m_LAMEFlags = lame_init();
+
+ if (!m_LAMEFlags) {
+ m_error = true;
+ m_errorString += i18n("Cannot initialize lalibmp3lame. ");
+ } else {
+ lame_set_in_samplerate(m_LAMEFlags, m_config.m_SoundFormat.m_SampleRate);
+ lame_set_num_channels(m_LAMEFlags, 2);
+ //lame_set_quality(m_LAMEFlags, m_config.mp3Quality);
+
+ lame_set_mode(m_LAMEFlags, m_config.m_SoundFormat.m_Channels == 1 ? MONO : JOINT_STEREO);
+
+ // lame_seterrorf(m_LAMEFlags, ...);
+ // lame_setdebugf(m_LAMEFlags, ...);
+ // lame_setmsgf(m_LAMEFlags, ...);
+
+ lame_set_VBR(m_LAMEFlags, vbr_default);
+ lame_set_VBR_q(m_LAMEFlags, m_config.m_mp3Quality);
+
+ if (lame_init_params(m_LAMEFlags) < 0) {
+ m_error = true;
+ m_errorString += i18n("Cannot initialize libmp3lame parameters. ").arg(output);
+ }
+
+ if (!m_error) {
+ id3tag_init(m_LAMEFlags);
+ id3tag_add_v2(m_LAMEFlags);
+ TQString title = m_RadioStation->name() + TQString().sprintf(" - %s", (TQDateTime::currentDateTime().toString(Qt::ISODate)).ascii());
+ TQString comment = i18n("Recorded by TDERadio");
+ size_t l = title.length() + comment.length() + 10;
+ m_ID3Tags = new char[l];
+ char *ctitle = m_ID3Tags;
+ strcpy(ctitle, title.latin1());
+ char *ccomment = m_ID3Tags + strlen(ctitle) + 1;
+ strcpy(ccomment, comment.latin1());
+ id3tag_set_title(m_LAMEFlags, ctitle);
+ id3tag_set_comment(m_LAMEFlags, ccomment);
+ }
+
+ m_MP3Output = fopen(output.ascii(), "wb+");
+ if (!m_MP3Output) {
+ m_errorString += i18n("Cannot open output file %1. ").arg(output);
+ m_error = true;
+ }
+
+ size_t nSamples = m_config.m_EncodeBufferSize / m_config.m_SoundFormat.frameSize();
+ m_MP3BufferSize = nSamples + nSamples / 4 + 7200;
+ m_MP3Buffer = new unsigned char[m_MP3BufferSize];
+
+ m_MP3LBuffer = new short int[nSamples];
+ m_MP3RBuffer = new short int[nSamples];
+
+ if (!m_MP3Buffer || !m_MP3LBuffer || !m_MP3RBuffer) {
+ m_error = true;
+ m_errorString += i18n("Cannot allocate buffers for mp3 encoding. ");
+ }
+ }
+
+ if (m_error) {
+ if (m_LAMEFlags) lame_close(m_LAMEFlags);
+ m_LAMEFlags = NULL;
+ if (m_MP3Output) fclose(m_MP3Output);
+ m_MP3Output = NULL;
+ if (m_MP3Buffer) delete [] m_MP3Buffer;
+ m_MP3Buffer = NULL;
+ m_MP3BufferSize = 0;
+ if (m_ID3Tags) delete [] m_ID3Tags;
+ m_ID3Tags = NULL;
+ if (m_MP3LBuffer) delete[] m_MP3LBuffer;
+ if (m_MP3RBuffer) delete[] m_MP3RBuffer;
+ m_MP3LBuffer = m_MP3RBuffer = NULL;
+ }
+#endif
+ return !m_error;
+}
+
+
+void RecordingEncodingMP3::closeOutput()
+{
+#ifdef HAVE_LAME
+ if (m_LAMEFlags) {
+ if (m_config.m_OutputFormat == RecordingConfig::outputMP3) {
+ int n = lame_encode_flush(m_LAMEFlags,
+ m_MP3Buffer,
+ m_MP3BufferSize);
+ if (n < 0) {
+ m_error = true;
+ m_errorString += i18n("Error %1 while encoding mp3. ").arg(TQString().setNum(n));
+ } else if (n > 0) {
+ int r = fwrite(m_MP3Buffer, 1, n, m_MP3Output);
+ if (r <= 0) {
+ m_error = true;
+ m_errorString += i18n("Error %1 writing output. ").arg(TQString().setNum(r));
+ } else {
+ lame_mp3_tags_fid(m_LAMEFlags, m_MP3Output);
+ }
+ }
+ }
+ if (m_LAMEFlags) lame_close(m_LAMEFlags);
+ m_LAMEFlags = NULL;
+ if (m_MP3Output) fclose(m_MP3Output);
+ m_MP3Output = NULL;
+ m_MP3BufferSize = 0;
+ if (m_MP3Buffer) delete [] m_MP3Buffer;
+ m_MP3Buffer = NULL;
+ if (m_ID3Tags) delete [] m_ID3Tags;
+ m_ID3Tags = NULL;
+ if (m_MP3LBuffer) delete[] m_MP3LBuffer;
+ if (m_MP3RBuffer) delete[] m_MP3RBuffer;
+ m_MP3LBuffer = m_MP3RBuffer = NULL;
+ }
+#endif
+}
diff --git a/plugins/recording/encoder_mp3.h b/plugins/recording/encoder_mp3.h
new file mode 100644
index 0000000..aaa912c
--- /dev/null
+++ b/plugins/recording/encoder_mp3.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ encoder_mp3.h
+ -------------------
+ begin : Sat Aug 20 2005
+ copyright : (C) 2005 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_RECORDING_ENCODER_MP3_H
+#define KRADIO_RECORDING_ENCODER_MP3_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "encoder.h"
+
+#ifdef HAVE_LAME
+ #include <lame/lame.h>
+#endif
+
+class RecordingEncodingMP3 : public RecordingEncoding
+{
+public:
+ RecordingEncodingMP3(TQObject *parent, SoundStreamID id, const RecordingConfig &cfg, const RadioStation *rs, const TQString &filename);
+ virtual ~RecordingEncodingMP3();
+
+ bool openOutput(const TQString &outputFile);
+ void closeOutput();
+
+protected:
+ void encode(const char *_buffer, size_t buffer_size, char *&export_buffer, size_t &export_buffer_size);
+
+#ifdef HAVE_LAME
+ unsigned char *m_MP3Buffer;
+ size_t m_MP3BufferSize;
+ FILE *m_MP3Output;
+ char *m_ID3Tags;
+ lame_global_flags *m_LAMEFlags;
+ short int *m_MP3LBuffer,
+ *m_MP3RBuffer;
+#endif
+};
+
+
+
+#endif
diff --git a/plugins/recording/encoder_ogg.cpp b/plugins/recording/encoder_ogg.cpp
new file mode 100644
index 0000000..ca093b9
--- /dev/null
+++ b/plugins/recording/encoder_ogg.cpp
@@ -0,0 +1,250 @@
+/***************************************************************************
+ encoder_ogg.cpp
+ -------------------
+ begin : Sat Aug 20 2005
+ copyright : (C) 2005 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 "encoder_ogg.h"
+
+#include <tdelocale.h>
+#include <stdlib.h>
+
+RecordingEncodingOgg::RecordingEncodingOgg(TQObject *parent, SoundStreamID ssid,
+ const RecordingConfig &cfg, const RadioStation *rs,
+ const TQString &filename)
+ : RecordingEncoding(parent, ssid, cfg, rs, filename)
+#ifdef HAVE_OGG
+ ,
+ m_OggOutput(NULL),
+ m_OggExportBuffer(NULL),
+ m_OggExportBufferSize(0)
+#endif
+{
+ m_config.m_OutputFormat = RecordingConfig::outputOGG;
+ m_config.m_SoundFormat.m_Encoding = "ogg";
+ openOutput(filename);
+}
+
+
+RecordingEncodingOgg::~RecordingEncodingOgg()
+{
+ closeOutput();
+}
+
+void RecordingEncodingOgg::encode(const char *_buffer, size_t buffer_size, char *&export_buffer, size_t &export_buffer_size)
+{
+ if (m_error)
+ return;
+
+#ifdef HAVE_OGG
+ SoundFormat &sf = m_config.m_SoundFormat;
+ ogg_page ogg_pg;
+ ogg_packet ogg_pkt;
+
+ size_t samples = buffer_size / sf.frameSize();
+
+ // buffer[channel][sample], normalized to -1..0..+1
+ float **buffer = vorbis_analysis_buffer(&m_VorbisDSP, (samples < 512 ? 512 : samples));
+
+ sf.convertSamplesToFloat(_buffer, buffer, samples);
+
+ /* Tell the library how many samples (per channel) we wrote
+ into the supplied buffer */
+ vorbis_analysis_wrote(&m_VorbisDSP, samples);
+
+ /* While we can get enough data from the library to analyse, one
+ block at a time... */
+
+ bool eos = false;
+ while(!m_error && !eos && vorbis_analysis_blockout(&m_VorbisDSP, &m_VorbisBlock) == 1) {
+
+ /* Do the main analysis, creating a packet */
+ vorbis_analysis(&m_VorbisBlock, NULL);
+ vorbis_bitrate_addblock(&m_VorbisBlock);
+
+ while(!m_error && vorbis_bitrate_flushpacket(&m_VorbisDSP, &ogg_pkt)) {
+ /* Add packet to bitstream */
+ ogg_stream_packetin(&m_OggStream,&ogg_pkt);
+
+ /* If we've gone over a page boundary, we can do actual output,
+ so do so (for however many pages are available) */
+
+ while(!m_error && !eos) {
+ int result = ogg_stream_pageout(&m_OggStream, &ogg_pg);
+ if (!result) break;
+
+ int n = fwrite(ogg_pg.header, 1, ogg_pg.header_len, m_OggOutput);
+ n += fwrite(ogg_pg.body, 1, ogg_pg.body_len, m_OggOutput);
+
+ m_encodedSize += n;
+
+ if (n != (ogg_pg.header_len + ogg_pg.body_len)) {
+ m_error = true;
+ m_errorString += i18n("Failed writing data to ogg/vorbis output stream. ");
+ break;
+ } else {
+
+ if (m_OggExportBufferSize < export_buffer_size + n) {
+ m_OggExportBuffer = (char*)realloc(m_OggExportBuffer, m_OggExportBufferSize + 2 * n);
+ m_OggExportBufferSize += 2 * n;
+ }
+
+ memcpy (m_OggExportBuffer + export_buffer_size, ogg_pg.header, ogg_pg.header_len);
+ export_buffer_size += ogg_pg.header_len;
+ memcpy (m_OggExportBuffer + export_buffer_size, ogg_pg.body, ogg_pg.body_len);
+ export_buffer_size += ogg_pg.body_len;
+
+ }
+ if (ogg_page_eos(&ogg_pg))
+ eos = 1;
+ }
+ }
+ }
+
+ export_buffer = m_OggExportBuffer;
+#endif
+}
+
+
+#ifdef HAVE_OGG
+static void vorbis_comment_add_tag_new(vorbis_comment *vc, const TQString &tag, const TQString &value)
+{
+ char *stag = strdup(tag.ascii());
+ char *svalue = strdup(value.utf8());
+ vorbis_comment_add_tag(vc, stag, svalue);
+ delete stag;
+ delete svalue;
+}
+#endif
+
+bool RecordingEncodingOgg::openOutput(const TQString &output)
+{
+#ifdef HAVE_OGG
+ m_OggOutput = fopen(output.ascii(), "wb+");
+ if (!m_OggOutput) {
+ m_errorString += i18n("Cannot open Ogg/Vorbis output file %1. ").arg(output);
+ m_error = true;
+ }
+
+ m_OggExportBuffer = (char*)malloc(m_OggExportBufferSize = 65536); // start with a 64k buffer
+
+
+ /* Have vorbisenc choose a mode for us */
+ vorbis_info_init(&m_VorbisInfo);
+
+ SoundFormat &sf = m_config.m_SoundFormat;
+ if (vorbis_encode_setup_vbr(&m_VorbisInfo, sf.m_Channels, sf.m_SampleRate, m_config.m_oggQuality)) {
+ m_error = true;
+ m_errorString = i18n("Ogg/Vorbis Mode initialisation failed: invalid parameters for quality\n");
+ vorbis_info_clear(&m_VorbisInfo);
+ return false;
+ }
+
+ /* Turn off management entirely (if it was turned on). */
+ vorbis_encode_ctl(&m_VorbisInfo, OV_ECTL_RATEMANAGE_SET, NULL);
+ vorbis_encode_setup_init(&m_VorbisInfo);
+
+ /* Now, set up the analysis engine, stream encoder, and other
+ preparation before the encoding begins.
+ */
+
+ vorbis_analysis_init(&m_VorbisDSP, &m_VorbisInfo);
+ vorbis_block_init(&m_VorbisDSP, &m_VorbisBlock);
+
+ ogg_stream_init (&m_OggStream, m_SoundStreamID.getID());
+
+ /* Now, build the three header packets and send through to the stream
+ output stage (but defer actual file output until the main encode loop) */
+
+ ogg_packet header_main;
+ ogg_packet header_comments;
+ ogg_packet header_codebooks;
+
+ /* Build the packets */
+ vorbis_comment vc;
+ vorbis_comment_init (&vc);
+ vorbis_comment_add_tag_new(&vc, "creator", "TDERadio" VERSION);
+ vorbis_comment_add_tag_new(&vc, "title", m_RadioStation->longName().utf8());
+ vorbis_comment_add_tag_new(&vc, "date", TQDateTime::currentDateTime().toString(Qt::ISODate));
+
+ vorbis_analysis_headerout(&m_VorbisDSP, &vc,
+ &header_main, &header_comments, &header_codebooks);
+
+ /* And stream them out */
+ ogg_stream_packetin(&m_OggStream, &header_main);
+ ogg_stream_packetin(&m_OggStream, &header_comments);
+ ogg_stream_packetin(&m_OggStream, &header_codebooks);
+
+ int result;
+ ogg_page ogg_page;
+ while((result = ogg_stream_flush(&m_OggStream, &ogg_page))) {
+
+ if (!result) break;
+
+ int n = fwrite(ogg_page.header, 1, ogg_page.header_len, m_OggOutput);
+ n += fwrite(ogg_page.body, 1, ogg_page.body_len, m_OggOutput);
+
+ if(n != ogg_page.header_len + ogg_page.body_len) {
+ m_error = true;
+ m_errorString += i18n("Failed writing Ogg/Vorbis header to output stream\n");
+ break;
+ }
+ }
+
+ vorbis_comment_clear (&vc);
+
+ if (m_error) {
+ if (m_OggOutput) fclose (m_OggOutput);
+ m_OggOutput = NULL;
+ free(m_OggExportBuffer);
+ m_OggExportBuffer = NULL;
+ m_OggExportBufferSize = 0;
+
+ ogg_stream_clear(&m_OggStream);
+ vorbis_block_clear(&m_VorbisBlock);
+ vorbis_dsp_clear(&m_VorbisDSP);
+ vorbis_info_clear(&m_VorbisInfo);
+ }
+
+ return !m_error;
+#endif
+}
+
+
+void RecordingEncodingOgg::closeOutput()
+{
+#ifdef HAVE_OGG
+ if (m_OggOutput) {
+
+ char *tmp_buf = NULL;
+ size_t tmp_size = 0;
+ // flush buffer
+ encode(tmp_buf, tmp_size, tmp_buf, tmp_size);
+
+ fclose(m_OggOutput);
+ m_OggOutput = NULL;
+
+ free(m_OggExportBuffer);
+ m_OggExportBuffer = NULL;
+ m_OggExportBufferSize = 0;
+
+ ogg_stream_clear(&m_OggStream);
+ vorbis_block_clear(&m_VorbisBlock);
+ vorbis_dsp_clear(&m_VorbisDSP);
+ vorbis_info_clear(&m_VorbisInfo);
+ }
+#endif
+}
+
+
diff --git a/plugins/recording/encoder_ogg.h b/plugins/recording/encoder_ogg.h
new file mode 100644
index 0000000..586c96e
--- /dev/null
+++ b/plugins/recording/encoder_ogg.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ encoder_ogg.h
+ -------------------
+ begin : Sat Aug 20 2005
+ copyright : (C) 2005 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_RECORDING_ENCODER_OGG_H
+#define KRADIO_RECORDING_ENCODER_OGG_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "encoder.h"
+
+#ifdef HAVE_OGG
+ #include <vorbis/vorbisenc.h>
+#endif
+
+class RecordingEncodingOgg : public RecordingEncoding
+{
+public:
+ RecordingEncodingOgg(TQObject *parent, SoundStreamID id, const RecordingConfig &cfg, const RadioStation *rs, const TQString &filename);
+ virtual ~RecordingEncodingOgg();
+
+ bool openOutput(const TQString &outputFile);
+ void closeOutput();
+
+protected:
+ void encode(const char *_buffer, size_t buffer_size, char *&export_buffer, size_t &export_buffer_size);
+
+#ifdef HAVE_OGG
+ FILE *m_OggOutput;
+ char *m_OggExportBuffer;
+ size_t m_OggExportBufferSize;
+ ogg_stream_state m_OggStream;
+ vorbis_dsp_state m_VorbisDSP;
+ vorbis_block m_VorbisBlock;
+ vorbis_info m_VorbisInfo;
+#endif
+};
+
+
+#endif
diff --git a/plugins/recording/encoder_pcm.cpp b/plugins/recording/encoder_pcm.cpp
new file mode 100644
index 0000000..24a8ab6
--- /dev/null
+++ b/plugins/recording/encoder_pcm.cpp
@@ -0,0 +1,78 @@
+/***************************************************************************
+ encoder_pcm.cpp
+ -------------------
+ begin : Sat Aug 20 2005
+ copyright : (C) 2005 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 "encoder_pcm.h"
+
+
+#include <tdelocale.h>
+
+RecordingEncodingPCM::RecordingEncodingPCM(TQObject *parent, SoundStreamID ssid,
+ const RecordingConfig &cfg, const RadioStation *rs,
+ const TQString &filename)
+ : RecordingEncoding(parent, ssid, cfg, rs, filename),
+ m_output(NULL)
+{
+ m_config.m_SoundFormat.m_Encoding = "raw";
+ openOutput(filename);
+}
+
+
+RecordingEncodingPCM::~RecordingEncodingPCM()
+{
+ closeOutput();
+}
+
+
+
+void RecordingEncodingPCM::encode(const char *buffer, size_t buffer_size, char *&export_buffer, size_t &export_buffer_size)
+{
+ if (m_error)
+ return;
+ m_encodedSize += buffer_size;
+
+ export_buffer = const_cast<char*>(buffer);
+ export_buffer_size = buffer_size;
+ int err = sf_write_raw(m_output, const_cast<char*>(buffer), buffer_size);
+
+ if (err != (int)buffer_size) {
+ m_error = true;
+ m_errorString += i18n("Error %1 writing output. ").arg(TQString().setNum(err));
+ }
+}
+
+
+bool RecordingEncodingPCM::openOutput(const TQString &output)
+{
+ SF_INFO sinfo;
+ m_config.getSoundFileInfo(sinfo, false);
+ m_output = sf_open(output.ascii(), SFM_WRITE, &sinfo);
+
+ if (!m_output) {
+ m_error = true;
+ m_errorString += i18n("Cannot open output file %1. ").arg(output);
+ }
+ return !m_error;
+}
+
+
+void RecordingEncodingPCM::closeOutput()
+{
+ if (m_output) sf_close (m_output);
+ m_output = NULL;
+}
+
+
diff --git a/plugins/recording/encoder_pcm.h b/plugins/recording/encoder_pcm.h
new file mode 100644
index 0000000..40e6cf4
--- /dev/null
+++ b/plugins/recording/encoder_pcm.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ encoder_pcm.h
+ -------------------
+ begin : Sat Aug 20 2005
+ copyright : (C) 2005 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_RECORDING_ENCODER_PCM_H
+#define KRADIO_RECORDING_ENCODER_PCM_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "encoder.h"
+
+#include <sndfile.h>
+
+class RecordingEncodingPCM : public RecordingEncoding
+{
+public:
+ RecordingEncodingPCM(TQObject *parent, SoundStreamID id, const RecordingConfig &cfg, const RadioStation *rs, const TQString &filename);
+ virtual ~RecordingEncodingPCM();
+
+ bool openOutput(const TQString &outputFile);
+ void closeOutput();
+
+protected:
+ void encode(const char *_buffer, size_t buffer_size, char *&export_buffer, size_t &export_buffer_size);
+
+
+ SNDFILE *m_output;
+};
+
+
+#endif
diff --git a/plugins/recording/icons/Makefile.am b/plugins/recording/icons/Makefile.am
new file mode 100644
index 0000000..974b96b
--- /dev/null
+++ b/plugins/recording/icons/Makefile.am
@@ -0,0 +1,2 @@
+icons_ICON = AUTO
+iconsdir = $(datadir)/icons
diff --git a/plugins/recording/icons/hi16-action-tderadio_record.png b/plugins/recording/icons/hi16-action-tderadio_record.png
new file mode 100644
index 0000000..ff75485
--- /dev/null
+++ b/plugins/recording/icons/hi16-action-tderadio_record.png
Binary files differ
diff --git a/plugins/recording/icons/hi16-app-tderadio_plus_rec.png b/plugins/recording/icons/hi16-app-tderadio_plus_rec.png
new file mode 100644
index 0000000..deea3dc
--- /dev/null
+++ b/plugins/recording/icons/hi16-app-tderadio_plus_rec.png
Binary files differ
diff --git a/plugins/recording/icons/hi22-action-tderadio_record.png b/plugins/recording/icons/hi22-action-tderadio_record.png
new file mode 100644
index 0000000..9706942
--- /dev/null
+++ b/plugins/recording/icons/hi22-action-tderadio_record.png
Binary files differ
diff --git a/plugins/recording/icons/hi22-app-tderadio_plus_rec.png b/plugins/recording/icons/hi22-app-tderadio_plus_rec.png
new file mode 100644
index 0000000..50697cc
--- /dev/null
+++ b/plugins/recording/icons/hi22-app-tderadio_plus_rec.png
Binary files differ
diff --git a/plugins/recording/icons/hi256-action-tderadio_record.png b/plugins/recording/icons/hi256-action-tderadio_record.png
new file mode 100644
index 0000000..a372627
--- /dev/null
+++ b/plugins/recording/icons/hi256-action-tderadio_record.png
Binary files differ
diff --git a/plugins/recording/icons/hi32-action-tderadio_record.png b/plugins/recording/icons/hi32-action-tderadio_record.png
new file mode 100644
index 0000000..8cb0ebd
--- /dev/null
+++ b/plugins/recording/icons/hi32-action-tderadio_record.png
Binary files differ
diff --git a/plugins/recording/icons/hi32-app-tderadio_plus_rec.png b/plugins/recording/icons/hi32-app-tderadio_plus_rec.png
new file mode 100644
index 0000000..91d46f4
--- /dev/null
+++ b/plugins/recording/icons/hi32-app-tderadio_plus_rec.png
Binary files differ
diff --git a/plugins/recording/icons/hi48-action-tderadio_record.png b/plugins/recording/icons/hi48-action-tderadio_record.png
new file mode 100644
index 0000000..69aca1d
--- /dev/null
+++ b/plugins/recording/icons/hi48-action-tderadio_record.png
Binary files differ
diff --git a/plugins/recording/icons/hi48-app-tderadio_plus_rec.png b/plugins/recording/icons/hi48-app-tderadio_plus_rec.png
new file mode 100644
index 0000000..975335c
--- /dev/null
+++ b/plugins/recording/icons/hi48-app-tderadio_plus_rec.png
Binary files differ
diff --git a/plugins/recording/icons/hi64-action-tderadio_record.png b/plugins/recording/icons/hi64-action-tderadio_record.png
new file mode 100644
index 0000000..4b2efce
--- /dev/null
+++ b/plugins/recording/icons/hi64-action-tderadio_record.png
Binary files differ
diff --git a/plugins/recording/icons/hi64-app-tderadio_plus_rec.png b/plugins/recording/icons/hi64-app-tderadio_plus_rec.png
new file mode 100644
index 0000000..9decd00
--- /dev/null
+++ b/plugins/recording/icons/hi64-app-tderadio_plus_rec.png
Binary files differ
diff --git a/plugins/recording/po/Makefile.am b/plugins/recording/po/Makefile.am
new file mode 100644
index 0000000..b2533fe
--- /dev/null
+++ b/plugins/recording/po/Makefile.am
@@ -0,0 +1,2 @@
+PACKAGE = tderadio-recording
+POFILES = AUTO
diff --git a/plugins/recording/po/de.po b/plugins/recording/po/de.po
new file mode 100644
index 0000000..0cf82d0
--- /dev/null
+++ b/plugins/recording/po/de.po
@@ -0,0 +1,396 @@
+# translation of de.po to
+# translation of tderadio-recording.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: 2021-07-07 18:28+0000\n"
+"PO-Revision-Date: 2019-12-22 15:33+0000\n"
+"Last-Translator: Chris <xchrisx@uber.space>\n"
+"Language-Team: German <https://mirror.git.trinitydesktop.org/weblate/"
+"projects/applications/tderadio-recording/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, Chris (TDE)"
+
+#. 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, (Keine Email)"
+
+#: encoder_mp3.cpp:79 encoder_mp3.cpp:189
+msgid "Error %1 while encoding mp3. "
+msgstr "Fehler %1 beim Kodieren des MP3-Streams. "
+
+#: encoder_mp3.cpp:89 encoder_mp3.cpp:194 encoder_pcm.cpp:53
+msgid "Error %1 writing output. "
+msgstr "Fehler %1 beim Schreiben der Ausgabedatei. "
+
+#: encoder_mp3.cpp:106
+msgid "Cannot initialize lalibmp3lame. "
+msgstr "Die Funktionsbibliothek libmp3lame kann nicht initialisiert werden. "
+
+#: encoder_mp3.cpp:123
+msgid "Cannot initialize libmp3lame parameters. "
+msgstr ""
+"Die Parameter der Funktionsbibliothek libmp3lame konnten nicht initialisiert "
+"werden. "
+
+#: encoder_mp3.cpp:130
+msgid "Recorded by TDERadio"
+msgstr "Aufzeichnung durch TDERadio"
+
+#: encoder_mp3.cpp:143 encoder_pcm.cpp:66
+msgid "Cannot open output file %1. "
+msgstr "Die Ausgabedatei %1 kann nicht geöffnet werden. "
+
+#: encoder_mp3.cpp:156
+msgid "Cannot allocate buffers for mp3 encoding. "
+msgstr ""
+"Die Puffer für das Kodieren des MP3-Streams konnten nicht angelegt werden. "
+
+#: encoder_ogg.cpp:94
+msgid "Failed writing data to ogg/vorbis output stream. "
+msgstr "Das schreiben der Ogg/Vorbis-Daten schlug fehl. "
+
+#: encoder_ogg.cpp:136
+msgid "Cannot open Ogg/Vorbis output file %1. "
+msgstr "Die Ogg/Vorbis-Ausgabedatei %1 konnte nicht geöffnet werden. "
+
+#: encoder_ogg.cpp:149
+msgid "Ogg/Vorbis Mode initialisation failed: invalid parameters for quality\n"
+msgstr ""
+"Die Initialisierung des Ogg/Vorbis-Modes schlug fehl: Ungültiger Qualitäts-"
+"Parameter\n"
+
+#: encoder_ogg.cpp:200
+msgid "Failed writing Ogg/Vorbis header to output stream\n"
+msgstr "Das Schreiben der Ogg/Vorbis-Kopfdaten der Ausgabedatei schlug fehl\n"
+
+#: recording-datamonitor.cpp:174 recording-datamonitor.cpp:179
+msgid "%1 dB"
+msgstr "%1 dB"
+
+#: recording-monitor.cpp:34
+msgid "Recording Monitor"
+msgstr "Aufnahme-Überwachung"
+
+#: recording-monitor.cpp:38 recording.cpp:47
+msgid "TDERadio Recording Monitor"
+msgstr "TDERadio Aufnahme-Überwachung"
+
+#: recording-monitor.cpp:43
+msgid "SoundStream"
+msgstr "Aufnahmedatenstrom"
+
+#: recording-monitor.cpp:45
+msgid "Status"
+msgstr "Status"
+
+#: recording-monitor.cpp:46 recording-monitor.cpp:48 recording-monitor.cpp:50
+#: recording-monitor.cpp:52 recording-monitor.cpp:54
+msgid "<undefined>"
+msgstr "<undefiniert>"
+
+#: recording-monitor.cpp:47
+msgid "Recording File"
+msgstr "Aufnahmedatei"
+
+#: recording-monitor.cpp:49
+msgid "File Size"
+msgstr "Dateigröße"
+
+#: recording-monitor.cpp:51
+msgid "Recording Time"
+msgstr "Aufnahmezeit"
+
+#: recording-configuration-ui.ui:359 recording-monitor.cpp:53
+#, no-c-format
+msgid "Sample Rate"
+msgstr "Abtastrate"
+
+#: recording-monitor.cpp:57 recording-monitor.cpp:393 recording-monitor.cpp:396
+msgid "&Record"
+msgstr "&Aufnehmen"
+
+#: recording-monitor.cpp:74 recording-monitor.cpp:118 recording-monitor.cpp:141
+msgid "nothing"
+msgstr "nichts"
+
+#: recording-monitor.cpp:339
+msgid "%1 Byte"
+msgstr "%1 Byte"
+
+#: recording-monitor.cpp:340
+msgid "%1 kB"
+msgstr "%1 kB"
+
+#: recording-monitor.cpp:341
+msgid "%1 MB"
+msgstr "%1 MB"
+
+#: recording-monitor.cpp:342
+msgid "%1 GB"
+msgstr "%1 GB"
+
+#: recording-monitor.cpp:345
+msgid "%1 Hz"
+msgstr "%1 Hz"
+
+#: recording-monitor.cpp:393
+msgid "&Stop Recording"
+msgstr "Aufnahme anhalten"
+
+#: recording.cpp:46 recording.cpp:54
+msgid "TDERadio Recording Plugin"
+msgstr "TDERadio Aufnahme-Plugin"
+
+#: recording.cpp:131 recording.cpp:132
+msgid "Recording"
+msgstr "Aufnahme"
+
+#: recording.cpp:360
+msgid "start capture not handled"
+msgstr "Der Aufnahmestart wurde ignoriert"
+
+#: recording.cpp:367
+msgid "Recording starting"
+msgstr "Die Aufnahme wird gestartet"
+
+#: recording.cpp:369
+msgid "starting encoding thread failed"
+msgstr "Das Starten des Aufnahme-Threads schlug fehl"
+
+#: recording.cpp:451
+msgid "could not read suffient data"
+msgstr "es konnten nicht ausreichend Daten gelesen werden"
+
+#: recording.cpp:482
+msgid ""
+"Encoder input buffer overflow (buffer configuration problem?). Skipped %1 "
+"input bytes"
+msgstr ""
+"Pufferüberlauf des Aufnahmepuffers des Kodierers/Komprimierers (Fehlerhafte "
+"Konfiguration der Puffer?). Es wurden %1 Bytes ignoriert."
+
+#: recording.cpp:544
+msgid "Recording::outputFile: "
+msgstr "Aufnahme::Ausgabedatei: "
+
+#: recording.cpp:594
+msgid "The encoding thread did not finish. It will be killed now."
+msgstr ""
+"Der Kodierungs-Thread beendete sich nicht selber. Er wird jetzt mit roher "
+"Gewalt beendet."
+
+#: recording.cpp:614
+msgid "Recording stopped"
+msgstr "Die Aufnahme wurde beendet"
+
+#: recording.cpp:647
+msgid ""
+"Recording::notifySoundStreamData(encoded data): Receivers skipped %1 Bytes"
+msgstr ""
+"Recording::notifySoundStreamData(Kodierte Daten): Die Empfängermodule "
+"übersprangen %1 Bytess"
+
+#: recording-configuration-ui.ui:16
+#, no-c-format
+msgid "RecordingConfigurationUI"
+msgstr "RecordingConfigurationUI"
+
+#: recording-configuration-ui.ui:34
+#, no-c-format
+msgid "Output"
+msgstr "Ausgabe"
+
+#: recording-configuration-ui.ui:138
+#, no-c-format
+msgid "MP3 Quality(0 - high, 9 - low)"
+msgstr "MP3 Qualität(0 - hoch, 9 - niedrig)"
+
+#: recording-configuration-ui.ui:149
+#, no-c-format
+msgid "raw pcm output (.raw)"
+msgstr "reine PCM-Ausgabe (.raw)"
+
+#: recording-configuration-ui.ui:154
+#, no-c-format
+msgid "Microsoft Wave (.wav)"
+msgstr "Microsoft Wave (.wav)"
+
+#: recording-configuration-ui.ui:159
+#, no-c-format
+msgid "Apple/SGI (.aiff)"
+msgstr "Apple/SGI (.aiff)"
+
+#: recording-configuration-ui.ui:164
+#, no-c-format
+msgid "Sun/NeXT (.au)"
+msgstr "Sun/NeXT (.au)"
+
+#: recording-configuration-ui.ui:169
+#, no-c-format
+msgid "MP3 Compressed (.mp3)"
+msgstr "MP3 komprimiert (.mp3)"
+
+#: recording-configuration-ui.ui:174
+#, no-c-format
+msgid "Ogg/Vorbis Compressed (.ogg)"
+msgstr "Ogg/Vorbis komprimiert (.ogg)"
+
+#: recording-configuration-ui.ui:194
+#, no-c-format
+msgid "Recording Directory"
+msgstr "Aufnahme-Verzeichnis"
+
+#: recording-configuration-ui.ui:202
+#, no-c-format
+msgid "File Format"
+msgstr "Dateiformat"
+
+#: recording-configuration-ui.ui:210
+#, no-c-format
+msgid "Ogg Quality(0 - low, 9 - high)"
+msgstr "Ogg Qualität(0 - niedrig, 9 - hoch)"
+
+#: recording-configuration-ui.ui:239
+#, no-c-format
+msgid "I&nput"
+msgstr "Quelle"
+
+#: recording-configuration-ui.ui:276
+#, no-c-format
+msgid "48000"
+msgstr "48000"
+
+#: recording-configuration-ui.ui:281
+#, no-c-format
+msgid "44100"
+msgstr "44100"
+
+#: recording-configuration-ui.ui:286
+#, no-c-format
+msgid "22050"
+msgstr "22050"
+
+#: recording-configuration-ui.ui:291
+#, no-c-format
+msgid "11025"
+msgstr "11025"
+
+#: recording-configuration-ui.ui:311
+#, no-c-format
+msgid "Endianess"
+msgstr "Byte-Reihenfolge"
+
+#: recording-configuration-ui.ui:334
+#, no-c-format
+msgid "Stereo"
+msgstr "Stereo"
+
+#: recording-configuration-ui.ui:339
+#, no-c-format
+msgid "Mono"
+msgstr "Mono"
+
+#: recording-configuration-ui.ui:365
+#, no-c-format
+msgid "Little Endian"
+msgstr "Little Endian"
+
+#: recording-configuration-ui.ui:370
+#, no-c-format
+msgid "Big Endian"
+msgstr "Big Endian"
+
+#: recording-configuration-ui.ui:388
+#, no-c-format
+msgid "16"
+msgstr "16"
+
+#: recording-configuration-ui.ui:393
+#, no-c-format
+msgid "8"
+msgstr "8"
+
+#: recording-configuration-ui.ui:413
+#, no-c-format
+msgid "Channels"
+msgstr "Kanäle"
+
+#: recording-configuration-ui.ui:421
+#, no-c-format
+msgid "Sample Bits"
+msgstr "Quantisierungs-Bits"
+
+#: recording-configuration-ui.ui:427
+#, no-c-format
+msgid "Signed"
+msgstr "Vorzeichenbehaftet"
+
+#: recording-configuration-ui.ui:432
+#, no-c-format
+msgid "Unsigned"
+msgstr "Vorzeichenlos"
+
+#: recording-configuration-ui.ui:490
+#, no-c-format
+msgid "&Buffers"
+msgstr "&Puffer"
+
+#: recording-configuration-ui.ui:512
+#, no-c-format
+msgid " kB"
+msgstr " kB"
+
+#: recording-configuration-ui.ui:532
+#, no-c-format
+msgid "Encoding Buffer Size"
+msgstr "Kodierungs-Puffergröße"
+
+#: recording-configuration-ui.ui:551
+#, no-c-format
+msgid "Number of Buffers"
+msgstr "Anzahl der Puffer"
+
+#: recording-configuration-ui.ui:580
+#, no-c-format
+msgid "Pre-Recordin&g"
+msgstr "Aufnahme&vorlaufs"
+
+#: recording-configuration-ui.ui:610
+#, no-c-format
+msgid "E&nable"
+msgstr "&Einschalten"
+
+#: recording-configuration-ui.ui:613
+#, no-c-format
+msgid "Alt+N"
+msgstr "Alt+N"
+
+#: recording-configuration-ui.ui:651
+#, no-c-format
+msgid "PreRecording Time"
+msgstr "Dauer des Aufnahmevorlaufs"
+
+#: recording-configuration-ui.ui:662
+#, no-c-format
+msgid " s"
+msgstr " s"
+
+#~ msgid "Waiting for encoding thread to terminate."
+#~ msgstr "Warte auf die Beendigung des Codierungs-Threads."
diff --git a/plugins/recording/po/ru.po b/plugins/recording/po/ru.po
new file mode 100644
index 0000000..86d7b2f
--- /dev/null
+++ b/plugins/recording/po/ru.po
@@ -0,0 +1,391 @@
+# translation of ru.po to
+# translation of tderadio-recording.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: 2021-07-07 18:28+0000\n"
+"PO-Revision-Date: 2006-11-08 12:35+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"
+
+#: encoder_mp3.cpp:79 encoder_mp3.cpp:189
+msgid "Error %1 while encoding mp3. "
+msgstr "При кодировании MP3 произошла ошибка: %1. "
+
+#: encoder_mp3.cpp:89 encoder_mp3.cpp:194 encoder_pcm.cpp:53
+msgid "Error %1 writing output. "
+msgstr "Во время записи произошла ошибка: %1"
+
+#: encoder_mp3.cpp:106
+msgid "Cannot initialize lalibmp3lame. "
+msgstr ""
+"Не могу инициализировать lalibmp3lame — необходимо для кодирования в MP3."
+
+#: encoder_mp3.cpp:123
+msgid "Cannot initialize libmp3lame parameters. "
+msgstr ""
+"Не могу инициализировать параметры libmp3lame — необходимо для кодирования в "
+"MP3."
+
+#: encoder_mp3.cpp:130
+msgid "Recorded by TDERadio"
+msgstr "Запись TDERadio"
+
+#: encoder_mp3.cpp:143 encoder_pcm.cpp:66
+msgid "Cannot open output file %1. "
+msgstr "Не могу открыть выходной файл %1. "
+
+#: encoder_mp3.cpp:156
+msgid "Cannot allocate buffers for mp3 encoding. "
+msgstr "Не могу разместить в памяти буферы для кодирования MP3."
+
+#: encoder_ogg.cpp:94
+msgid "Failed writing data to ogg/vorbis output stream. "
+msgstr "Ошибка записи данных в выходной поток ogg/vorbis. "
+
+#: encoder_ogg.cpp:136
+msgid "Cannot open Ogg/Vorbis output file %1. "
+msgstr "Не могу открыть выходной файл Ogg/Vorbis \"%1\". "
+
+#: encoder_ogg.cpp:149
+msgid "Ogg/Vorbis Mode initialisation failed: invalid parameters for quality\n"
+msgstr ""
+"Инициализация режима Ogg/Vorbis не удалась: качество записи указано неверно\n"
+
+#: encoder_ogg.cpp:200
+msgid "Failed writing Ogg/Vorbis header to output stream\n"
+msgstr "Ошибка записи заголовка Ogg/Vorbis в выходной поток\n"
+
+#: recording-datamonitor.cpp:174 recording-datamonitor.cpp:179
+msgid "%1 dB"
+msgstr "%1 дБ"
+
+#: recording-monitor.cpp:34
+msgid "Recording Monitor"
+msgstr "Монитор записи"
+
+#: recording-monitor.cpp:38 recording.cpp:47
+msgid "TDERadio Recording Monitor"
+msgstr "Монитор записи для TDERadio"
+
+#: recording-monitor.cpp:43
+msgid "SoundStream"
+msgstr "Источник"
+
+#: recording-monitor.cpp:45
+msgid "Status"
+msgstr "Состояние"
+
+#: recording-monitor.cpp:46 recording-monitor.cpp:48 recording-monitor.cpp:50
+#: recording-monitor.cpp:52 recording-monitor.cpp:54
+msgid "<undefined>"
+msgstr "<не определено>"
+
+#: recording-monitor.cpp:47
+msgid "Recording File"
+msgstr "Файл"
+
+#: recording-monitor.cpp:49
+msgid "File Size"
+msgstr "Размер файла"
+
+#: recording-monitor.cpp:51
+msgid "Recording Time"
+msgstr "Длительность записи"
+
+#: recording-configuration-ui.ui:359 recording-monitor.cpp:53
+#, no-c-format
+msgid "Sample Rate"
+msgstr "Частота дискретизации"
+
+#: recording-monitor.cpp:57 recording-monitor.cpp:393 recording-monitor.cpp:396
+msgid "&Record"
+msgstr "&Начать запись"
+
+#: recording-monitor.cpp:74 recording-monitor.cpp:118 recording-monitor.cpp:141
+msgid "nothing"
+msgstr "(нет)"
+
+#: recording-monitor.cpp:339
+msgid "%1 Byte"
+msgstr "%1 байт"
+
+#: recording-monitor.cpp:340
+msgid "%1 kB"
+msgstr "%1 кБ"
+
+#: recording-monitor.cpp:341
+msgid "%1 MB"
+msgstr "%1 МБ"
+
+#: recording-monitor.cpp:342
+msgid "%1 GB"
+msgstr "%1 ГБ"
+
+#: recording-monitor.cpp:345
+msgid "%1 Hz"
+msgstr "%1 Гц"
+
+#: recording-monitor.cpp:393
+msgid "&Stop Recording"
+msgstr "&Остановить запись"
+
+#: recording.cpp:46 recording.cpp:54
+msgid "TDERadio Recording Plugin"
+msgstr "Модуль записи звука для TDERadio"
+
+#: recording.cpp:131 recording.cpp:132
+msgid "Recording"
+msgstr "Запись"
+
+#: recording.cpp:360
+msgid "start capture not handled"
+msgstr ""
+
+#: recording.cpp:367
+msgid "Recording starting"
+msgstr "Запись запущена"
+
+#: recording.cpp:369
+msgid "starting encoding thread failed"
+msgstr "Не смог запустить процесс кодирования"
+
+#: recording.cpp:451
+msgid "could not read suffient data"
+msgstr "Не смог прочесть достаточно данных"
+
+#: recording.cpp:482
+msgid ""
+"Encoder input buffer overflow (buffer configuration problem?). Skipped %1 "
+"input bytes"
+msgstr ""
+"Переполнение на входе кодировщика (вероятно, неправильно настроен буфер). "
+"Пропускаю %1 байт на входе."
+
+#: recording.cpp:544
+msgid "Recording::outputFile: "
+msgstr "Recording::outputFile (выходной файл записи):"
+
+#: recording.cpp:594
+msgid "The encoding thread did not finish. It will be killed now."
+msgstr "Нить кодировщика не завершилась. Процесс будет уничтожен."
+
+#: recording.cpp:614
+#, fuzzy
+msgid "Recording stopped"
+msgstr "Запись заершена"
+
+#: recording.cpp:647
+msgid ""
+"Recording::notifySoundStreamData(encoded data): Receivers skipped %1 Bytes"
+msgstr ""
+"Recording::notifySoundStreamData(encoded data): Приёмник пропустил %1 байт"
+
+#: recording-configuration-ui.ui:16
+#, no-c-format
+msgid "RecordingConfigurationUI"
+msgstr "RecordingConfigurationUI"
+
+#: recording-configuration-ui.ui:34
+#, no-c-format
+msgid "Output"
+msgstr "Выход"
+
+#: recording-configuration-ui.ui:138
+#, no-c-format
+msgid "MP3 Quality(0 - high, 9 - low)"
+msgstr "Качество MP3 (0 — высокое, 9 — низкое)"
+
+#: recording-configuration-ui.ui:149
+#, no-c-format
+msgid "raw pcm output (.raw)"
+msgstr "Неформатированный вывод (.raw)"
+
+#: recording-configuration-ui.ui:154
+#, no-c-format
+msgid "Microsoft Wave (.wav)"
+msgstr "Microsoft Wave (.wav)"
+
+#: recording-configuration-ui.ui:159
+#, no-c-format
+msgid "Apple/SGI (.aiff)"
+msgstr "Apple/SGI (.aiff)"
+
+#: recording-configuration-ui.ui:164
+#, no-c-format
+msgid "Sun/NeXT (.au)"
+msgstr "Sun/NeXT (.au)"
+
+#: recording-configuration-ui.ui:169
+#, no-c-format
+msgid "MP3 Compressed (.mp3)"
+msgstr "Сжатый MP3 (.mp3)"
+
+#: recording-configuration-ui.ui:174
+#, no-c-format
+msgid "Ogg/Vorbis Compressed (.ogg)"
+msgstr "Сжатый Ogg Vorbis (.ogg)"
+
+#: recording-configuration-ui.ui:194
+#, no-c-format
+msgid "Recording Directory"
+msgstr "Каталог для сохранения"
+
+#: recording-configuration-ui.ui:202
+#, no-c-format
+msgid "File Format"
+msgstr "Формат файла"
+
+#: recording-configuration-ui.ui:210
+#, no-c-format
+msgid "Ogg Quality(0 - low, 9 - high)"
+msgstr "Качество Ogg (0 — ниже, 9 — выше)"
+
+#: recording-configuration-ui.ui:239
+#, no-c-format
+msgid "I&nput"
+msgstr "В&вод"
+
+#: recording-configuration-ui.ui:276
+#, no-c-format
+msgid "48000"
+msgstr "48000"
+
+#: recording-configuration-ui.ui:281
+#, no-c-format
+msgid "44100"
+msgstr "44100"
+
+#: recording-configuration-ui.ui:286
+#, no-c-format
+msgid "22050"
+msgstr "22050"
+
+#: recording-configuration-ui.ui:291
+#, no-c-format
+msgid "11025"
+msgstr "11025"
+
+#: recording-configuration-ui.ui:311
+#, no-c-format
+msgid "Endianess"
+msgstr "Порядок байтов"
+
+#: recording-configuration-ui.ui:334
+#, no-c-format
+msgid "Stereo"
+msgstr "2 (Стерео)"
+
+#: recording-configuration-ui.ui:339
+#, no-c-format
+msgid "Mono"
+msgstr "1 (Моно)"
+
+#: recording-configuration-ui.ui:365
+#, no-c-format
+msgid "Little Endian"
+msgstr "Little Endian"
+
+#: recording-configuration-ui.ui:370
+#, fuzzy, no-c-format
+msgid "Big Endian"
+msgstr "Big Endian"
+
+#: recording-configuration-ui.ui:388
+#, no-c-format
+msgid "16"
+msgstr "16"
+
+#: recording-configuration-ui.ui:393
+#, no-c-format
+msgid "8"
+msgstr "8"
+
+#: recording-configuration-ui.ui:413
+#, no-c-format
+msgid "Channels"
+msgstr "Число каналов"
+
+#: recording-configuration-ui.ui:421
+#, no-c-format
+msgid "Sample Bits"
+msgstr "Бит на элемент выборки"
+
+#: recording-configuration-ui.ui:427
+#, no-c-format
+msgid "Signed"
+msgstr "Со знаком"
+
+#: recording-configuration-ui.ui:432
+#, no-c-format
+msgid "Unsigned"
+msgstr "Без знака"
+
+#: recording-configuration-ui.ui:490
+#, no-c-format
+msgid "&Buffers"
+msgstr "&Буферы"
+
+#: recording-configuration-ui.ui:512
+#, no-c-format
+msgid " kB"
+msgstr " кБ"
+
+#: recording-configuration-ui.ui:532
+#, no-c-format
+msgid "Encoding Buffer Size"
+msgstr "Размер буфера для записи"
+
+#: recording-configuration-ui.ui:551
+#, no-c-format
+msgid "Number of Buffers"
+msgstr "Количество буферов"
+
+#: recording-configuration-ui.ui:580
+#, no-c-format
+msgid "Pre-Recordin&g"
+msgstr "&Упреждающая запись"
+
+#: recording-configuration-ui.ui:610
+#, no-c-format
+msgid "E&nable"
+msgstr "Включить"
+
+#: recording-configuration-ui.ui:613
+#, no-c-format
+msgid "Alt+N"
+msgstr "Alt+N"
+
+#: recording-configuration-ui.ui:651
+#, no-c-format
+msgid "PreRecording Time"
+msgstr "Упреждение"
+
+#: recording-configuration-ui.ui:662
+#, no-c-format
+msgid " s"
+msgstr " с"
+
+#~ msgid "Waiting for encoding thread to terminate."
+#~ msgstr "Жду завершения нити кодировщика"
diff --git a/plugins/recording/po/tderadio-recording.pot b/plugins/recording/po/tderadio-recording.pot
new file mode 100644
index 0000000..601779c
--- /dev/null
+++ b/plugins/recording/po/tderadio-recording.pot
@@ -0,0 +1,378 @@
+# SOME DESCRIPTIVE TITLE.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2021-07-07 18:28+0000\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 ""
+
+#: encoder_mp3.cpp:79 encoder_mp3.cpp:189
+msgid "Error %1 while encoding mp3. "
+msgstr ""
+
+#: encoder_mp3.cpp:89 encoder_mp3.cpp:194 encoder_pcm.cpp:53
+msgid "Error %1 writing output. "
+msgstr ""
+
+#: encoder_mp3.cpp:106
+msgid "Cannot initialize lalibmp3lame. "
+msgstr ""
+
+#: encoder_mp3.cpp:123
+msgid "Cannot initialize libmp3lame parameters. "
+msgstr ""
+
+#: encoder_mp3.cpp:130
+msgid "Recorded by TDERadio"
+msgstr ""
+
+#: encoder_mp3.cpp:143 encoder_pcm.cpp:66
+msgid "Cannot open output file %1. "
+msgstr ""
+
+#: encoder_mp3.cpp:156
+msgid "Cannot allocate buffers for mp3 encoding. "
+msgstr ""
+
+#: encoder_ogg.cpp:94
+msgid "Failed writing data to ogg/vorbis output stream. "
+msgstr ""
+
+#: encoder_ogg.cpp:136
+msgid "Cannot open Ogg/Vorbis output file %1. "
+msgstr ""
+
+#: encoder_ogg.cpp:149
+msgid "Ogg/Vorbis Mode initialisation failed: invalid parameters for quality\n"
+msgstr ""
+
+#: encoder_ogg.cpp:200
+msgid "Failed writing Ogg/Vorbis header to output stream\n"
+msgstr ""
+
+#: recording-datamonitor.cpp:174 recording-datamonitor.cpp:179
+msgid "%1 dB"
+msgstr ""
+
+#: recording-monitor.cpp:34
+msgid "Recording Monitor"
+msgstr ""
+
+#: recording-monitor.cpp:38 recording.cpp:47
+msgid "TDERadio Recording Monitor"
+msgstr ""
+
+#: recording-monitor.cpp:43
+msgid "SoundStream"
+msgstr ""
+
+#: recording-monitor.cpp:45
+msgid "Status"
+msgstr ""
+
+#: recording-monitor.cpp:46 recording-monitor.cpp:48 recording-monitor.cpp:50
+#: recording-monitor.cpp:52 recording-monitor.cpp:54
+msgid "<undefined>"
+msgstr ""
+
+#: recording-monitor.cpp:47
+msgid "Recording File"
+msgstr ""
+
+#: recording-monitor.cpp:49
+msgid "File Size"
+msgstr ""
+
+#: recording-monitor.cpp:51
+msgid "Recording Time"
+msgstr ""
+
+#: recording-configuration-ui.ui:359 recording-monitor.cpp:53
+#, no-c-format
+msgid "Sample Rate"
+msgstr ""
+
+#: recording-monitor.cpp:57 recording-monitor.cpp:393 recording-monitor.cpp:396
+msgid "&Record"
+msgstr ""
+
+#: recording-monitor.cpp:74 recording-monitor.cpp:118 recording-monitor.cpp:141
+msgid "nothing"
+msgstr ""
+
+#: recording-monitor.cpp:339
+msgid "%1 Byte"
+msgstr ""
+
+#: recording-monitor.cpp:340
+msgid "%1 kB"
+msgstr ""
+
+#: recording-monitor.cpp:341
+msgid "%1 MB"
+msgstr ""
+
+#: recording-monitor.cpp:342
+msgid "%1 GB"
+msgstr ""
+
+#: recording-monitor.cpp:345
+msgid "%1 Hz"
+msgstr ""
+
+#: recording-monitor.cpp:393
+msgid "&Stop Recording"
+msgstr ""
+
+#: recording.cpp:46 recording.cpp:54
+msgid "TDERadio Recording Plugin"
+msgstr ""
+
+#: recording.cpp:131 recording.cpp:132
+msgid "Recording"
+msgstr ""
+
+#: recording.cpp:360
+msgid "start capture not handled"
+msgstr ""
+
+#: recording.cpp:367
+msgid "Recording starting"
+msgstr ""
+
+#: recording.cpp:369
+msgid "starting encoding thread failed"
+msgstr ""
+
+#: recording.cpp:451
+msgid "could not read suffient data"
+msgstr ""
+
+#: recording.cpp:482
+msgid ""
+"Encoder input buffer overflow (buffer configuration problem?). Skipped %1 "
+"input bytes"
+msgstr ""
+
+#: recording.cpp:544
+msgid "Recording::outputFile: "
+msgstr ""
+
+#: recording.cpp:594
+msgid "The encoding thread did not finish. It will be killed now."
+msgstr ""
+
+#: recording.cpp:614
+msgid "Recording stopped"
+msgstr ""
+
+#: recording.cpp:647
+msgid ""
+"Recording::notifySoundStreamData(encoded data): Receivers skipped %1 Bytes"
+msgstr ""
+
+#: recording-configuration-ui.ui:16
+#, no-c-format
+msgid "RecordingConfigurationUI"
+msgstr ""
+
+#: recording-configuration-ui.ui:34
+#, no-c-format
+msgid "Output"
+msgstr ""
+
+#: recording-configuration-ui.ui:138
+#, no-c-format
+msgid "MP3 Quality(0 - high, 9 - low)"
+msgstr ""
+
+#: recording-configuration-ui.ui:149
+#, no-c-format
+msgid "raw pcm output (.raw)"
+msgstr ""
+
+#: recording-configuration-ui.ui:154
+#, no-c-format
+msgid "Microsoft Wave (.wav)"
+msgstr ""
+
+#: recording-configuration-ui.ui:159
+#, no-c-format
+msgid "Apple/SGI (.aiff)"
+msgstr ""
+
+#: recording-configuration-ui.ui:164
+#, no-c-format
+msgid "Sun/NeXT (.au)"
+msgstr ""
+
+#: recording-configuration-ui.ui:169
+#, no-c-format
+msgid "MP3 Compressed (.mp3)"
+msgstr ""
+
+#: recording-configuration-ui.ui:174
+#, no-c-format
+msgid "Ogg/Vorbis Compressed (.ogg)"
+msgstr ""
+
+#: recording-configuration-ui.ui:194
+#, no-c-format
+msgid "Recording Directory"
+msgstr ""
+
+#: recording-configuration-ui.ui:202
+#, no-c-format
+msgid "File Format"
+msgstr ""
+
+#: recording-configuration-ui.ui:210
+#, no-c-format
+msgid "Ogg Quality(0 - low, 9 - high)"
+msgstr ""
+
+#: recording-configuration-ui.ui:239
+#, no-c-format
+msgid "I&nput"
+msgstr ""
+
+#: recording-configuration-ui.ui:276
+#, no-c-format
+msgid "48000"
+msgstr ""
+
+#: recording-configuration-ui.ui:281
+#, no-c-format
+msgid "44100"
+msgstr ""
+
+#: recording-configuration-ui.ui:286
+#, no-c-format
+msgid "22050"
+msgstr ""
+
+#: recording-configuration-ui.ui:291
+#, no-c-format
+msgid "11025"
+msgstr ""
+
+#: recording-configuration-ui.ui:311
+#, no-c-format
+msgid "Endianess"
+msgstr ""
+
+#: recording-configuration-ui.ui:334
+#, no-c-format
+msgid "Stereo"
+msgstr ""
+
+#: recording-configuration-ui.ui:339
+#, no-c-format
+msgid "Mono"
+msgstr ""
+
+#: recording-configuration-ui.ui:365
+#, no-c-format
+msgid "Little Endian"
+msgstr ""
+
+#: recording-configuration-ui.ui:370
+#, no-c-format
+msgid "Big Endian"
+msgstr ""
+
+#: recording-configuration-ui.ui:388
+#, no-c-format
+msgid "16"
+msgstr ""
+
+#: recording-configuration-ui.ui:393
+#, no-c-format
+msgid "8"
+msgstr ""
+
+#: recording-configuration-ui.ui:413
+#, no-c-format
+msgid "Channels"
+msgstr ""
+
+#: recording-configuration-ui.ui:421
+#, no-c-format
+msgid "Sample Bits"
+msgstr ""
+
+#: recording-configuration-ui.ui:427
+#, no-c-format
+msgid "Signed"
+msgstr ""
+
+#: recording-configuration-ui.ui:432
+#, no-c-format
+msgid "Unsigned"
+msgstr ""
+
+#: recording-configuration-ui.ui:490
+#, no-c-format
+msgid "&Buffers"
+msgstr ""
+
+#: recording-configuration-ui.ui:512
+#, no-c-format
+msgid " kB"
+msgstr ""
+
+#: recording-configuration-ui.ui:532
+#, no-c-format
+msgid "Encoding Buffer Size"
+msgstr ""
+
+#: recording-configuration-ui.ui:551
+#, no-c-format
+msgid "Number of Buffers"
+msgstr ""
+
+#: recording-configuration-ui.ui:580
+#, no-c-format
+msgid "Pre-Recordin&g"
+msgstr ""
+
+#: recording-configuration-ui.ui:610
+#, no-c-format
+msgid "E&nable"
+msgstr ""
+
+#: recording-configuration-ui.ui:613
+#, no-c-format
+msgid "Alt+N"
+msgstr ""
+
+#: recording-configuration-ui.ui:651
+#, no-c-format
+msgid "PreRecording Time"
+msgstr ""
+
+#: recording-configuration-ui.ui:662
+#, no-c-format
+msgid " s"
+msgstr ""
diff --git a/plugins/recording/reccfg_interfaces.cpp b/plugins/recording/reccfg_interfaces.cpp
new file mode 100644
index 0000000..9cbc9e6
--- /dev/null
+++ b/plugins/recording/reccfg_interfaces.cpp
@@ -0,0 +1,151 @@
+/***************************************************************************
+ reccfg_interfaces.cpp - description
+ -------------------
+ begin : Sun May 01 2005
+ copyright : (C) 2005by 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 <linux/soundcard.h>
+#include "reccfg_interfaces.h"
+
+// IRecCfg
+
+IF_IMPL_SENDER ( IRecCfg::notifyEncoderBufferChanged (size_t BufferSize, size_t BufferCount),
+ noticeEncoderBufferChanged(BufferSize, BufferCount)
+ );
+IF_IMPL_SENDER ( IRecCfg::notifySoundFormatChanged(const SoundFormat &sf),
+ noticeSoundFormatChanged(sf)
+ );
+IF_IMPL_SENDER ( IRecCfg::notifyMP3QualityChanged(int q),
+ noticeMP3QualityChanged(q)
+ );
+IF_IMPL_SENDER ( IRecCfg::notifyOggQualityChanged(float q),
+ noticeOggQualityChanged(q)
+ );
+IF_IMPL_SENDER ( IRecCfg::notifyRecordingDirectoryChanged(const TQString &dir),
+ noticeRecordingDirectoryChanged(dir)
+ );
+IF_IMPL_SENDER ( IRecCfg::notifyOutputFormatChanged(RecordingConfig::OutputFormat of),
+ noticeOutputFormatChanged(of)
+ );
+IF_IMPL_SENDER ( IRecCfg::notifyPreRecordingChanged(bool enable, int seconds),
+ noticePreRecordingChanged(enable, seconds)
+ );
+IF_IMPL_SENDER ( IRecCfg::notifyRecordingConfigChanged (const RecordingConfig &cfg),
+ noticeRecordingConfigChanged(cfg)
+ );
+
+// IRecCfgClient
+
+IF_IMPL_SENDER ( IRecCfgClient::sendEncoderBuffer (size_t BufferSize, size_t BufferCount),
+ setEncoderBuffer(BufferSize, BufferCount)
+ );
+IF_IMPL_SENDER ( IRecCfgClient::sendSoundFormat(const SoundFormat &sf),
+ setSoundFormat(sf)
+ );
+IF_IMPL_SENDER ( IRecCfgClient::sendMP3Quality(int q),
+ setMP3Quality(q)
+ );
+IF_IMPL_SENDER ( IRecCfgClient::sendOggQuality(float q),
+ setOggQuality(q)
+ );
+IF_IMPL_SENDER ( IRecCfgClient::sendRecordingDirectory(const TQString &dir),
+ setRecordingDirectory(dir)
+ );
+IF_IMPL_SENDER ( IRecCfgClient::sendOutputFormat(RecordingConfig::OutputFormat of),
+ setOutputFormat(of)
+ );
+IF_IMPL_SENDER ( IRecCfgClient::sendPreRecording(bool enable, int seconds),
+ setPreRecording(enable, seconds)
+ );
+IF_IMPL_SENDER ( IRecCfgClient::sendRecordingConfig(const RecordingConfig &cfg),
+ setRecordingConfig(cfg)
+ );
+
+IF_IMPL_QUERY ( void IRecCfgClient::queryEncoderBuffer(size_t &BufferSize, size_t &BufferCount),
+ getEncoderBuffer(BufferSize, BufferCount),
+
+ );
+
+static SoundFormat defaultSoundFormat;
+IF_IMPL_QUERY ( const SoundFormat &IRecCfgClient::querySoundFormat (),
+ getSoundFormat(),
+ defaultSoundFormat
+ );
+
+IF_IMPL_QUERY ( int IRecCfgClient::queryMP3Quality (),
+ getMP3Quality(),
+ 7
+ );
+
+IF_IMPL_QUERY ( float IRecCfgClient::queryOggQuality (),
+ getOggQuality(),
+ 7
+ );
+
+static TQString defaultRecDir("/tmp");
+IF_IMPL_QUERY ( const TQString &IRecCfgClient::queryRecordingDirectory(),
+ getRecordingDirectory(),
+ defaultRecDir
+ );
+
+IF_IMPL_QUERY ( RecordingConfig::OutputFormat IRecCfgClient::queryOutputFormat(),
+ getOutputFormat(),
+ RecordingConfig::outputWAV
+ );
+
+IF_IMPL_QUERY ( bool IRecCfgClient::queryPreRecording(int &seconds),
+ getPreRecording(seconds),
+ false
+ );
+
+static RecordingConfig defaultRecConfig;
+IF_IMPL_QUERY ( const RecordingConfig &IRecCfgClient::queryRecordingConfig(),
+ getRecordingConfig(),
+ defaultRecConfig
+ );
+
+void IRecCfgClient::noticeConnectedI (cmplInterface *, bool /*pointer_valid*/)
+{
+ size_t bs = 0, bc = 0;
+ queryEncoderBuffer(bs, bc);
+ noticeEncoderBufferChanged(bs, bc);
+ noticeSoundFormatChanged(querySoundFormat());
+ noticeMP3QualityChanged (queryMP3Quality());
+ noticeOggQualityChanged (queryOggQuality());
+ noticeRecordingDirectoryChanged(queryRecordingDirectory());
+ noticeOutputFormatChanged(queryOutputFormat());
+ int s = 0;
+ bool e = queryPreRecording(s);
+ noticePreRecordingChanged(e, s);
+ noticeRecordingConfigChanged(queryRecordingConfig());
+}
+
+
+void IRecCfgClient::noticeDisconnectedI (cmplInterface *, bool /*pointer_valid*/)
+{
+ size_t bs = 0, bc = 0;
+ queryEncoderBuffer(bs, bc);
+ noticeEncoderBufferChanged(bs, bc);
+ noticeSoundFormatChanged(querySoundFormat());
+ noticeMP3QualityChanged (queryMP3Quality());
+ noticeOggQualityChanged (queryOggQuality());
+ noticeRecordingDirectoryChanged(queryRecordingDirectory());
+ noticeOutputFormatChanged(queryOutputFormat());
+ int s = 0;
+ bool e = queryPreRecording(s);
+ noticePreRecordingChanged(e, s);
+ noticeRecordingConfigChanged(queryRecordingConfig());
+}
+
+
diff --git a/plugins/recording/reccfg_interfaces.h b/plugins/recording/reccfg_interfaces.h
new file mode 100644
index 0000000..937ca42
--- /dev/null
+++ b/plugins/recording/reccfg_interfaces.h
@@ -0,0 +1,102 @@
+/***************************************************************************
+ reccfg_interfaces.h - description
+ -------------------
+ begin : Sun May 01 2005
+ copyright : (C) 2005 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_RECCFG_INTERFACES_H
+#define KRADIO_RECCFG_INTERFACES_H
+
+#include "../../src/include/interfaces.h"
+#include "recording-config.h"
+
+INTERFACE(IRecCfg, IRecCfgClient)
+{
+public:
+ IF_CON_DESTRUCTOR(IRecCfg, -1)
+
+RECEIVERS:
+ IF_RECEIVER( setEncoderBuffer (size_t BufferSize, size_t BufferCount) )
+ IF_RECEIVER( setSoundFormat (const SoundFormat &sf) )
+ IF_RECEIVER( setMP3Quality (int q) )
+ IF_RECEIVER( setOggQuality (float q) )
+ IF_RECEIVER( setRecordingDirectory(const TQString &dir) )
+ IF_RECEIVER( setOutputFormat (RecordingConfig::OutputFormat of) )
+ IF_RECEIVER( setPreRecording (bool enable, int seconds) )
+ IF_RECEIVER( setRecordingConfig (const RecordingConfig &cfg) )
+
+SENDERS:
+ IF_SENDER ( notifyEncoderBufferChanged (size_t BufferSize, size_t BufferCount) )
+ IF_SENDER ( notifySoundFormatChanged (const SoundFormat &sf) )
+ IF_SENDER ( notifyMP3QualityChanged (int q) )
+ IF_SENDER ( notifyOggQualityChanged (float q) )
+ IF_SENDER ( notifyRecordingDirectoryChanged(const TQString &dir) )
+ IF_SENDER ( notifyOutputFormatChanged (RecordingConfig::OutputFormat of) )
+ IF_SENDER ( notifyPreRecordingChanged (bool enable, int seconds) )
+ IF_SENDER ( notifyRecordingConfigChanged (const RecordingConfig &cfg) )
+
+ANSWERS:
+ IF_ANSWER ( void getEncoderBuffer(size_t &BufferSize, size_t &BufferCount) const )
+ IF_ANSWER ( const SoundFormat &getSoundFormat () const )
+ IF_ANSWER ( int getMP3Quality () const )
+ IF_ANSWER ( float getOggQuality () const )
+ IF_ANSWER ( const TQString &getRecordingDirectory() const )
+ IF_ANSWER ( RecordingConfig::OutputFormat getOutputFormat() const )
+ IF_ANSWER ( bool getPreRecording(int &seconds) const )
+ IF_ANSWER ( const RecordingConfig &getRecordingConfig() const )
+};
+
+
+
+INTERFACE(IRecCfgClient, IRecCfg)
+{
+public:
+ IF_CON_DESTRUCTOR(IRecCfgClient, 1)
+
+SENDERS:
+ IF_SENDER ( sendEncoderBuffer (size_t BufferSize, size_t BufferCount) )
+ IF_SENDER ( sendSoundFormat (const SoundFormat &sf) )
+ IF_SENDER ( sendMP3Quality (int q) )
+ IF_SENDER ( sendOggQuality (float q) )
+ IF_SENDER ( sendRecordingDirectory(const TQString &dir) )
+ IF_SENDER ( sendOutputFormat (RecordingConfig::OutputFormat of) )
+ IF_SENDER ( sendPreRecording (bool enable, int seconds) )
+ IF_SENDER ( sendRecordingConfig (const RecordingConfig &cfg) )
+
+RECEIVERS:
+ IF_RECEIVER( noticeEncoderBufferChanged (size_t BufferSize, size_t BufferCount) )
+ IF_RECEIVER( noticeSoundFormatChanged (const SoundFormat &sf) )
+ IF_RECEIVER( noticeMP3QualityChanged (int q) )
+ IF_RECEIVER( noticeOggQualityChanged (float q) )
+ IF_RECEIVER( noticeRecordingDirectoryChanged(const TQString &dir) )
+ IF_RECEIVER( noticeOutputFormatChanged (RecordingConfig::OutputFormat of) )
+ IF_RECEIVER( noticePreRecordingChanged (bool enable, int seconds) )
+ IF_RECEIVER( noticeRecordingConfigChanged (const RecordingConfig &cfg) )
+
+QUERIES:
+ IF_QUERY ( void queryEncoderBuffer(size_t &BufferSize, size_t &BufferCount) )
+ IF_QUERY ( const SoundFormat &querySoundFormat () )
+ IF_QUERY ( int queryMP3Quality () )
+ IF_QUERY ( float queryOggQuality () )
+ IF_QUERY ( const TQString &queryRecordingDirectory() )
+ IF_QUERY ( RecordingConfig::OutputFormat queryOutputFormat() )
+ IF_QUERY ( bool queryPreRecording(int &seconds) )
+ IF_QUERY ( const RecordingConfig &queryRecordingConfig() )
+
+RECEIVERS:
+ virtual void noticeConnectedI (cmplInterface *, bool /*pointer_valid*/);
+ virtual void noticeDisconnectedI (cmplInterface *, bool /*pointer_valid*/);
+};
+
+#endif
diff --git a/plugins/recording/recording-config.cpp b/plugins/recording/recording-config.cpp
new file mode 100644
index 0000000..2395e28
--- /dev/null
+++ b/plugins/recording/recording-config.cpp
@@ -0,0 +1,215 @@
+/***************************************************************************
+ recording-config.cpp - description
+ -------------------
+ begin : Mi Apr 30 2005
+ copyright : (C) 2005 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 "recording-config.h"
+
+#include <sndfile.h>
+
+RecordingConfig::RecordingConfig ()
+: m_EncodeBufferSize(256*1024),
+ m_EncodeBufferCount(3),
+ m_mp3Quality(7),
+ m_oggQuality(1.0),
+ m_Directory("/tmp"),
+ m_OutputFormat(outputWAV),
+ m_PreRecordingEnable (false),
+ m_PreRecordingSeconds(10)
+{
+ checkFormatSettings();
+}
+
+RecordingConfig::RecordingConfig (const TQString &directory,
+ OutputFormat of,
+ const SoundFormat &sf, int mp3_q, float ogg_q)
+: m_EncodeBufferSize(256*1024),
+ m_EncodeBufferCount(3),
+ m_SoundFormat(sf),
+ m_mp3Quality(mp3_q),
+ m_oggQuality(ogg_q),
+ m_Directory(directory),
+ m_OutputFormat(of),
+ m_PreRecordingEnable (false),
+ m_PreRecordingSeconds(10)
+{
+ checkFormatSettings();
+}
+
+
+RecordingConfig::RecordingConfig (const RecordingConfig &c)
+ :
+ m_EncodeBufferSize(c.m_EncodeBufferSize),
+ m_EncodeBufferCount(c.m_EncodeBufferCount),
+ m_SoundFormat(c.m_SoundFormat),
+ m_mp3Quality(c.m_mp3Quality),
+ m_oggQuality(c.m_oggQuality),
+ m_Directory(c.m_Directory),
+ m_OutputFormat(c.m_OutputFormat),
+ m_PreRecordingEnable (false),
+ m_PreRecordingSeconds(10)
+{
+ checkFormatSettings();
+}
+
+
+void RecordingConfig::restoreConfig(TDEConfig *c)
+{
+ m_EncodeBufferSize = c->readNumEntry("encodeBufferSize", 256*1024);
+ m_EncodeBufferCount = c->readNumEntry("encodeBufferCount", 3);
+
+ m_SoundFormat.restoreConfig("", c);
+ m_Directory = c->readEntry("directory", "/tmp");
+ m_mp3Quality = c->readNumEntry("mp3quality", 7);
+ m_oggQuality = c->readDoubleNumEntry("oggquality", 1.0);
+ TQString of = c->readEntry("outputFormat", ".wav");
+
+ if (of == ".wav")
+ m_OutputFormat = outputWAV;
+ else if (of == ".aiff")
+ m_OutputFormat = outputAIFF;
+ else if (of == ".au")
+ m_OutputFormat = outputAU;
+#ifdef HAVE_LAME
+ else if (of == ".mp3")
+ m_OutputFormat = outputMP3;
+#endif
+#ifdef HAVE_OGG
+ else if (of == ".ogg")
+ m_OutputFormat = outputOGG;
+#endif
+ else if (of == ".raw")
+ m_OutputFormat = outputRAW;
+
+ // if there was any unknown format
+ else
+ m_OutputFormat = outputWAV;
+
+ m_PreRecordingEnable = c->readBoolEntry("prerecording-enable", false);
+ m_PreRecordingSeconds = c->readNumEntry("prerecording-seconds", 10);
+
+ checkFormatSettings();
+}
+
+
+void RecordingConfig::saveConfig(TDEConfig *c) const
+{
+ c->writeEntry("encodeBufferSize", m_EncodeBufferSize);
+ c->writeEntry("encodeBufferCount", m_EncodeBufferCount);
+ m_SoundFormat.saveConfig("", c);
+ c->writeEntry("directory", m_Directory);
+ c->writeEntry("mp3quality", m_mp3Quality);
+ c->writeEntry("oggquality", m_oggQuality);
+
+ switch(m_OutputFormat) {
+ case outputWAV: c->writeEntry("outputFormat", ".wav"); break;
+ case outputAIFF: c->writeEntry("outputFormat", ".aiff"); break;
+ case outputAU: c->writeEntry("outputFormat", ".au"); break;
+ case outputMP3: c->writeEntry("outputFormat", ".mp3"); break;
+ case outputOGG: c->writeEntry("outputFormat", ".ogg"); break;
+ case outputRAW: c->writeEntry("outputFormat", ".raw"); break;
+ default: c->writeEntry("outputFormat", ".wav"); break;
+ }
+
+ c->writeEntry("prerecording-enable", m_PreRecordingEnable);
+ c->writeEntry("prerecording-seconds", m_PreRecordingSeconds);
+}
+
+
+void RecordingConfig::getSoundFileInfo(SF_INFO &sinfo, bool input)
+{
+ checkFormatSettings();
+
+ sinfo.samplerate = m_SoundFormat.m_SampleRate;
+ sinfo.channels = m_SoundFormat.m_Channels;
+ sinfo.format = 0;
+ sinfo.seekable = !input;
+
+ // U8 only supported for RAW and WAV
+ if (m_SoundFormat.m_SampleBits == 8) {
+ if ((m_SoundFormat.m_IsSigned &&
+ m_OutputFormat != outputWAV) ||
+ m_OutputFormat == outputAU
+ ) {
+ sinfo.format |= SF_FORMAT_PCM_S8;
+ } else {
+ sinfo.format |= SF_FORMAT_PCM_U8;
+ }
+ }
+ if (m_SoundFormat.m_SampleBits == 16)
+ sinfo.format |= SF_FORMAT_PCM_16;
+
+ if (m_SoundFormat.m_Endianess == LITTLE_ENDIAN)
+ sinfo.format |= SF_ENDIAN_LITTLE;
+ else
+ sinfo.format |= SF_ENDIAN_BIG;
+
+ if (input) {
+ sinfo.format |= SF_FORMAT_RAW;
+ } else {
+ switch (m_OutputFormat) {
+ case outputWAV: sinfo.format |= SF_FORMAT_WAV; break;
+ case outputAIFF: sinfo.format |= SF_FORMAT_AIFF; break;
+ case outputAU: sinfo.format |= SF_FORMAT_AU; break;
+ case outputRAW: sinfo.format |= SF_FORMAT_RAW; break;
+ default: sinfo.format |= SF_FORMAT_WAV; break;
+ }
+ }
+}
+
+
+void RecordingConfig::checkFormatSettings()
+{
+ // correct Endianess and Signs for specific formats
+ switch (m_OutputFormat) {
+ case outputWAV:
+ m_SoundFormat.m_Endianess = LITTLE_ENDIAN;
+ if (m_SoundFormat.m_SampleBits == 8)
+ m_SoundFormat.m_IsSigned = false;
+ // libsndfile only supports signed 16 bit samples
+ if (m_SoundFormat.m_SampleBits == 16)
+ m_SoundFormat.m_IsSigned = true;
+ break;
+ case outputAIFF:
+ m_SoundFormat.m_Endianess = BIG_ENDIAN;
+ // libsndfile only supports signed 16 bit samples
+ if (m_SoundFormat.m_SampleBits == 16)
+ m_SoundFormat.m_IsSigned = true;
+ break;
+ case outputAU:
+ m_SoundFormat.m_Endianess = BIG_ENDIAN;
+ m_SoundFormat.m_IsSigned = true;
+ // libsndfile only supports signed 16 bit samples
+ if (m_SoundFormat.m_SampleBits == 16)
+ m_SoundFormat.m_IsSigned = true;
+ break;
+ case outputMP3:
+ m_SoundFormat.m_IsSigned = true;
+ m_SoundFormat.m_SampleBits = 16;
+ break;
+ case outputOGG:
+ m_SoundFormat.m_IsSigned = true;
+ m_SoundFormat.m_SampleBits = 16;
+ break;
+ case outputRAW:
+ // libsndfile only supports signed 16 bit samples
+ if (m_SoundFormat.m_SampleBits == 16)
+ m_SoundFormat.m_IsSigned = true;
+ break;
+ default:
+ break;
+ }
+}
+
diff --git a/plugins/recording/recording-config.h b/plugins/recording/recording-config.h
new file mode 100644
index 0000000..ba7ba52
--- /dev/null
+++ b/plugins/recording/recording-config.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ recording-config.h - description
+ -------------------
+ begin : Mi Apr 30 2005
+ copyright : (C) 2005 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_RECORDING_CONFIG_H
+#define KRADIO_RECORDING_CONFIG_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/soundformat.h"
+
+class TDEConfig;
+struct SF_INFO;
+
+class RecordingConfig
+{
+public:
+ enum OutputFormat {
+ outputWAV,
+ outputAIFF,
+ outputAU,
+ outputMP3,
+ outputOGG,
+ outputRAW
+ };
+
+public:
+ RecordingConfig ();
+ RecordingConfig (const TQString &directory,
+ OutputFormat of,
+ const SoundFormat &, int mp3_q, float ogg_q);
+ RecordingConfig (const RecordingConfig &c);
+
+ void restoreConfig(TDEConfig *c);
+ void saveConfig(TDEConfig *c) const;
+
+ void getSoundFileInfo(SF_INFO &info, bool input);
+
+ void checkFormatSettings();
+
+public:
+ size_t m_EncodeBufferSize;
+ size_t m_EncodeBufferCount;
+
+ SoundFormat m_SoundFormat;
+ int m_mp3Quality;
+ float m_oggQuality;
+ TQString m_Directory;
+ OutputFormat m_OutputFormat;
+
+ bool m_PreRecordingEnable;
+ int m_PreRecordingSeconds;
+};
+
+
+
+
+#endif
diff --git a/plugins/recording/recording-configuration-ui.ui b/plugins/recording/recording-configuration-ui.ui
new file mode 100644
index 0000000..99d7e0a
--- /dev/null
+++ b/plugins/recording/recording-configuration-ui.ui
@@ -0,0 +1,726 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>RecordingConfigurationUI</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>RecordingConfigurationUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>468</width>
+ <height>197</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>RecordingConfigurationUI</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>kTabWidget13</cstring>
+ </property>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>TabPage_2</cstring>
+ </property>
+ <attribute name="title">
+ <string>Output</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget" row="2" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout3_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>141</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>editOggQuality</cstring>
+ </property>
+ <property name="maxValue">
+ <number>9</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="value">
+ <number>7</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget" row="1" column="2">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>141</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>editMP3Quality</cstring>
+ </property>
+ <property name="maxValue">
+ <number>9</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="value">
+ <number>5</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLabel" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>labelMP3Quality</cstring>
+ </property>
+ <property name="text">
+ <string>MP3 Quality(0 - high, 9 - low)</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="3" column="2">
+ <property name="name">
+ <cstring>editDirectory</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="0" column="2">
+ <item>
+ <property name="text">
+ <string>raw pcm output (.raw)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Microsoft Wave (.wav)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Apple/SGI (.aiff)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Sun/NeXT (.au)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>MP3 Compressed (.mp3)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Ogg/Vorbis Compressed (.ogg)</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>editFileFormat</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>lableDirectory</cstring>
+ </property>
+ <property name="text">
+ <string>Recording Directory</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>lableFileFormat</cstring>
+ </property>
+ <property name="text">
+ <string>File Format</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>labelOggQuality</cstring>
+ </property>
+ <property name="text">
+ <string>Ogg Quality(0 - low, 9 - high)</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer132</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>I&amp;nput</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout69</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="0" column="2">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>225</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KComboBox" row="0" column="1">
+ <item>
+ <property name="text">
+ <string>48000</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>44100</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>22050</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>11025</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>editRate</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>lableEndianess</cstring>
+ </property>
+ <property name="text">
+ <string>Endianess</string>
+ </property>
+ </widget>
+ <spacer row="3" column="2">
+ <property name="name">
+ <cstring>spacer1_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>225</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KComboBox" row="3" column="1">
+ <item>
+ <property name="text">
+ <string>Stereo</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Mono</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>editChannels</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>labelRate</cstring>
+ </property>
+ <property name="text">
+ <string>Sample Rate</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="2" column="1">
+ <item>
+ <property name="text">
+ <string>Little Endian</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Big Endian</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>editEndianess</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="1">
+ <item>
+ <property name="text">
+ <string>16</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>8</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>editBits</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>lableChannels</cstring>
+ </property>
+ <property name="text">
+ <string>Channels</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>lableBits</cstring>
+ </property>
+ <property name="text">
+ <string>Sample Bits</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="2">
+ <item>
+ <property name="text">
+ <string>Signed</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Unsigned</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>editSign</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <spacer row="2" column="2">
+ <property name="name">
+ <cstring>spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>225</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer131</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>TabPage_3</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;Buffers</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQSpinBox" row="0" column="1">
+ <property name="name">
+ <cstring>editBufferSize</cstring>
+ </property>
+ <property name="suffix">
+ <string> kB</string>
+ </property>
+ <property name="maxValue">
+ <number>2048</number>
+ </property>
+ <property name="minValue">
+ <number>64</number>
+ </property>
+ <property name="lineStep">
+ <number>16</number>
+ </property>
+ <property name="value">
+ <number>256</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>labelEditBufferSize</cstring>
+ </property>
+ <property name="text">
+ <string>Encoding Buffer Size</string>
+ </property>
+ </widget>
+ <widget class="TQSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>editBufferCount</cstring>
+ </property>
+ <property name="minValue">
+ <number>3</number>
+ </property>
+ <property name="value">
+ <number>3</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>labelEditBufferCount</cstring>
+ </property>
+ <property name="text">
+ <string>Number of Buffers</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer132_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>TabPage_4</cstring>
+ </property>
+ <attribute name="title">
+ <string>Pre-Recordin&amp;g</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout68</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>m_checkboxPreRecordingEnable</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;nable</string>
+ </property>
+ <property name="accel">
+ <string>Alt+N</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>380</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>m_labelPreRecordingTime</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>PreRecording Time</string>
+ </property>
+ </widget>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>m_spinboxPreRecordingSeconds</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="suffix">
+ <string> s</string>
+ </property>
+ <property name="maxValue">
+ <number>999</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="lineStep">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>10</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer132_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>m_checkboxPreRecordingEnable</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_spinboxPreRecordingSeconds</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_checkboxPreRecordingEnable</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_labelPreRecordingTime</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<layoutdefaults spacing="6" margin="0"/>
+<includes>
+ <include location="global" impldecl="in implementation">kcombobox.h</include>
+ <include location="global" impldecl="in implementation">klineedit.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/recording/recording-configuration.cpp b/plugins/recording/recording-configuration.cpp
new file mode 100644
index 0000000..f35f7dd
--- /dev/null
+++ b/plugins/recording/recording-configuration.cpp
@@ -0,0 +1,414 @@
+/***************************************************************************
+ recording-configuration.cpp - description
+ -------------------
+ begin : So Aug 31 2003
+ copyright : (C) 2003 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 "recording-configuration.h"
+//#include "recording-context.h"
+
+#include <kurlrequester.h>
+#include <kcombobox.h>
+#include <tqspinbox.h>
+#include <tqlabel.h>
+#include <tqcheckbox.h>
+
+#include <ktabwidget.h>
+
+
+RecordingConfiguration::RecordingConfiguration (TQWidget *parent)
+ : RecordingConfigurationUI(parent),
+ m_dirty(true),
+ m_ignore_gui_updates(false)
+{
+ editDirectory->setMode(KFile::Directory | KFile::ExistingOnly);
+
+ TQObject::connect(editFileFormat, TQT_SIGNAL(activated(int)),
+ this, TQT_SLOT(slotFormatSelectionChanged()));
+ TQObject::connect(editBits, TQT_SIGNAL(activated(int)),
+ this, TQT_SLOT(slotFormatSelectionChanged()));
+
+ connect(editRate, TQT_SIGNAL(activated(int)), TQT_SLOT(slotSetDirty()));
+ connect(editBits, TQT_SIGNAL(activated(int)), TQT_SLOT(slotSetDirty()));
+ connect(editSign, TQT_SIGNAL(activated(int)), TQT_SLOT(slotSetDirty()));
+ connect(editEndianess, TQT_SIGNAL(activated(int)), TQT_SLOT(slotSetDirty()));
+ connect(editChannels, TQT_SIGNAL(activated(int)), TQT_SLOT(slotSetDirty()));
+ connect(editFileFormat, TQT_SIGNAL(activated(int)), TQT_SLOT(slotSetDirty()));
+ connect(editMP3Quality, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotSetDirty()));
+ connect(editOggQuality, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotSetDirty()));
+ connect(editDirectory, TQT_SIGNAL(textChanged(const TQString &)), TQT_SLOT(slotSetDirty()));
+ connect(editBufferSize, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotSetDirty()));
+ connect(editBufferCount, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotSetDirty()));
+ connect(m_spinboxPreRecordingSeconds, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotSetDirty()));
+ connect(m_checkboxPreRecordingEnable, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotSetDirty()));
+
+// attention: remove items with higher index first ;-) otherwise indexes are not valid
+#ifndef HAVE_OGG
+ editFileFormat->removeItem(FORMAT_OGG_IDX_ORG);
+ delete editOggQuality;
+ editOggQuality = NULL;
+ delete labelOggQuality;
+ labelOggQuality = NULL;
+#endif
+#ifndef HAVE_LAME
+ editFileFormat->removeItem(FORMAT_MP3_IDX_ORG);
+ delete editMP3Quality;
+ editMP3Quality = NULL;
+ delete labelMP3Quality;
+ labelMP3Quality = NULL;
+#endif
+}
+
+
+RecordingConfiguration::~RecordingConfiguration ()
+{
+}
+
+
+void RecordingConfiguration::setGUIBuffers(const RecordingConfig &c)
+{
+ editBufferSize->setValue(c.m_EncodeBufferSize / 1024);
+ editBufferCount->setValue(c.m_EncodeBufferCount);
+}
+
+void RecordingConfiguration::setGUIDirectories(const RecordingConfig &c)
+{
+ editDirectory->setURL(c.m_Directory);
+}
+
+void RecordingConfiguration::setGUISoundFormat(const RecordingConfig &c)
+{
+ switch (c.m_SoundFormat.m_SampleBits) {
+ case 8 : editBits->setCurrentItem(BITS_8_IDX ); break;
+ case 16: editBits->setCurrentItem(BITS_16_IDX); break;
+ default: editBits->setCurrentItem(BITS_16_IDX);
+ }
+ switch (c.m_SoundFormat.m_Channels) {
+ case 1 : editChannels->setCurrentItem(CHANNELS_MONO_IDX); break;
+ case 2 : editChannels->setCurrentItem(CHANNELS_STEREO_IDX); break;
+ default: editChannels->setCurrentItem(CHANNELS_STEREO_IDX); break;
+ }
+ switch (c.m_SoundFormat.m_IsSigned) {
+ case 0 : editSign->setCurrentItem(SIGN_UNSIGNED_IDX); break;
+ case 1 : editSign->setCurrentItem(SIGN_SIGNED_IDX); break;
+ default: editSign->setCurrentItem(SIGN_SIGNED_IDX); break;
+ }
+ switch (c.m_SoundFormat.m_SampleRate) {
+ case 48000: editRate->setCurrentItem(RATE_48000_IDX); break;
+ case 44100: editRate->setCurrentItem(RATE_44100_IDX); break;
+ case 22050: editRate->setCurrentItem(RATE_22050_IDX); break;
+ case 11025: editRate->setCurrentItem(RATE_11025_IDX); break;
+ default: editRate->setCurrentItem(RATE_44100_IDX); break;
+ }
+ switch (c.m_SoundFormat.m_Endianess) {
+ case BIG_ENDIAN : editEndianess->setCurrentItem(ENDIAN_BIG_IDX); break;
+ case LITTLE_ENDIAN : editEndianess->setCurrentItem(ENDIAN_LITTLE_IDX); break;
+ default: editEndianess->setCurrentItem(ENDIAN_LITTLE_IDX); break;
+ }
+}
+
+void RecordingConfiguration::setGUIOutputFormat(const RecordingConfig &c)
+{
+ switch (c.m_OutputFormat) {
+ case RecordingConfig::outputWAV: editFileFormat->setCurrentItem(FORMAT_WAV_IDX); break;
+ case RecordingConfig::outputAIFF: editFileFormat->setCurrentItem(FORMAT_AIFF_IDX); break;
+ case RecordingConfig::outputAU: editFileFormat->setCurrentItem(FORMAT_AU_IDX); break;
+ case RecordingConfig::outputRAW: editFileFormat->setCurrentItem(FORMAT_RAW_IDX); break;
+#ifdef HAVE_LAME
+ case RecordingConfig::outputMP3: editFileFormat->setCurrentItem(FORMAT_MP3_IDX); break;
+#endif
+#ifdef HAVE_OGG
+ case RecordingConfig::outputOGG: editFileFormat->setCurrentItem(FORMAT_OGG_IDX); break;
+#endif
+ default: editFileFormat->setCurrentItem(FORMAT_WAV_IDX); break;
+ }
+}
+
+void RecordingConfiguration::setGUIEncoderQuality(const RecordingConfig &c)
+{
+#ifdef HAVE_LAME
+ editMP3Quality->setValue(c.m_mp3Quality);
+#endif
+#ifdef HAVE_OGG
+ editOggQuality->setValue((int)(c.m_oggQuality * 9));
+#endif
+}
+
+
+void RecordingConfiguration::setGUIPreRecording(const RecordingConfig &c)
+{
+ m_spinboxPreRecordingSeconds->setValue(c.m_PreRecordingSeconds);
+ m_checkboxPreRecordingEnable->setChecked(c.m_PreRecordingEnable);
+}
+
+
+void RecordingConfiguration::slotOK()
+{
+ if (m_dirty) {
+ storeConfig();
+ sendRecordingConfig(m_RecordingConfig);
+ m_dirty = false;
+ }
+}
+
+
+void RecordingConfiguration::storeConfig()
+{
+ RecordingConfig &c = m_RecordingConfig;
+
+ c.m_EncodeBufferSize = editBufferSize->value() * 1024;
+ c.m_EncodeBufferCount = editBufferCount->value();
+
+ c.m_Directory = editDirectory->url();
+
+ switch(editRate->currentItem()) {
+ case RATE_48000_IDX: c.m_SoundFormat.m_SampleRate = 48000; break;
+ case RATE_44100_IDX: c.m_SoundFormat.m_SampleRate = 44100; break;
+ case RATE_22050_IDX: c.m_SoundFormat.m_SampleRate = 22050; break;
+ case RATE_11025_IDX: c.m_SoundFormat.m_SampleRate = 11025; break;
+ default: c.m_SoundFormat.m_SampleRate = 44100; break;
+ }
+ switch(editChannels->currentItem()) {
+ case CHANNELS_MONO_IDX: c.m_SoundFormat.m_Channels = 1; break;
+ case CHANNELS_STEREO_IDX: c.m_SoundFormat.m_Channels = 2; break;
+ default: c.m_SoundFormat.m_Channels = 2; break;
+ }
+ switch(editSign->currentItem()) {
+ case SIGN_UNSIGNED_IDX: c.m_SoundFormat.m_IsSigned = false; break;
+ case SIGN_SIGNED_IDX: c.m_SoundFormat.m_IsSigned = true; break;
+ default: c.m_SoundFormat.m_IsSigned = true; break;
+ }
+ switch(editEndianess->currentItem()) {
+ case ENDIAN_LITTLE_IDX: c.m_SoundFormat.m_Endianess = LITTLE_ENDIAN; break;
+ case ENDIAN_BIG_IDX: c.m_SoundFormat.m_Endianess = BIG_ENDIAN; break;
+ default: c.m_SoundFormat.m_Endianess = LITTLE_ENDIAN; break;
+ }
+ switch(editBits->currentItem()) {
+ case BITS_8_IDX: c.m_SoundFormat.m_SampleBits = 8; break;
+ case BITS_16_IDX: c.m_SoundFormat.m_SampleBits = 16; break;
+ default: c.m_SoundFormat.m_SampleBits = 16; break;
+ }
+ switch(editFileFormat->currentItem()) {
+ case FORMAT_WAV_IDX: c.m_OutputFormat = RecordingConfig::outputWAV; break;
+ case FORMAT_AIFF_IDX: c.m_OutputFormat = RecordingConfig::outputAIFF; break;
+ case FORMAT_AU_IDX: c.m_OutputFormat = RecordingConfig::outputAU; break;
+ case FORMAT_RAW_IDX: c.m_OutputFormat = RecordingConfig::outputRAW; break;
+#ifdef HAVE_LAME
+ case FORMAT_MP3_IDX: c.m_OutputFormat = RecordingConfig::outputMP3; break;
+#endif
+#ifdef HAVE_OGG
+ case FORMAT_OGG_IDX: c.m_OutputFormat = RecordingConfig::outputOGG; break;
+#endif
+ default: c.m_OutputFormat = RecordingConfig::outputWAV; break;
+ }
+#ifdef HAVE_LAME
+ c.m_mp3Quality = editMP3Quality->value();
+#endif
+#ifdef HAVE_OGG
+ c.m_oggQuality = ((float)editOggQuality->value()) / 9.0f;
+#endif
+
+ c.m_PreRecordingEnable = m_checkboxPreRecordingEnable->isChecked();
+ c.m_PreRecordingSeconds = m_spinboxPreRecordingSeconds->value();
+
+ c.checkFormatSettings();
+}
+
+
+void RecordingConfiguration::slotCancel()
+{
+ if (m_dirty) {
+ noticeRecordingConfigChanged(m_RecordingConfig);
+ m_dirty = false;
+ }
+}
+
+
+void RecordingConfiguration::slotFormatSelectionChanged()
+{
+ int bitsIDX = editBits->currentItem();
+ int formatIDX = editFileFormat->currentItem();
+
+ int endianTest = 0x04030201;
+ bool littleEndian = ((char*)&endianTest)[0] == 0x01;
+
+#ifdef HAVE_LAME
+ editMP3Quality ->setEnabled(false);
+ labelMP3Quality->setEnabled(false);
+#endif
+#ifdef HAVE_OGG
+ editOggQuality ->setEnabled(false);
+ labelOggQuality->setEnabled(false);
+#endif
+
+ editBits->setEnabled(true);
+
+ if (formatIDX == FORMAT_MP3_IDX) {
+ editBits->setDisabled(true);
+ editBits->setCurrentItem(BITS_16_IDX);
+ editSign->setDisabled(true);
+ editSign->setCurrentItem(SIGN_SIGNED_IDX);
+#ifdef HAVE_LAME
+ editMP3Quality ->setEnabled(true);
+ labelMP3Quality->setEnabled(true);
+#endif
+ } else if (formatIDX == FORMAT_OGG_IDX) {
+ editBits->setDisabled(true);
+ editBits->setCurrentItem(BITS_16_IDX);
+ editSign->setDisabled(true);
+ editSign->setCurrentItem(SIGN_SIGNED_IDX);
+#ifdef HAVE_OGG
+ editOggQuality ->setEnabled(true);
+ labelOggQuality->setEnabled(true);
+#endif
+ } else {
+ if (bitsIDX == BITS_8_IDX) {
+ if (formatIDX == FORMAT_RAW_IDX || formatIDX == FORMAT_AIFF_IDX) {
+ editSign->setDisabled(false);
+ } else {
+ editSign->setDisabled(true);
+ editSign->setCurrentItem(formatIDX == FORMAT_WAV_IDX ? SIGN_UNSIGNED_IDX : SIGN_SIGNED_IDX);
+ }
+ } else {
+ editSign->setDisabled(true);
+ editSign->setCurrentItem(SIGN_SIGNED_IDX);
+ }
+ }
+
+ switch (formatIDX) {
+ case FORMAT_RAW_IDX :
+ editEndianess->setDisabled(false);
+ break;
+#ifdef HAVE_LAME
+ case FORMAT_MP3_IDX :
+ editEndianess->setCurrentItem(littleEndian ? ENDIAN_LITTLE_IDX : ENDIAN_BIG_IDX);
+ editEndianess->setDisabled(true);
+ break;
+#endif
+#ifdef HAVE_OGG
+ case FORMAT_OGG_IDX :
+ editEndianess->setCurrentItem(littleEndian ? ENDIAN_LITTLE_IDX : ENDIAN_BIG_IDX);
+ editEndianess->setDisabled(true);
+ break;
+#endif
+ default:
+ editEndianess->setDisabled(true);
+ if (formatIDX == FORMAT_AIFF_IDX || formatIDX == FORMAT_AU_IDX) {
+ editEndianess->setCurrentItem(ENDIAN_BIG_IDX);
+ } else {
+ editEndianess->setCurrentItem(ENDIAN_LITTLE_IDX);
+ }
+ break;
+ }
+}
+
+
+
+bool RecordingConfiguration::noticeEncoderBufferChanged (size_t BufferSize, size_t BufferCount)
+{
+ m_ignore_gui_updates = true;
+ m_RecordingConfig.m_EncodeBufferSize = BufferSize;
+ m_RecordingConfig.m_EncodeBufferCount = BufferCount;
+ setGUIBuffers(m_RecordingConfig);
+ slotFormatSelectionChanged();
+ m_ignore_gui_updates = false;
+ return true;
+}
+
+
+bool RecordingConfiguration::noticeSoundFormatChanged (const SoundFormat &sf)
+{
+ m_ignore_gui_updates = true;
+ m_RecordingConfig.m_SoundFormat = sf;
+ setGUISoundFormat(m_RecordingConfig);
+ slotFormatSelectionChanged();
+ m_ignore_gui_updates = false;
+ return true;
+}
+
+
+bool RecordingConfiguration::noticeMP3QualityChanged (int q)
+{
+ m_ignore_gui_updates = true;
+ m_RecordingConfig.m_mp3Quality = q;
+ setGUIEncoderQuality(m_RecordingConfig);
+ slotFormatSelectionChanged();
+ m_ignore_gui_updates = false;
+ return true;
+}
+
+bool RecordingConfiguration::noticeOggQualityChanged (float q)
+{
+ m_ignore_gui_updates = true;
+ m_RecordingConfig.m_oggQuality = q;
+ setGUIEncoderQuality(m_RecordingConfig);
+ slotFormatSelectionChanged();
+ m_ignore_gui_updates = false;
+ return true;
+}
+
+bool RecordingConfiguration::noticeRecordingDirectoryChanged(const TQString &dir)
+{
+ m_ignore_gui_updates = true;
+ m_RecordingConfig.m_Directory = dir;
+ setGUIDirectories(m_RecordingConfig);
+ slotFormatSelectionChanged();
+ m_ignore_gui_updates = false;
+ return true;
+}
+
+bool RecordingConfiguration::noticeOutputFormatChanged (RecordingConfig::OutputFormat of)
+{
+ m_ignore_gui_updates = true;
+ m_RecordingConfig.m_OutputFormat = of;
+ setGUIOutputFormat(m_RecordingConfig);
+ slotFormatSelectionChanged();
+ m_ignore_gui_updates = false;
+ return true;
+}
+
+bool RecordingConfiguration::noticePreRecordingChanged (bool enable, int seconds)
+{
+ m_ignore_gui_updates = true;
+ m_RecordingConfig.m_PreRecordingEnable = enable;
+ m_RecordingConfig.m_PreRecordingSeconds = seconds;
+ setGUIPreRecording(m_RecordingConfig);
+ m_ignore_gui_updates = false;
+ return true;
+}
+
+bool RecordingConfiguration::noticeRecordingConfigChanged(const RecordingConfig &c)
+{
+ m_ignore_gui_updates = true;
+ m_RecordingConfig = c;
+ setGUIBuffers(c);
+ setGUIDirectories(c);
+ setGUISoundFormat(c);
+ setGUIOutputFormat(c);
+ setGUIEncoderQuality(c);
+ setGUIPreRecording(c);
+ slotFormatSelectionChanged();
+ m_ignore_gui_updates = false;
+ return true;
+}
+
+void RecordingConfiguration::slotSetDirty()
+{
+ if (!m_ignore_gui_updates) {
+ m_dirty = true;
+ }
+}
+
+
+#include "recording-configuration.moc"
diff --git a/plugins/recording/recording-configuration.h b/plugins/recording/recording-configuration.h
new file mode 100644
index 0000000..90c2144
--- /dev/null
+++ b/plugins/recording/recording-configuration.h
@@ -0,0 +1,127 @@
+/***************************************************************************
+ recording-configuration.h - description
+ -------------------
+ begin : So Aug 31 2003
+ copyright : (C) 2003 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_RECORDING_CONFIGURATION_H
+#define KRADIO_RECORDING_CONFIGURATION_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/soundformat.h"
+
+#include "recording-config.h"
+#include "reccfg_interfaces.h"
+#include "recording-configuration-ui.h"
+
+#define RATE_48000_IDX 0
+#define RATE_44100_IDX 1
+#define RATE_22050_IDX 2
+#define RATE_11025_IDX 3
+
+#define CHANNELS_STEREO_IDX 0
+#define CHANNELS_MONO_IDX 1
+
+#define SIGN_SIGNED_IDX 0
+#define SIGN_UNSIGNED_IDX 1
+
+#define BITS_16_IDX 0
+#define BITS_8_IDX 1
+
+#define ENDIAN_LITTLE_IDX 0
+#define ENDIAN_BIG_IDX 1
+
+#define FORMAT_RAW_IDX 0
+#define FORMAT_WAV_IDX 1
+#define FORMAT_AIFF_IDX 2
+#define FORMAT_AU_IDX 3
+#define NEXT_IDX1 4
+
+#define FORMAT_MP3_IDX_ORG 4
+#define FORMAT_OGG_IDX_ORG 5
+
+
+#ifdef HAVE_LAME
+ #define FORMAT_MP3_IDX NEXT_IDX1
+ #define NEXT_IDX2 (NEXT_IDX1+1)
+#else
+ #define FORMAT_MP3_IDX (-1)
+ #define NEXT_IDX2 NEXT_IDX1
+#endif
+
+#ifdef HAVE_OGG
+ #define FORMAT_OGG_IDX NEXT_IDX2
+ #define NEXT_IDX3 (NEXT_IDX2+1)
+#else
+ #define FORMAT_OGG_IDX (-1)
+ #define NEXT_IDX3 NEXT_IDX2
+#endif
+
+
+
+
+
+
+class RecordingConfiguration : public RecordingConfigurationUI,
+ public IRecCfgClient
+{
+Q_OBJECT
+
+public :
+ RecordingConfiguration (TQWidget *parent);
+ ~RecordingConfiguration ();
+
+// IRecCfgClient
+
+ bool noticeEncoderBufferChanged (size_t BufferSize, size_t BufferCount);
+ bool noticeSoundFormatChanged (const SoundFormat &sf);
+ bool noticeMP3QualityChanged (int q);
+ bool noticeOggQualityChanged (float q);
+ bool noticeRecordingDirectoryChanged(const TQString &dir);
+ bool noticeOutputFormatChanged (RecordingConfig::OutputFormat of);
+ bool noticePreRecordingChanged (bool enable, int seconds);
+ bool noticeRecordingConfigChanged (const RecordingConfig &cfg);
+
+protected slots:
+
+ void slotOK();
+ void slotCancel();
+ void slotSetDirty();
+
+ void slotFormatSelectionChanged();
+
+protected:
+
+ void storeConfig();
+
+ void setGUIBuffers(const RecordingConfig &c);
+ void setGUIDirectories(const RecordingConfig &c);
+ void setGUISoundFormat(const RecordingConfig &c);
+ void setGUIOutputFormat(const RecordingConfig &c);
+ void setGUIPreRecording(const RecordingConfig &c);
+ void setGUIEncoderQuality(const RecordingConfig &c);
+
+ RecordingConfig m_RecordingConfig;
+
+ bool m_dirty;
+ bool m_ignore_gui_updates;
+};
+
+
+
+
+#endif
diff --git a/plugins/recording/recording-datamonitor.cpp b/plugins/recording/recording-datamonitor.cpp
new file mode 100644
index 0000000..cd8b7e1
--- /dev/null
+++ b/plugins/recording/recording-datamonitor.cpp
@@ -0,0 +1,278 @@
+/***************************************************************************
+ recording-monitor-widget.cpp - description
+ -------------------
+ begin : So Sep 7 2003
+ copyright : (C) 2003 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 "recording-datamonitor.h"
+//#include "recording-context.h"
+#include <math.h>
+
+#include <tqpainter.h>
+#include <tqimage.h>
+#include <tqpixmap.h>
+#include <kimageeffect.h> // fading, blending, ...
+#include <kpixmapio.h> // fast conversion between TQPixmap/TQImage
+#include <limits.h>
+#include <stdlib.h>
+
+#include <tdelocale.h>
+
+#define CHANNEL_H_MIN 20
+#define BLOCK_W_MIN 10
+#define W_MIN (20 * (BLOCK_W_MIN))
+
+RecordingDataMonitor::RecordingDataMonitor(TQWidget *parent, const char *name)
+ : TQFrame(parent, name),
+ m_channelsMax(NULL),
+ m_channelsAvg(NULL),
+ m_maxValue(INT_MAX),
+ m_channels(0),
+ m_pActiveBlocks(NULL)
+{
+ setFrameStyle(Box | Sunken);
+ setLineWidth(1);
+ setMidLineWidth(1);
+
+ setChannels(2);
+
+ setColors(TQColor(20, 244, 20),
+ TQColor(10, 117, 10));
+
+ setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding));
+}
+
+
+RecordingDataMonitor::~RecordingDataMonitor()
+{
+ if (m_channelsMax) delete[] m_channelsMax;
+ if (m_channelsAvg) delete[] m_channelsAvg;
+ if (m_pActiveBlocks) delete[] m_pActiveBlocks;
+}
+
+
+
+// own stuff
+
+void RecordingDataMonitor::setChannels(int n)
+{
+ if (n != m_channels) {
+ if (m_channelsMax) delete[] m_channelsMax;
+ if (m_channelsAvg) delete[] m_channelsAvg;
+ if (m_pActiveBlocks) delete[] m_pActiveBlocks;
+ m_channels = n > 0 ? n : 0;
+ if (m_channels > 0) {
+ m_channelsMax = new int[m_channels];
+ m_channelsAvg = new double[m_channels];
+ m_pActiveBlocks = new int[m_channels];
+ for (int i = 0; i < m_channels; ++i) {
+ m_pActiveBlocks[i] = 0;
+ }
+ } else {
+ m_channelsMax = NULL;
+ m_channelsAvg = NULL;
+ m_pActiveBlocks = NULL;
+ }
+ }
+
+ for (int i = 0; i < m_channels; ++i) {
+ m_channelsMax[i] = 0;
+ m_channelsAvg[i] = 0;
+ }
+ setMinimumSize(TQSize(W_MIN, (m_channels + 1 )* CHANNEL_H_MIN));
+}
+
+
+// QT/KDE ...
+
+void RecordingDataMonitor::drawContents(TQPainter *painter)
+{
+ if (painter)
+ internalDrawContents(*painter, true);
+}
+
+void RecordingDataMonitor::internalDrawContents(TQPainter &painter, bool repaintAll)
+{
+ if (m_channels <= 0) return;
+ TQRect r = contentsRect();
+
+ TQPen activePen (colorGroup().color(TQColorGroup::Text), 1);
+ TQPen inactivePen (colorGroup().color(TQColorGroup::Mid), 1);
+ TQBrush activeBrush = colorGroup().brush(TQColorGroup::Text);
+ TQBrush inactiveBrush = colorGroup().brush(TQColorGroup::Mid);
+ TQBrush yellowBrush(TQColor(255,255,0));
+ TQBrush orangeBrush(TQColor(255,192,0));
+ TQBrush redBrush (TQColor(255,0, 0));
+
+
+ double ranges [5] = { 0.75, 0.83, 0.91, 1.0, 999 };
+ TQBrush *brushes[5] = { &activeBrush, &yellowBrush, &orangeBrush, &redBrush, &redBrush };
+
+ painter.setBrush( isEnabled() ? activeBrush : inactiveBrush);
+
+ int nBlocks = (r.width()-1) / BLOCK_W_MIN;
+ int xoffs = (r.width()-1) % BLOCK_W_MIN;
+ int chHeight = (r.height()-1-CHANNEL_H_MIN) / m_channels;
+ int yoffs = (r.height()-1) % m_channels;
+
+ double min_dB = 20*log10(1 / (double)m_maxValue );
+
+ int x0 = xoffs/2 + r.top();
+ int y = yoffs/2 + r.left();
+ for (int c = 0; c < m_channels; ++c) {
+ int x = x0;
+
+
+ int startBlock = 0;
+ int endBlock = nBlocks - 1;
+ int oldActiveBlocks = m_pActiveBlocks[c];
+
+ double dBMax = isEnabled() ? 20*log10(m_channelsMax[c] / (double)m_maxValue ) : min_dB;
+
+ m_pActiveBlocks[c] = m_channelsMax[c] ? (int)rint(nBlocks * (min_dB - dBMax) / min_dB) : 0;
+
+ if (!repaintAll) {
+ if (oldActiveBlocks > m_pActiveBlocks[c]) {
+ startBlock = m_pActiveBlocks[c];
+ endBlock = oldActiveBlocks - 1;
+ } else {
+ startBlock = oldActiveBlocks;
+ endBlock = m_pActiveBlocks[c]-1;
+ }
+ }
+
+ int range = 0;
+
+ x += BLOCK_W_MIN * startBlock;
+ for (int b = startBlock; b <= endBlock; ++b) {
+ while (b >= nBlocks * ranges[range]) ++range;
+ painter.fillRect(x+1, y+1, BLOCK_W_MIN-1, chHeight-1,
+ b < m_pActiveBlocks[c] ? *brushes[range] : inactiveBrush);
+ x += BLOCK_W_MIN;
+ }
+
+ y += chHeight;
+ }
+
+ if (repaintAll) {
+ TQFont f("Helvetica");
+ painter.setPen (activePen);
+ f.setPixelSize(CHANNEL_H_MIN);
+ painter.setFont(f);
+
+ int maxW = TQFontMetrics(f).width(i18n("%1 dB").arg((int)min_dB));
+ int delta_dB = 5;
+ while (abs((long)min_dB) / delta_dB * maxW * 2 > r.width()) delta_dB *= 2;
+
+ for (int dB = 0; dB >= min_dB; dB -= delta_dB) {
+ TQString txt = i18n("%1 dB").arg(dB);
+ int w = TQFontMetrics(f).width(txt);
+ int x = x0 + (int)(nBlocks * BLOCK_W_MIN * (min_dB - dB) / min_dB) - w;
+ if (x < x0) continue;
+ painter.drawText(x, y + CHANNEL_H_MIN, txt);
+ }
+ }
+}
+
+
+bool RecordingDataMonitor::setColors(const TQColor &activeText,
+ const TQColor &button)
+{
+ m_colorActiveText = activeText;
+ m_colorButton = button;
+
+ TQPalette pl = palette();
+ TQColorGroup cg = pl.inactive();
+
+ TQBrush fg = cg.brush(TQColorGroup::Foreground),
+ btn = cg.brush(TQColorGroup::Button),
+ lgt = cg.brush(TQColorGroup::Light),
+ drk = cg.brush(TQColorGroup::Dark),
+ mid = cg.brush(TQColorGroup::Mid),
+ txt = cg.brush(TQColorGroup::Text),
+ btx = cg.brush(TQColorGroup::BrightText),
+ bas = cg.brush(TQColorGroup::Base),
+ bg = cg.brush(TQColorGroup::Background);
+
+ fg.setColor (m_colorActiveText);
+ btn.setColor(m_colorButton);
+ lgt.setColor(m_colorButton.light(180));
+ drk.setColor(m_colorButton.light( 50));
+ mid.setColor(m_colorButton.light( 75));
+ txt.setColor(m_colorActiveText);
+ btx.setColor(m_colorActiveText);
+ bas.setColor(m_colorButton);
+ bg.setColor (m_colorButton);
+
+ TQColorGroup ncg(fg, btn, lgt, drk, mid, txt, btx, bas, bg);
+ pl.setInactive(ncg);
+ pl.setActive(ncg);
+ setPalette(pl);
+
+ if (parentWidget() && parentWidget()->backgroundPixmap() ){
+ KPixmapIO io;
+ TQImage i = io.convertToImage(*parentWidget()->backgroundPixmap());
+ KImageEffect::fade(i, 0.5, colorGroup().color(TQColorGroup::Dark));
+ setPaletteBackgroundPixmap(io.convertToPixmap(i));
+ setBackgroundOrigin(WindowOrigin);
+ } else {
+ setBackgroundColor(colorGroup().color(TQColorGroup::Button));
+ }
+
+ return true;
+}
+
+
+bool RecordingDataMonitor::noticeSoundStreamData(SoundStreamID /*id*/,
+ const SoundFormat &sf, const char *data, size_t size, size_t &/*consumed_size*/,
+ const SoundMetaData &/*md*/
+)
+{
+ if (!isEnabled())
+ return false;
+ int nSamples = size / sf.frameSize();
+ int sample_size = sf.sampleSize();
+
+ int bias = 0;
+ setChannels(sf.m_Channels);
+ int old_max = m_maxValue;
+ m_maxValue = sf.maxValue();
+ if (!sf.m_IsSigned) {
+ m_maxValue /= 2;
+ bias = -m_maxValue;
+ }
+
+ int c = 0;
+ for (int s = 0; s < nSamples; ++s, ++c, data += sample_size) {
+ if (c >= m_channels) c -= m_channels; // avoid slow c = s % m_channels
+
+ int &m = m_channelsMax[c];
+ int x = abs(sf.convertSampleToInt(data, false) + bias);
+ if (m < x) m = x;
+ m_channelsAvg[c] += x;
+ }
+ for (int i = 0; i < m_channels; ++i)
+ m_channelsAvg[i] /= nSamples;
+
+ TQPainter paint(this);
+ if (m_maxValue != old_max) {
+ repaint(true);
+ } else {
+ internalDrawContents(paint, false);
+ }
+ return true;
+}
+
+
+#include "recording-datamonitor.moc"
diff --git a/plugins/recording/recording-datamonitor.h b/plugins/recording/recording-datamonitor.h
new file mode 100644
index 0000000..2ac493e
--- /dev/null
+++ b/plugins/recording/recording-datamonitor.h
@@ -0,0 +1,67 @@
+/***************************************************************************
+ recording-monitor-widget.h - description
+ -------------------
+ begin : So Sep 7 2003
+ copyright : (C) 2003 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_RECORDING_DATA_MONITOR
+#define KRADIO_RECORDING_DATA_MONITOR
+
+#include <tqframe.h>
+#include <tqcolor.h>
+
+//#include <tderadio/interfaces/recording-interfaces.h>
+#include "../../src/include/soundstreamclient_interfaces.h"
+
+class RecordingDataMonitor : public TQFrame//,
+ //public ISoundStreamClient
+ //public IRecordingClient
+{
+Q_OBJECT
+
+public:
+ RecordingDataMonitor(TQWidget *parent, const char *name);
+ ~RecordingDataMonitor();
+
+ bool noticeSoundStreamData(SoundStreamID id,
+ const SoundFormat &sf, const char *data, size_t size, size_t &consumed_size,
+ const SoundMetaData &md);
+
+// QT/KDE ...
+
+protected:
+
+ void drawContents(TQPainter *p);
+ void internalDrawContents(TQPainter &painter, bool repaintAll);
+// own stuff ...
+
+protected:
+
+ void setChannels(int n);
+ bool setColors(const TQColor &activeColor, const TQColor &bkgnd);
+
+// data
+protected:
+
+ int *m_channelsMax; // maximum absolute value recorded on each channel
+ double *m_channelsAvg; // average value recorded on each channel
+ int m_maxValue; // maximum absolute value possible for samples
+ int m_channels;
+
+ TQColor m_colorActiveText, m_colorButton;
+
+ int *m_pActiveBlocks;
+};
+
+#endif
diff --git a/plugins/recording/recording-monitor.cpp b/plugins/recording/recording-monitor.cpp
new file mode 100644
index 0000000..ee1514b
--- /dev/null
+++ b/plugins/recording/recording-monitor.cpp
@@ -0,0 +1,402 @@
+/***************************************************************************
+ recording-monitor.cpp - description
+ -------------------
+ begin : Mo Sep 1 2003
+ copyright : (C) 2003 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 "recording-monitor.h"
+#include "recording-datamonitor.h"
+#include "../../src/include/aboutwidget.h"
+
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqlayout.h>
+#include <tqcheckbox.h>
+#include <kcombobox.h>
+
+#include <tdelocale.h>
+#include <tdeconfig.h>
+#include <tdeaboutdata.h>
+
+RecordingMonitor::RecordingMonitor(const TQString &name)
+ : TQWidget(NULL, name.ascii()),
+ WidgetPluginBase(name, i18n("Recording Monitor")),
+ m_recording(false),
+ m_defaultStreamDescription(TQString())
+{
+ setCaption(i18n("TDERadio Recording Monitor"));
+
+ TQVBoxLayout *l = new TQVBoxLayout(this, 10, 4);
+ TQGridLayout *l0 = new TQGridLayout(l, 6, 2);
+
+ l0->addWidget( new TQLabel(i18n("SoundStream"), this), 0, 0);
+ l0->addWidget(m_comboSoundStreamSelector = new KComboBox( this), 0, 1);
+ l0->addWidget( new TQLabel(i18n("Status"), this), 1, 0);
+ l0->addWidget(m_labelStatus = new TQLabel(i18n("<undefined>"), this), 1, 1);
+ l0->addWidget( new TQLabel(i18n("Recording File"), this), 2, 0);
+ l0->addWidget(m_labelFileName = new TQLabel(i18n("<undefined>"), this), 2, 1);
+ l0->addWidget( new TQLabel(i18n("File Size"), this), 3, 0);
+ l0->addWidget(m_labelSize = new TQLabel(i18n("<undefined>"), this), 3, 1);
+ l0->addWidget( new TQLabel(i18n("Recording Time"), this), 4, 0);
+ l0->addWidget(m_labelTime = new TQLabel(i18n("<undefined>"), this), 4, 1);
+ l0->addWidget( new TQLabel(i18n("Sample Rate"), this), 5, 0);
+ l0->addWidget(m_labelRate = new TQLabel(i18n("<undefined>"), this), 5, 1);
+
+ TQPushButton *close = new TQPushButton(i18n("&Close"), this);
+ m_btnStartStop = new TQPushButton(i18n("&Record"), this);
+ TQObject::connect(close, TQT_SIGNAL(clicked()), this, TQT_SLOT(hide()));
+ TQObject::connect(m_btnStartStop, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotStartStopRecording()));
+
+ m_dataMonitor = new RecordingDataMonitor(this, NULL);
+ m_dataMonitor->setEnabled(false);
+
+ TQHBoxLayout *hl0 = new TQHBoxLayout(l);
+ hl0->addWidget(m_dataMonitor);
+
+ TQHBoxLayout *hl2 = new TQHBoxLayout(l);
+ hl2->addItem(new TQSpacerItem(10, 1));
+ hl2->addWidget(close);
+ hl2->addWidget(m_btnStartStop);
+ hl2->addItem(new TQSpacerItem(10, 1));
+
+
+ m_comboSoundStreamSelector->insertItem(i18n("nothing"));
+ TQObject::connect(m_comboSoundStreamSelector, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotStreamSelected(int)));
+
+ updateRecordingButton();
+}
+
+
+RecordingMonitor::~RecordingMonitor()
+{
+}
+
+// WidgetPluginBase
+
+void RecordingMonitor::saveState (TDEConfig *config) const
+{
+ config->setGroup(TQString("recordingmonitor-") + name());
+
+ WidgetPluginBase::saveState(config);
+}
+
+
+void RecordingMonitor::restoreState (TDEConfig *config)
+{
+ config->setGroup(TQString("recordingmonitor-") + name());
+
+ WidgetPluginBase::restoreState(config, false);
+}
+
+
+bool RecordingMonitor::connectI(Interface *i)
+{
+ bool a = ISoundStreamClient::connectI(i);
+ bool b = WidgetPluginBase::connectI(i);
+ return a || b;
+}
+
+bool RecordingMonitor::disconnectI(Interface *i)
+{
+ bool a = ISoundStreamClient::disconnectI(i);
+ bool b = WidgetPluginBase::disconnectI(i);
+ if (a) {
+ m_comboSoundStreamSelector->clear();
+ m_SoundStreamID2idx.clear();
+ m_idx2SoundStreamID.clear();
+ m_comboSoundStreamSelector->insertItem(i18n("nothing"));
+ }
+ return a || b;
+}
+
+
+void RecordingMonitor::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid)
+{
+ ISoundStreamClient::noticeConnectedI(s, pointer_valid);
+ if (s && pointer_valid) {
+ s->register4_notifySoundStreamCreated(this);
+ s->register4_notifySoundStreamClosed(this);
+ s->register4_notifySoundStreamChanged(this);
+ s->register4_notifySoundStreamData(this);
+ s->register4_sendStartRecordingWithFormat(this);
+ s->register4_sendStopRecording(this);
+
+ TQMap<TQString, SoundStreamID> tmp;
+ queryEnumerateSoundStreams(tmp);
+
+ m_comboSoundStreamSelector->clear();
+ m_SoundStreamID2idx.clear();
+ m_idx2SoundStreamID.clear();
+ m_comboSoundStreamSelector->insertItem(i18n("nothing"));
+ TQMapConstIterator<TQString, SoundStreamID> end = tmp.end();
+ for (TQMapConstIterator<TQString, SoundStreamID> it = tmp.begin(); it != end; ++it) {
+ int idx = m_comboSoundStreamSelector->count();
+ m_comboSoundStreamSelector->insertItem(it.key());
+ m_idx2SoundStreamID[idx] = *it;
+ m_SoundStreamID2idx[*it] = idx;
+ }
+ }
+}
+
+ConfigPageInfo RecordingMonitor::createConfigurationPage()
+{
+ return ConfigPageInfo();
+}
+
+AboutPageInfo RecordingMonitor::createAboutPage()
+{
+/* TDEAboutData aboutData("tderadio",
+ NULL,
+ NULL,
+ I18N_NOOP("Recording Monitor Plugin for TDERadio"),
+ TDEAboutData::License_GPL,
+ "(c) 2002-2005 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("Recording Monitor"),
+ i18n("Recording Monitor Plugin"),
+ "goto"
+ );
+*/
+ return AboutPageInfo();
+}
+
+
+void RecordingMonitor::show()
+{
+ WidgetPluginBase::pShow();
+ TQWidget::show();
+}
+
+
+void RecordingMonitor::showOnOrgDesktop()
+{
+ WidgetPluginBase::pShowOnOrgDesktop();
+ //TQWidget::show();
+}
+
+void RecordingMonitor::hide()
+{
+ WidgetPluginBase::pHide();
+ TQWidget::hide();
+}
+
+
+void RecordingMonitor::showEvent(TQShowEvent *e)
+{
+ TQWidget::showEvent(e);
+ WidgetPluginBase::pShowEvent(e);
+ //m_comboSoundStreamSelector->setCurrentItem(1);
+ //slotStreamSelected(1);
+}
+
+
+void RecordingMonitor::hideEvent(TQHideEvent *e)
+{
+ TQWidget::hideEvent(e);
+ WidgetPluginBase::pHideEvent(e);
+ m_comboSoundStreamSelector->setCurrentItem(0);
+ slotStreamSelected(0);
+}
+
+
+void RecordingMonitor::slotStartStopRecording()
+{
+ if (m_currentStream.isValid()) {
+ if (m_recording) {
+ sendStopRecording(m_currentStream);
+ } else {
+ sendStartRecording(m_currentStream);
+ }
+ }
+ updateRecordingButton();
+}
+
+
+bool RecordingMonitor::noticeSoundStreamCreated(SoundStreamID id)
+{
+ TQString tmp = TQString();
+ querySoundStreamDescription(id, tmp);
+
+ int idx = m_comboSoundStreamSelector->count();
+ m_comboSoundStreamSelector->insertItem(tmp);
+ m_idx2SoundStreamID[idx] = id;
+ m_SoundStreamID2idx[id] = idx;
+
+ if (tmp == m_defaultStreamDescription) {
+ m_comboSoundStreamSelector->setCurrentItem(idx);
+ slotStreamSelected(idx);
+ }
+ return true;
+}
+
+
+bool RecordingMonitor::noticeSoundStreamClosed(SoundStreamID id)
+{
+ if (m_SoundStreamID2idx.contains(id)) {
+ int idx = m_SoundStreamID2idx[id];
+ m_idx2SoundStreamID.clear();
+ m_SoundStreamID2idx.remove(id);
+ TQMapIterator<SoundStreamID, int> end = m_SoundStreamID2idx.end();
+ for (TQMapIterator<SoundStreamID, int> it = m_SoundStreamID2idx.begin(); it != end; ++it) {
+ if (*it > idx) {
+ (*it)--;
+ }
+ m_idx2SoundStreamID[*it] = it.key();
+ }
+ m_comboSoundStreamSelector->removeItem(idx);
+ slotStreamSelected(m_comboSoundStreamSelector->currentItem());
+ return true;
+ }
+ return false;
+}
+
+
+bool RecordingMonitor::noticeSoundStreamChanged(SoundStreamID id)
+{
+ if (m_SoundStreamID2idx.contains(id)) {
+ int idx = m_SoundStreamID2idx[id];
+ TQString tmp = TQString();
+ querySoundStreamDescription(id, tmp);
+ m_comboSoundStreamSelector->changeItem(tmp, idx);
+ if (idx == m_comboSoundStreamSelector->currentItem()) {
+ m_defaultStreamDescription = tmp;
+ }
+ return true;
+ }
+ return false;
+}
+
+bool RecordingMonitor::startRecordingWithFormat(SoundStreamID id, const SoundFormat &/*sf*/, SoundFormat &/*real_format*/)
+{
+ if (id == m_currentStream) {
+ m_recording = true;
+ updateRecordingButton();
+ }
+ return false;
+}
+
+bool RecordingMonitor::stopRecording(SoundStreamID id)
+{
+ if (id == m_currentStream) {
+ m_recording = false;
+ updateRecordingButton();
+ }
+ return false;
+}
+
+bool RecordingMonitor::noticeSoundStreamData(SoundStreamID id,
+ const SoundFormat &sf, const char *data, size_t size, size_t &consumed_size,
+ const SoundMetaData &md
+)
+{
+ if (m_idx2SoundStreamID[m_comboSoundStreamSelector->currentItem()] == id) {
+
+ m_labelFileName->setText(md.url().url());
+
+ double B = (double)md.position() + (double)size;
+
+ double s = md.relativeTimestamp();
+
+ int m = (int)(s / 60); s -= 60 * m;
+ int h = m / 60; m %= 60;
+ int d = h / 24; h %= 24;
+ TQString time;
+ if (d) {
+ time.sprintf("%dd - %02d:%02d:%05.2f", d, h, m, s);
+ } else {
+ time.sprintf("%02d:%02d:%05.2f", h, m, s);
+ }
+ m_labelTime->setText(time);
+
+ if (sf.m_Encoding == "raw") {
+ m_dataMonitor->setEnabled(true);
+ m_dataMonitor->noticeSoundStreamData(id, sf, data, size, consumed_size, md);
+ } else {
+ m_dataMonitor->setEnabled(false);
+ }
+
+ double kB = B / 1024;
+ double MB = kB / 1024;
+ double GB = MB / 1024;
+ TQString str_size;
+ str_size = i18n("%1 Byte").arg(TDEGlobal::locale()->formatNumber((int)B, 0));
+ if (kB > 1) str_size = i18n("%1 kB").arg(TDEGlobal::locale()->formatNumber(kB, 3));
+ if (MB > 1) str_size = i18n("%1 MB").arg(TDEGlobal::locale()->formatNumber(MB, 3));
+ if (GB > 1) str_size = i18n("%1 GB").arg(TDEGlobal::locale()->formatNumber(GB, 3));
+ m_labelSize->setText(str_size);
+
+ m_labelRate->setText(i18n("%1 Hz").arg(sf.m_SampleRate));
+ return true;
+ }
+ return false;
+}
+
+
+void RecordingMonitor::slotStreamSelected(int idx)
+{
+ SoundStreamID old_id = m_currentStream;
+ if (old_id.isValid()) {
+ sendStopCapture(old_id);
+ }
+
+ SoundStreamID id = m_idx2SoundStreamID.contains(idx) ? m_idx2SoundStreamID[idx] : SoundStreamID::InvalidID;
+ if (id.isValid()) {
+
+ m_defaultStreamDescription = m_comboSoundStreamSelector->text(idx);
+
+ SoundFormat sf;
+ sendStartCaptureWithFormat(id, sf, sf);
+ m_dataMonitor ->setEnabled(true);
+ m_labelSize ->setEnabled(true);
+ m_labelSize ->setEnabled(true);
+ m_labelTime ->setEnabled(true);
+ m_labelRate ->setEnabled(true);
+ m_labelFileName ->setEnabled(true);
+ m_labelStatus ->setEnabled(true);
+ } else {
+ m_dataMonitor ->setEnabled(false);
+ m_labelSize ->setEnabled(false);
+ m_labelSize ->setEnabled(false);
+ m_labelTime ->setEnabled(false);
+ m_labelRate ->setEnabled(false);
+ m_labelFileName ->setEnabled(false);
+ m_labelStatus ->setEnabled(false);
+ }
+ m_currentStream = id;
+ m_recording = false;
+ SoundFormat sf;
+ queryIsRecordingRunning(m_currentStream, m_recording, sf);
+ updateRecordingButton();
+}
+
+
+void RecordingMonitor::updateRecordingButton()
+{
+ if (m_currentStream.isValid()) {
+ m_btnStartStop->setText(!m_recording ? i18n("&Record") : i18n("&Stop Recording"));
+ m_btnStartStop->setEnabled(true);
+ } else {
+ m_btnStartStop->setText(i18n("&Record"));
+ m_btnStartStop->setEnabled(false);
+ }
+}
+
+
+#include "recording-monitor.moc"
diff --git a/plugins/recording/recording-monitor.h b/plugins/recording/recording-monitor.h
new file mode 100644
index 0000000..b2a8890
--- /dev/null
+++ b/plugins/recording/recording-monitor.h
@@ -0,0 +1,125 @@
+/***************************************************************************
+ recording-monitor.h - description
+ -------------------
+ begin : Mo Sep 1 2003
+ copyright : (C) 2003 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_RECORDING_MONITOR_H
+#define KRADIO_RECORDING_MONITOR_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tqwidget.h>
+
+#include "../../src/include/widgetplugins.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+//#include <tderadio/interfaces/recording-interfaces.h>
+
+
+class TQLabel;
+class TQPushButton;
+class TQCheckBox;
+class RecordingDataMonitor;
+class KComboBox;
+
+class RecordingMonitor : public TQWidget,
+ public WidgetPluginBase,
+ public ISoundStreamClient
+ //public IRecordingClient
+{
+Q_OBJECT
+
+public:
+
+ RecordingMonitor(const TQString &name);
+ virtual ~RecordingMonitor();
+
+ const TQString &name() const { return PluginBase::name(); }
+ TQString &name() { return PluginBase::name(); }
+
+ virtual TQString pluginClassName() const { return "RecordingMonitor"; }
+
+ // WidgetPluginBase
+
+public:
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+ virtual bool connectI(Interface *i);
+ virtual bool disconnectI(Interface *i);
+
+ virtual ConfigPageInfo createConfigurationPage();
+ virtual AboutPageInfo createAboutPage();
+
+ // IRecordingClient
+
+ void noticeConnectedI (ISoundStreamServer *s, bool pointer_valid);
+
+ bool noticeSoundStreamCreated(SoundStreamID id);
+ bool noticeSoundStreamClosed(SoundStreamID id);
+ bool noticeSoundStreamChanged(SoundStreamID id);
+
+ bool startRecordingWithFormat(SoundStreamID id, const SoundFormat &sf, SoundFormat &real_format);
+ bool stopRecording(SoundStreamID id);
+
+ bool noticeSoundStreamData(SoundStreamID id, const SoundFormat &sf, const char *data, size_t size, size_t &consumed_size, const SoundMetaData &md);
+
+public slots:
+
+ void toggleShown() { WidgetPluginBase::pToggleShown(); }
+ void showOnOrgDesktop();
+ void show();
+ void hide();
+
+ void slotStartStopRecording();
+
+ void slotStreamSelected(int idx);
+
+protected:
+
+ virtual void updateRecordingButton();
+
+ virtual void showEvent(TQShowEvent *);
+ virtual void hideEvent(TQHideEvent *);
+
+ const TQWidget *getWidget() const { return this; }
+ TQWidget *getWidget() { return this; }
+
+
+protected:
+
+ TQLabel *m_labelSize;
+ TQLabel *m_labelTime;
+ TQLabel *m_labelRate;
+ TQLabel *m_labelFileName;
+ TQLabel *m_labelStatus;
+ TQPushButton *m_btnStartStop;
+
+ KComboBox *m_comboSoundStreamSelector;
+ TQMap<SoundStreamID, int> m_SoundStreamID2idx;
+ TQMap<int, SoundStreamID> m_idx2SoundStreamID;
+
+ SoundStreamID m_currentStream;
+ RecordingDataMonitor *m_dataMonitor;
+
+ bool m_recording;
+ TQString m_defaultStreamDescription;
+};
+
+
+
+
+#endif
diff --git a/plugins/recording/recording.cpp b/plugins/recording/recording.cpp
new file mode 100644
index 0000000..2f1ce05
--- /dev/null
+++ b/plugins/recording/recording.cpp
@@ -0,0 +1,731 @@
+/***************************************************************************
+ recording.cpp - description
+ -------------------
+ begin : Mi Aug 27 2003
+ copyright : (C) 2003 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 "../../src/include/radiostation.h"
+#include "../../src/include/errorlog-interfaces.h"
+#include "../../src/include/aboutwidget.h"
+#include "../../src/include/fileringbuffer.h"
+#include "../../src/include/utils.h"
+
+#include "recording.h"
+#include "recording-configuration.h"
+#include "soundstreamevent.h"
+#include "recording-monitor.h"
+#include "encoder_mp3.h"
+#include "encoder_ogg.h"
+#include "encoder_pcm.h"
+
+#include <tqevent.h>
+#include <tqapplication.h>
+#include <tqregexp.h>
+
+#include <tdeconfig.h>
+#include <tdeversion.h>
+
+#include <tdeaboutdata.h>
+
+
+///////////////////////////////////////////////////////////////////////
+//// plugin library functions
+
+PLUGIN_LIBRARY_FUNCTIONS2(
+ Recording, "tderadio-recording", i18n("TDERadio Recording Plugin"),
+ RecordingMonitor, i18n("TDERadio Recording Monitor")
+);
+
+///////////////////////////////////////////////////////////////////////
+
+Recording::Recording(const TQString &name)
+ : TQObject(NULL, NULL),
+ PluginBase(name, i18n("TDERadio Recording Plugin")),
+ m_config()
+{
+}
+
+
+Recording::~Recording()
+{
+ TQMapIterator<SoundStreamID, RecordingEncoding*> it = m_EncodingThreads.begin();
+ TQMapIterator<SoundStreamID, RecordingEncoding*> end = m_EncodingThreads.end();
+ for (; it != end; ++it) {
+ sendStopRecording(it.key());
+ }
+}
+
+
+bool Recording::connectI(Interface *i)
+{
+ bool a = IRecCfg::connectI(i);
+ bool b = PluginBase::connectI(i);
+ bool c = ISoundStreamClient::connectI(i);
+ return a || b || c;
+}
+
+
+bool Recording::disconnectI(Interface *i)
+{
+ bool a = IRecCfg::disconnectI(i);
+ bool b = PluginBase::disconnectI(i);
+ bool c = ISoundStreamClient::disconnectI(i);
+ return a || b || c;
+}
+
+
+void Recording::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid)
+{
+ ISoundStreamClient::noticeConnectedI(s, pointer_valid);
+ if (s && pointer_valid) {
+ s->register4_sendStartPlayback(this);
+ s->register4_sendStopPlayback(this);
+ s->register4_sendStartRecording(this);
+ s->register4_sendStartRecordingWithFormat(this);
+ s->register4_notifySoundStreamData(this);
+ s->register4_sendStopRecording(this);
+ s->register4_queryIsRecordingRunning(this);
+ s->register4_querySoundStreamDescription(this);
+ s->register4_querySoundStreamRadioStation(this);
+ s->register4_queryEnumerateSoundStreams(this);
+ s->register4_notifySoundStreamChanged(this);
+ s->register4_notifySoundStreamClosed(this);
+ }
+}
+
+// PluginBase
+
+void Recording::saveState (TDEConfig *c) const
+{
+ c->setGroup(TQString("recording-") + PluginBase::name());
+ m_config.saveConfig(c);
+}
+
+
+void Recording::restoreState (TDEConfig *c)
+{
+ c->setGroup(TQString("recording-") + PluginBase::name());
+ RecordingConfig cfg;
+ cfg.restoreConfig(c);
+ setRecordingConfig(cfg);
+ //notifyRecordingConfigChanged(m_config);
+}
+
+
+ConfigPageInfo Recording::createConfigurationPage()
+{
+ RecordingConfiguration *c = new RecordingConfiguration(NULL);
+ connectI(c);
+ return ConfigPageInfo(c,
+ i18n("Recording"),
+ i18n("Recording"),
+ "tderadio_record");
+}
+
+
+AboutPageInfo Recording::createAboutPage()
+{
+/* TDEAboutData aboutData("tderadio",
+ NULL,
+ NULL,
+ I18N_NOOP("Recording Monitor for TDERadio"),
+ TDEAboutData::License_GPL,
+ "(c) 2002-2005 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("Recording"),
+ i18n("Recording Plugin"),
+ "tderadio_record"
+ );*/
+ return AboutPageInfo();
+}
+
+
+// IRecCfg
+
+bool Recording::setEncoderBuffer (size_t BufferSize, size_t BufferCount)
+{
+ if (m_config.m_EncodeBufferSize != BufferSize ||
+ m_config.m_EncodeBufferCount != BufferCount)
+ {
+ m_config.m_EncodeBufferSize = BufferSize;
+ m_config.m_EncodeBufferCount = BufferCount;
+ notifyEncoderBufferChanged(BufferSize, BufferCount);
+ }
+ return true;
+}
+
+bool Recording::setSoundFormat (const SoundFormat &sf)
+{
+ if (m_config.m_SoundFormat != sf) {
+ m_config.m_SoundFormat = sf;
+ notifySoundFormatChanged(sf);
+ }
+ return true;
+}
+
+bool Recording::setMP3Quality (int q)
+{
+ if (m_config.m_mp3Quality != q) {
+ m_config.m_mp3Quality = q;
+ notifyMP3QualityChanged(q);
+ }
+ return true;
+}
+
+bool Recording::setOggQuality (float q)
+{
+ if (m_config.m_oggQuality != q) {
+ m_config.m_oggQuality = q;
+ notifyOggQualityChanged(q);
+ }
+ return true;
+}
+
+bool Recording::setRecordingDirectory(const TQString &dir)
+{
+ if (m_config.m_Directory != dir) {
+ m_config.m_Directory = dir;
+ notifyRecordingDirectoryChanged(dir);
+ }
+ return true;
+}
+
+bool Recording::setOutputFormat (RecordingConfig::OutputFormat of)
+{
+ if (m_config.m_OutputFormat != of) {
+ m_config.m_OutputFormat = of;
+ notifyOutputFormatChanged(of);
+ }
+ return true;
+}
+
+bool Recording::setPreRecording (bool enable, int seconds)
+{
+ if (m_config.m_PreRecordingEnable != enable || m_config.m_PreRecordingSeconds != seconds) {
+ m_config.m_PreRecordingEnable = enable;
+ m_config.m_PreRecordingSeconds = seconds;
+
+ if (enable) {
+ for (TQMapIterator<SoundStreamID,FileRingBuffer*> it = m_PreRecordingBuffers.begin(); it != m_PreRecordingBuffers.end(); ++it) {
+ if (*it != NULL) {
+ delete *it;
+ }
+ *it = new FileRingBuffer(m_config.m_Directory + "/tderadio-prerecord-"+TQString::number(it.key().getID()), m_config.m_PreRecordingSeconds * m_config.m_SoundFormat.m_SampleRate * m_config.m_SoundFormat.frameSize());
+ SoundFormat sf = m_config.m_SoundFormat;
+ sendStartCaptureWithFormat(it.key(), sf, sf, false);
+ }
+ }
+ else {
+ for (TQMapIterator<SoundStreamID,FileRingBuffer*> it = m_PreRecordingBuffers.begin(); it != m_PreRecordingBuffers.end(); ++it) {
+ if (*it != NULL) {
+ sendStopCapture(it.key());
+ delete *it;
+ }
+ }
+ m_PreRecordingBuffers.clear();
+ }
+
+ notifyPreRecordingChanged(enable, seconds);
+ }
+ return true;
+}
+
+void Recording::getEncoderBuffer(size_t &BufferSize, size_t &BufferCount) const
+{
+ BufferSize = m_config.m_EncodeBufferSize;
+ BufferCount = m_config.m_EncodeBufferCount;
+}
+
+const SoundFormat &Recording::getSoundFormat () const
+{
+ return m_config.m_SoundFormat;
+}
+
+int Recording::getMP3Quality () const
+{
+ return m_config.m_mp3Quality;
+}
+
+float Recording::getOggQuality () const
+{
+ return m_config.m_oggQuality;
+}
+
+const TQString &Recording::getRecordingDirectory() const
+{
+ return m_config.m_Directory;
+}
+
+RecordingConfig::OutputFormat Recording::getOutputFormat() const
+{
+ return m_config.m_OutputFormat;
+}
+
+bool Recording::getPreRecording(int &seconds) const
+{
+ seconds = m_config.m_PreRecordingSeconds;
+ return m_config.m_PreRecordingEnable;
+}
+
+const RecordingConfig &Recording::getRecordingConfig() const
+{
+ return m_config;
+}
+
+bool Recording::setRecordingConfig(const RecordingConfig &c)
+{
+ setEncoderBuffer (c.m_EncodeBufferSize, c.m_EncodeBufferCount);
+ setSoundFormat (c.m_SoundFormat);
+ setMP3Quality (c.m_mp3Quality);
+ setOggQuality (c.m_oggQuality);
+ setRecordingDirectory(c.m_Directory);
+ setOutputFormat (c.m_OutputFormat);
+ setPreRecording (c.m_PreRecordingEnable, c.m_PreRecordingSeconds);
+
+ m_config = c;
+
+ notifyRecordingConfigChanged(m_config);
+
+ return true;
+}
+
+
+// ISoundStreamClient
+bool Recording::startPlayback(SoundStreamID id)
+{
+ if (m_PreRecordingBuffers.contains(id))
+ delete m_PreRecordingBuffers[id];
+ m_PreRecordingBuffers[id] = NULL;
+ if (m_config.m_PreRecordingEnable) {
+ m_PreRecordingBuffers[id] = new FileRingBuffer(m_config.m_Directory + "/tderadio-prerecord-"+TQString::number(id.getID()), m_config.m_PreRecordingSeconds * m_config.m_SoundFormat.m_SampleRate * m_config.m_SoundFormat.frameSize());
+ SoundFormat sf = m_config.m_SoundFormat;
+ sendStartCaptureWithFormat(id, sf, sf, false);
+ }
+ return false;
+}
+
+bool Recording::stopPlayback(SoundStreamID id)
+{
+ if (m_PreRecordingBuffers.contains(id)) {
+ if (m_PreRecordingBuffers[id])
+ delete m_PreRecordingBuffers[id];
+ m_PreRecordingBuffers.remove(id);
+ sendStopCapture(id);
+ }
+ return false;
+}
+
+bool Recording::startRecording(SoundStreamID id)
+{
+
+/* FileRingBuffer *test = new FileRingBuffer("/tmp/ringbuffertest", 2048);
+ char buffer1[1024];
+ char buffer2[1024];
+ char buffer3[1024];
+ for (int i = 0; i < 1024; ++i) {
+ buffer1[i] = 'a';
+ buffer2[i] = 'b';
+ buffer3[i] = 'c';
+ }
+ test->addData(buffer1, 1024);
+ test->addData(buffer2, 1024);
+ test->removeData(1024);
+ test->addData(buffer3, 1024);
+*/
+
+ SoundFormat realFormat = m_config.m_SoundFormat;
+ return sendStartRecordingWithFormat(id, realFormat, realFormat);
+}
+
+bool Recording::startRecordingWithFormat(SoundStreamID id, const SoundFormat &sf, SoundFormat &real_format)
+{
+ if (!sendStartCaptureWithFormat(id, sf, real_format, /* force_format = */ true)) {
+ logError(i18n("start capture not handled"));
+ return false;
+ }
+
+ RecordingConfig cfg = m_config;
+ cfg.m_SoundFormat = real_format;
+
+ logInfo(i18n("Recording starting"));
+ if (!startEncoder(id, cfg)) {
+ logError(i18n("starting encoding thread failed"));
+ sendStopCapture(id);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool Recording::stopRecording(SoundStreamID id)
+{
+ if (m_EncodingThreads.contains(id)) {
+ sendStopCapture(id);
+ if (m_config.m_PreRecordingEnable) {
+ if (!m_PreRecordingBuffers.contains(id)) {
+ if (m_PreRecordingBuffers[id] != NULL) {
+ delete m_PreRecordingBuffers[id];
+ }
+ bool b = false;
+ queryIsPlaybackRunning(id, b);
+ if (b) {
+ m_PreRecordingBuffers[id] = new FileRingBuffer(m_config.m_Directory + "/tderadio-prerecord-"+TQString::number(id.getID()), m_config.m_PreRecordingSeconds * m_config.m_SoundFormat.m_SampleRate * m_config.m_SoundFormat.frameSize());
+ } else {
+ m_PreRecordingBuffers[id] = NULL;
+ }
+ }
+ }
+ stopEncoder(id);
+ return true;
+ }
+ return false;
+}
+
+
+
+bool Recording::noticeSoundStreamData(SoundStreamID id,
+ const SoundFormat &/*sf*/, const char *data, size_t size, size_t &consumed_size,
+ const SoundMetaData &md
+)
+{
+ if (m_PreRecordingBuffers.contains(id) && m_PreRecordingBuffers[id] != NULL) {
+
+ FileRingBuffer &fbuf = *m_PreRecordingBuffers[id];
+ if (fbuf.getFreeSize() < size) {
+ fbuf.removeData(size - fbuf.getFreeSize());
+ }
+ size_t n = fbuf.addData(data, size);
+ consumed_size = (consumed_size == SIZE_T_DONT_CARE) ? n : min(consumed_size, n);
+// if (n != size) {
+// logDebug("recording packet: was not written completely to tmp buf");
+// }
+
+// //BEGIN DEBUG
+// char tmp[4096];
+// for (unsigned int i = 0; i < sizeof(tmp); ++i) { tmp[i] = 0; }
+// if (fbuf.getFreeSize() < sizeof(tmp)) {
+// fbuf.removeData(sizeof(tmp) - fbuf.getFreeSize());
+// }
+// fbuf.addData((char*)tmp, sizeof(tmp));
+// //END DEBUG
+
+ if (m_EncodingThreads.contains(id)) {
+
+ //logDebug("recording packet: " + TQString::number(size));
+
+ RecordingEncoding *thread = m_EncodingThreads[id];
+
+ //logDebug("noticeSoundStreamData thread = " + TQString::number((long long)thread, 16));
+
+ size_t remSize = fbuf.getFillSize();
+
+ while (remSize > 0) {
+ size_t bufferSize = remSize;
+ char *buf = thread->lockInputBuffer(bufferSize);
+ if (!buf) {
+ // Encoder buffer is full and bigger than remaining data
+ break;
+ }
+ if (bufferSize > remSize) {
+ bufferSize = remSize;
+ }
+ if (fbuf.takeData(buf, bufferSize) != bufferSize) {
+ logError(i18n("could not read suffient data"));
+ }
+
+ thread->unlockInputBuffer(bufferSize, md);
+ remSize -= bufferSize;
+ }
+
+ if (remSize == 0) {
+ delete m_PreRecordingBuffers[id];
+ m_PreRecordingBuffers.remove(id);
+ }
+ }
+
+ return true;
+ }
+
+ else if (m_EncodingThreads.contains(id)) {
+
+ //logDebug("recording packet: " + TQString::number(size));
+
+ RecordingEncoding *thread = m_EncodingThreads[id];
+
+ //logDebug("noticeSoundStreamData thread = " + TQString::number((long long)thread, 16));
+
+ size_t remSize = size;
+ const char *remData = data;
+
+ while (remSize > 0) {
+ size_t bufferSize = remSize;
+ char *buf = thread->lockInputBuffer(bufferSize);
+ if (!buf) {
+ logWarning(i18n("Encoder input buffer overflow (buffer configuration problem?). Skipped %1 input bytes").arg(TQString::number(remSize)));
+ break;
+ }
+ if (bufferSize > remSize) {
+ bufferSize = remSize;
+ }
+ memcpy(buf, remData, bufferSize);
+
+ thread->unlockInputBuffer(bufferSize, md);
+ remSize -= bufferSize;
+ remData += bufferSize;
+ }
+ consumed_size = (consumed_size == SIZE_T_DONT_CARE) ? size - remSize : min(consumed_size, size - remSize);
+
+ return true;
+ }
+ return false;
+}
+
+
+
+
+bool Recording::startEncoder(SoundStreamID ssid, const RecordingConfig &cfg)
+{
+ if (m_EncodingThreads.contains(ssid))
+ return false;
+
+ SoundStreamID encID = createNewSoundStream(ssid, false);
+ m_RawStreams2EncodedStreams[ssid] = encID;
+ m_EncodedStreams2RawStreams[encID] = ssid;
+
+ TQString ext = ".wav";
+ switch (m_config.m_OutputFormat) {
+ case RecordingConfig::outputWAV: ext = ".wav"; break;
+ case RecordingConfig::outputAIFF: ext = ".aiff"; break;
+ case RecordingConfig::outputAU: ext = ".au"; break;
+#ifdef HAVE_LAME
+ case RecordingConfig::outputMP3: ext = ".mp3"; break;
+#endif
+#ifdef HAVE_LAME
+ case RecordingConfig::outputOGG: ext = ".ogg"; break;
+#endif
+ case RecordingConfig::outputRAW: ext = ".raw"; break;
+ default: ext = ".wav"; break;
+ }
+ const RadioStation *rs = NULL;
+ querySoundStreamRadioStation(ssid, rs);
+ TQString station = rs ? rs->name() + "-" : "";
+ station.replace(TQRegExp("[/*?]"), "_");
+
+ TQDate date = TQDate::currentDate();
+ TQTime time = TQTime::currentTime();
+ TQString sdate;
+
+ sdate.sprintf("%d.%d.%d.%d.%d",date.year(),date.month(),date.day(),time.hour(),time.minute());
+
+ TQString output = m_config.m_Directory
+ + "/tderadio-recording-"
+ + station
+ + sdate
+ + ext;
+
+ logInfo(i18n("Recording::outputFile: ") + output);
+
+ RecordingEncoding *thread = NULL;
+ switch (m_config.m_OutputFormat) {
+#ifdef HAVE_LAME
+ case RecordingConfig::outputMP3:
+ thread = new RecordingEncodingMP3(this, ssid, cfg, rs, output);
+ break;
+#endif
+#ifdef HAVE_OGG
+ case RecordingConfig::outputOGG:
+ thread = new RecordingEncodingOgg(this, ssid, cfg, rs, output);
+ break;
+#endif
+ default:
+ thread = new RecordingEncodingPCM(this, ssid, cfg, rs, output);
+ }
+
+ //m_encodingThread->openOutput(output, rs);
+
+ if (thread->error()) {
+ //m_context.setError();
+ logError(thread->errorString());
+ } else {
+ thread->start();
+ }
+ // store thread even if it has indicated an error
+ m_EncodingThreads[ssid] = thread;
+
+ //logDebug("startEncoder thread = " + TQString::number((long long)thread, 16));
+
+ notifySoundStreamCreated(encID);
+ return !thread->error();
+}
+
+
+void Recording::stopEncoder(SoundStreamID id)
+{
+ if (m_EncodingThreads.contains(id)) {
+
+ RecordingEncoding *thread = m_EncodingThreads[id];
+
+ thread->setDone();
+
+ //logDebug("stopEncoder thread = " + TQString::number((long long)thread, 16));
+ //logDebug("stopEncoder thread error = " + TQString::number(thread->error(), 16));
+
+ // FIXME: set a timer and do waiting "in background"
+ if (!thread->wait(5000)) {
+ //m_context.setError();
+ logError(i18n("The encoding thread did not finish. It will be killed now."));
+ thread->terminate();
+ thread->wait();
+ } else {
+ if (thread->error()) {
+ //m_context.setError();
+ logError(thread->errorString());
+ } else {
+ //TQ_UINT64 size = thread->encodedSize();
+ //m_context.setEncodedSize(low, high);
+ //notifyRecordingContextChanged(m_context);
+ }
+ }
+ delete thread;
+ m_EncodingThreads.remove(id);
+ SoundStreamID encID = m_RawStreams2EncodedStreams[id];
+ m_EncodedStreams2RawStreams.remove(encID);
+ m_RawStreams2EncodedStreams.remove(id);
+ sendStopPlayback(encID);
+ closeSoundStream(encID);
+ logInfo(i18n("Recording stopped"));
+ }
+}
+
+
+bool Recording::event(TQEvent *_e)
+{
+ if (SoundStreamEvent::isSoundStreamEvent(_e)) {
+ SoundStreamEvent *e = static_cast<SoundStreamEvent*>(_e);
+ SoundStreamID id = e->getSoundStreamID();
+
+ if (m_EncodingThreads.contains(id)) {
+
+ RecordingEncoding *thread = m_EncodingThreads[id];
+
+ //logDebug("Recording::event: thread = " + TQString::number((long long)thread, 16));
+
+ if (thread->error()) {
+ logError(thread->errorString());
+ //m_context.setError();
+ stopEncoder(id);
+ } else {
+ //TQ_UINT64 size = thread->encodedSize();
+ //m_context.setEncodedSize(low, high);
+ //notifyRecordingContextChanged(m_context);
+ if (e->type() == EncodingTerminated) {
+ stopEncoder(id);
+ } else if (e->type() == EncodingStep) {
+ SoundStreamEncodingStepEvent *step = static_cast<SoundStreamEncodingStepEvent*>(e);
+ size_t consumed_size = SIZE_T_DONT_CARE;
+ notifySoundStreamData(m_RawStreams2EncodedStreams[id], thread->config().m_SoundFormat,
+ step->data(), step->size(), consumed_size, step->metaData());
+ if (consumed_size != SIZE_T_DONT_CARE && consumed_size < step->size()) {
+ logError(i18n("Recording::notifySoundStreamData(encoded data): Receivers skipped %1 Bytes").arg(step->size() - consumed_size));
+ }
+ }
+ }
+ }
+ return true;
+ } else {
+ return TQObject::event(_e);
+ }
+}
+
+
+bool Recording::getSoundStreamDescription(SoundStreamID id, TQString &descr) const
+{
+ if (m_EncodedStreams2RawStreams.contains(id)) {
+ if (querySoundStreamDescription(m_EncodedStreams2RawStreams[id], descr)) {
+ descr = name() + " - " + descr;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool Recording::getSoundStreamRadioStation(SoundStreamID id, const RadioStation *&rs) const
+{
+ if (m_EncodedStreams2RawStreams.contains(id)) {
+ if (querySoundStreamRadioStation(m_EncodedStreams2RawStreams[id], rs)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool Recording::enumerateSoundStreams(TQMap<TQString, SoundStreamID> &list) const
+{
+ TQMapConstIterator<SoundStreamID,SoundStreamID> end = m_RawStreams2EncodedStreams.end();
+ for (TQMapConstIterator<SoundStreamID,SoundStreamID> it = m_RawStreams2EncodedStreams.begin(); it != end; ++it) {
+ TQString tmp = TQString();
+ getSoundStreamDescription(*it, tmp);
+ list[tmp] = *it;
+ }
+ return m_RawStreams2EncodedStreams.count() > 0;
+}
+
+
+bool Recording::noticeSoundStreamChanged(SoundStreamID id)
+{
+ if (m_RawStreams2EncodedStreams.contains(id)) {
+ notifySoundStreamChanged(m_RawStreams2EncodedStreams[id]);
+ return true;
+ }
+ return false;
+}
+
+
+bool Recording::isRecordingRunning(SoundStreamID id, bool &b, SoundFormat &sf) const
+{
+ if (m_EncodingThreads.contains(id)) {
+ b = m_EncodingThreads[id]->running();
+ sf = getSoundFormat();
+ return true;
+ }
+ return false;
+}
+
+
+bool Recording::noticeSoundStreamClosed(SoundStreamID id)
+{
+ if (m_PreRecordingBuffers.contains(id)) {
+ if (m_PreRecordingBuffers[id])
+ delete m_PreRecordingBuffers[id];
+ m_PreRecordingBuffers.remove(id);
+ }
+
+ if (m_EncodingThreads.contains(id)) {
+ sendStopRecording(id);
+ return true;
+ }
+ return false;
+}
+
+
+#include "recording.moc"
diff --git a/plugins/recording/recording.h b/plugins/recording/recording.h
new file mode 100644
index 0000000..7d48331
--- /dev/null
+++ b/plugins/recording/recording.h
@@ -0,0 +1,149 @@
+/***************************************************************************
+ recording.h - description
+ -------------------
+ begin : Mi Aug 27 2003
+ copyright : (C) 2003 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_RECORDING_H
+#define KRADIO_RECORDING_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <tqobject.h>
+#include <tqstring.h>
+#include <tqmap.h>
+
+#include "../../src/include/plugins.h"
+#include "../../src/include/timecontrol_interfaces.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+
+#include "recording-config.h"
+#include "reccfg_interfaces.h"
+#include "encoder.h"
+
+class RadioStation;
+class StationList;
+class TQSocketNotifier;
+class RecordingEncoding;
+class FileRingBuffer;
+
+class Recording : public TQObject,
+ public PluginBase,
+ public ISoundStreamClient,
+ public IRecCfg
+{
+Q_OBJECT
+
+public:
+ Recording(const TQString &name);
+ ~Recording();
+
+ virtual TQString pluginClassName() const { return "Recording"; }
+
+ virtual const TQString &name() const { return PluginBase::name(); }
+ virtual TQString &name() { return PluginBase::name(); }
+
+ virtual bool connectI(Interface *i);
+ virtual bool disconnectI(Interface *i);
+
+
+ bool isRecording () const;
+
+
+ // PluginBase
+
+public:
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+ virtual ConfigPageInfo createConfigurationPage();
+ virtual AboutPageInfo createAboutPage();
+
+protected:
+
+// IRecCfg
+
+ bool setEncoderBuffer (size_t BufferSize, size_t BufferCount);
+ bool setSoundFormat (const SoundFormat &sf);
+ bool setMP3Quality (int q);
+ bool setOggQuality (float q);
+ bool setRecordingDirectory(const TQString &dir);
+ bool setOutputFormat (RecordingConfig::OutputFormat of);
+ bool setPreRecording (bool enable, int seconds);
+ bool setRecordingConfig (const RecordingConfig &cfg);
+
+ void getEncoderBuffer(size_t &BufferSize, size_t &BufferCount) const;
+ const SoundFormat &getSoundFormat () const;
+ int getMP3Quality () const;
+ float getOggQuality () const;
+ const TQString &getRecordingDirectory() const;
+ RecordingConfig::OutputFormat getOutputFormat() const;
+ bool getPreRecording(int &seconds) const;
+ const RecordingConfig &getRecordingConfig() const;
+
+// ISoundStreamClient
+
+ void noticeConnectedI (ISoundStreamServer *s, bool pointer_valid);
+
+ bool startPlayback(SoundStreamID id);
+ bool stopPlayback(SoundStreamID id);
+
+ bool startRecording(SoundStreamID id);
+ bool startRecordingWithFormat(SoundStreamID id, const SoundFormat &sf, SoundFormat &real_format);
+ bool noticeSoundStreamData(SoundStreamID id, const SoundFormat &sf, const char *data, size_t size, size_t &consumed_size, const SoundMetaData &md);
+ bool stopRecording(SoundStreamID id);
+ bool isRecordingRunning(SoundStreamID id, bool &b, SoundFormat &sf) const;
+
+ bool getSoundStreamDescription(SoundStreamID id, TQString &descr) const;
+ bool getSoundStreamRadioStation(SoundStreamID id, const RadioStation *&rs) const;
+
+ bool noticeSoundStreamClosed(SoundStreamID id);
+ bool noticeSoundStreamChanged(SoundStreamID id);
+
+ bool enumerateSoundStreams(TQMap<TQString, SoundStreamID> &list) const;
+
+protected slots:
+
+ bool event(TQEvent *e);
+
+protected:
+
+ bool startEncoder(SoundStreamID ssid, const RecordingConfig &cfg);
+ void stopEncoder(SoundStreamID ssid);
+
+protected:
+
+ RecordingConfig m_config;
+ TQMap<SoundStreamID, FileRingBuffer*> m_PreRecordingBuffers;
+
+ TQMap<SoundStreamID, RecordingEncoding*> m_EncodingThreads;
+ TQMap<SoundStreamID, SoundStreamID> m_RawStreams2EncodedStreams;
+ TQMap<SoundStreamID, SoundStreamID> m_EncodedStreams2RawStreams;
+};
+
+/* PreRecording Notes: listen for startplayback, stopplayback, closestream
+ manage map streamid => buffer
+ set each started stream into capture mode
+ put data into ringbuffers
+ on capture start, feed everything into the encoder buffer,
+ if encoderbuffer < prerecbuffer =>
+ put as much as possible into encoder
+ put new audio data into ring buffer
+
+*/
+
+#endif
diff --git a/plugins/recording/soundstreamevent.h b/plugins/recording/soundstreamevent.h
new file mode 100644
index 0000000..c7b986e
--- /dev/null
+++ b/plugins/recording/soundstreamevent.h
@@ -0,0 +1,87 @@
+/***************************************************************************
+ soundstreamevent.h - description
+ -------------------
+ begin : Fri May 06 2005
+ copyright : (C) 2005 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_RECORDING_SOUNDSTREAM_EVENT_H
+#define KRADIO_RECORDING_SOUNDSTREAM_EVENT_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tqevent.h>
+
+#include "../../src/include/sound_metadata.h"
+
+const TQEvent::Type EncodingTerminated = (TQEvent::Type)(TQEvent::User+1);
+const TQEvent::Type EncodingStep = (TQEvent::Type)(TQEvent::User+2);
+
+class SoundStreamEvent : public TQEvent
+{
+public:
+ SoundStreamEvent(TQEvent::Type t, SoundStreamID id) : TQEvent(t), m_SSID(id) {}
+ const SoundStreamID &getSoundStreamID() const { return m_SSID; }
+
+ static bool isSoundStreamEvent (const TQEvent *e) { return e && ((e->type() == EncodingTerminated) || (e->type() == EncodingStep)); }
+
+protected:
+ SoundStreamID m_SSID;
+};
+
+
+
+
+
+
+class SoundStreamEncodingTerminatedEvent : public SoundStreamEvent
+{
+public:
+ SoundStreamEncodingTerminatedEvent(SoundStreamID id) : SoundStreamEvent(EncodingTerminated, id) {}
+};
+
+
+
+
+
+
+class SoundStreamEncodingStepEvent : public SoundStreamEvent
+{
+public:
+ SoundStreamEncodingStepEvent(SoundStreamID id, const char *data, size_t size, const SoundMetaData &md)
+ : SoundStreamEvent(EncodingStep, id),
+ m_Size(size),
+ m_MetaData(md)
+ {
+ m_Data = new char [m_Size];
+ memcpy (m_Data, data, m_Size);
+ }
+ virtual ~SoundStreamEncodingStepEvent() { freeData(); }
+
+ void freeData() { if (m_Data) delete m_Data; m_Data = NULL; m_Size = 0; } // _MUST_ be called by event receiver
+
+ const char *data() const { return m_Data; }
+ size_t size() const { return m_Size; }
+ const SoundMetaData &metaData() const { return m_MetaData; }
+
+ static bool isSoundStreamEncodingStep (const TQEvent *e) { return e && (e->type() == EncodingStep); }
+
+protected:
+ char *m_Data;
+ size_t m_Size;
+ SoundMetaData m_MetaData;
+};
+
+#endif
diff --git a/plugins/soundserver/CMakeL10n.txt b/plugins/soundserver/CMakeL10n.txt
new file mode 100644
index 0000000..afd005e
--- /dev/null
+++ b/plugins/soundserver/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-soundserver"
+ DESTINATION "po"
+)
diff --git a/plugins/soundserver/Makefile.am b/plugins/soundserver/Makefile.am
new file mode 100644
index 0000000..bac5fe3
--- /dev/null
+++ b/plugins/soundserver/Makefile.am
@@ -0,0 +1,18 @@
+SUBDIRS = po .
+
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = libsoundserver.la
+
+libsoundserver_la_SOURCES = soundserver.cpp
+libsoundserver_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+
+noinst_HEADERS = soundserver.h
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-sound-server.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-soundserver.pot
diff --git a/plugins/soundserver/po/Makefile.am b/plugins/soundserver/po/Makefile.am
new file mode 100644
index 0000000..f469927
--- /dev/null
+++ b/plugins/soundserver/po/Makefile.am
@@ -0,0 +1,2 @@
+PACKAGE = tderadio-soundserver
+POFILES = AUTO
diff --git a/plugins/soundserver/po/de.po b/plugins/soundserver/po/de.po
new file mode 100644
index 0000000..19e4c42
--- /dev/null
+++ b/plugins/soundserver/po/de.po
@@ -0,0 +1,44 @@
+# translation of de.po to
+# translation of tderadio-sound-server.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-22 13:27+0000\n"
+"Last-Translator: Chris <xchrisx@uber.space>\n"
+"Language-Team: German <https://mirror.git.trinitydesktop.org/weblate/"
+"projects/applications/tderadio-soundserver/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 "Chris (TDE)"
+
+#. 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 "(Keine Email)"
+
+#: soundserver.cpp:27
+msgid "SoundServer"
+msgstr "SoundServer"
+
+#: soundserver.cpp:32
+msgid "SoundServer Plugin"
+msgstr "SoundServer Zusatzmodul"
+
+#: soundserver.cpp:34
+msgid "initializing tderadio soundserver"
+msgstr "Initialisierung des TDERadio-Soundservers"
diff --git a/plugins/soundserver/po/ru.po b/plugins/soundserver/po/ru.po
new file mode 100644
index 0000000..b0c42ef
--- /dev/null
+++ b/plugins/soundserver/po/ru.po
@@ -0,0 +1,42 @@
+# translation of ru.po to
+# translation of tderadio-soundserver.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:46+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 ""
+
+#: soundserver.cpp:27
+msgid "SoundServer"
+msgstr "SoundServer"
+
+#: soundserver.cpp:32
+msgid "SoundServer Plugin"
+msgstr "Модуль звукового сервера"
+
+#: soundserver.cpp:34
+msgid "initializing tderadio soundserver"
+msgstr "Включение звукового сервера TDERadio"
diff --git a/plugins/soundserver/po/tderadio-soundserver.pot b/plugins/soundserver/po/tderadio-soundserver.pot
new file mode 100644
index 0000000..54cb4f5
--- /dev/null
+++ b/plugins/soundserver/po/tderadio-soundserver.pot
@@ -0,0 +1,40 @@
+# 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 ""
+
+#: soundserver.cpp:27
+msgid "SoundServer"
+msgstr ""
+
+#: soundserver.cpp:32
+msgid "SoundServer Plugin"
+msgstr ""
+
+#: soundserver.cpp:34
+msgid "initializing tderadio soundserver"
+msgstr ""
diff --git a/plugins/soundserver/soundserver.cpp b/plugins/soundserver/soundserver.cpp
new file mode 100644
index 0000000..305e4c2
--- /dev/null
+++ b/plugins/soundserver/soundserver.cpp
@@ -0,0 +1,74 @@
+/***************************************************************************
+ soundserver.cpp - description
+ -------------------
+ begin : Sun Apr 17 2005
+ copyright : (C) 2003 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 "soundserver.h"
+
+#include <tdeapplication.h>
+#include <tdelocale.h>
+
+
+///////////////////////////////////////////////////////////////////////
+//// plugin library functions
+
+PLUGIN_LIBRARY_FUNCTIONS(SoundServer, "tderadio-soundserver", i18n("SoundServer"));
+
+/////////////////////////////////////////////////////////////////////////////
+
+SoundServer::SoundServer(const TQString &name)
+ : PluginBase(name, i18n("SoundServer Plugin"))
+{
+ logDebug(i18n("initializing tderadio soundserver"));
+}
+
+SoundServer::~SoundServer()
+{
+}
+
+bool SoundServer::connectI (Interface *i)
+{
+ bool a = PluginBase::connectI(i);
+ bool b = ISoundStreamServer::connectI(i);
+ return a || b;
+}
+
+
+bool SoundServer::disconnectI (Interface *i)
+{
+ bool a = PluginBase::disconnectI(i);
+ bool b = ISoundStreamServer::disconnectI(i);
+ return a || b;
+}
+
+
+
+void SoundServer::saveState (TDEConfig *) const
+{
+}
+
+void SoundServer::restoreState (TDEConfig *)
+{
+}
+
+ConfigPageInfo SoundServer::createConfigurationPage()
+{
+ return ConfigPageInfo ();
+}
+
+AboutPageInfo SoundServer::createAboutPage()
+{
+ return AboutPageInfo();
+}
diff --git a/plugins/soundserver/soundserver.h b/plugins/soundserver/soundserver.h
new file mode 100644
index 0000000..f01e863
--- /dev/null
+++ b/plugins/soundserver/soundserver.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ soundserver.h - description
+ -------------------
+ begin : Sun Apr 17 2005
+ copyright : (C) 2003 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_SOUNDSERVER_H
+#define KRADIO_SOUNDSERVER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/soundstreamclient_interfaces.h"
+#include "../../src/include/plugins.h"
+
+
+class SoundServer : public PluginBase,
+ public ISoundStreamServer
+{
+public:
+ SoundServer(const TQString &name);
+ ~SoundServer();
+
+ virtual bool connectI (Interface *);
+ virtual bool disconnectI (Interface *);
+
+ virtual TQString pluginClassName() const { return "SoundServer"; }
+
+ virtual const TQString &name() const { return PluginBase::name(); }
+ virtual TQString &name() { return PluginBase::name(); }
+
+ // PluginBase
+
+public:
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+ virtual ConfigPageInfo createConfigurationPage();
+ virtual AboutPageInfo createAboutPage();
+};
+
+#endif
diff --git a/plugins/streaming/CMakeL10n.txt b/plugins/streaming/CMakeL10n.txt
new file mode 100644
index 0000000..6d6e365
--- /dev/null
+++ b/plugins/streaming/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-streaming"
+ DESTINATION "po"
+)
diff --git a/plugins/streaming/Makefile.am b/plugins/streaming/Makefile.am
new file mode 100644
index 0000000..783a6e2
--- /dev/null
+++ b/plugins/streaming/Makefile.am
@@ -0,0 +1,18 @@
+SUBDIRS = po icons .
+
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = libstreaming.la
+libstreaming_la_SOURCES = streaming.cpp streaming-configuration-ui.ui \
+ streaming-configuration.cpp streaming-job.cpp
+libstreaming_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+
+noinst_HEADERS = streaming.h streaming-configuration.h streaming-job.h
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-streaming.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-streaming.pot
diff --git a/plugins/streaming/icons/Makefile.am b/plugins/streaming/icons/Makefile.am
new file mode 100644
index 0000000..974b96b
--- /dev/null
+++ b/plugins/streaming/icons/Makefile.am
@@ -0,0 +1,2 @@
+icons_ICON = AUTO
+iconsdir = $(datadir)/icons
diff --git a/plugins/streaming/icons/hi16-action-tderadio_streaming.png b/plugins/streaming/icons/hi16-action-tderadio_streaming.png
new file mode 100644
index 0000000..320a633
--- /dev/null
+++ b/plugins/streaming/icons/hi16-action-tderadio_streaming.png
Binary files differ
diff --git a/plugins/streaming/icons/hi22-action-tderadio_streaming.png b/plugins/streaming/icons/hi22-action-tderadio_streaming.png
new file mode 100644
index 0000000..e582ea8
--- /dev/null
+++ b/plugins/streaming/icons/hi22-action-tderadio_streaming.png
Binary files differ
diff --git a/plugins/streaming/icons/hi32-action-tderadio_streaming.png b/plugins/streaming/icons/hi32-action-tderadio_streaming.png
new file mode 100644
index 0000000..0767a6a
--- /dev/null
+++ b/plugins/streaming/icons/hi32-action-tderadio_streaming.png
Binary files differ
diff --git a/plugins/streaming/icons/hi48-action-tderadio_streaming.png b/plugins/streaming/icons/hi48-action-tderadio_streaming.png
new file mode 100644
index 0000000..6ace14e
--- /dev/null
+++ b/plugins/streaming/icons/hi48-action-tderadio_streaming.png
Binary files differ
diff --git a/plugins/streaming/icons/hi64-action-tderadio_streaming.png b/plugins/streaming/icons/hi64-action-tderadio_streaming.png
new file mode 100644
index 0000000..a9fc990
--- /dev/null
+++ b/plugins/streaming/icons/hi64-action-tderadio_streaming.png
Binary files differ
diff --git a/plugins/streaming/po/Makefile.am b/plugins/streaming/po/Makefile.am
new file mode 100644
index 0000000..ce811b6
--- /dev/null
+++ b/plugins/streaming/po/Makefile.am
@@ -0,0 +1,2 @@
+PACKAGE = tderadio-streaming
+POFILES = AUTO
diff --git a/plugins/streaming/po/de.po b/plugins/streaming/po/de.po
new file mode 100644
index 0000000..54833bc
--- /dev/null
+++ b/plugins/streaming/po/de.po
@@ -0,0 +1,206 @@
+# translation of de.po to
+# translation of tderadio-streaming.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: 2021-07-07 18:28+0000\n"
+"PO-Revision-Date: 2019-08-31 00:45+0000\n"
+"Last-Translator: Chris <xchrisx@uber.space>\n"
+"Language-Team: German <https://mirror.git.trinitydesktop.org/weblate/"
+"projects/applications/tderadio-streaming/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.8\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 "Chris (TDE)"
+
+#. 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 "(Keine Email)"
+
+#: streaming-configuration.cpp:155 streaming-configuration.cpp:259
+msgid "new channel"
+msgstr "Neuer Kanal"
+
+#: streaming-job.cpp:204
+msgid "skipped %1 bytes"
+msgstr "%1 bytes wurden übersprungen"
+
+#: streaming.cpp:33
+msgid "Streaming Support"
+msgstr "Unterstützung für das Streaming"
+
+#: streaming.cpp:42
+msgid "TDERadio Streaming Plugin"
+msgstr "TDERadio Streaming-Plugin"
+
+#: streaming.cpp:172
+msgid "Streaming"
+msgstr "Streaming"
+
+#: streaming.cpp:173
+msgid "Streaming Device Options"
+msgstr "Geräteoptionen für das Streaming"
+
+#: streaming.cpp:393
+msgid "internal stream, not stored (%1)"
+msgstr "interner, nicht aufgezeichneter Datenstrom (%1)"
+
+#: streaming.cpp:403
+msgid ""
+"StreamingDevice %1::notifySoundStreamData: Playback Clients skipped %2 bytes"
+msgstr ""
+"Streaminggerät %1::notifySoundStreamData: Die Wiedergabe-Module haben %2 "
+"bytes übersprungen."
+
+#: streaming.cpp:426
+#, c-format
+msgid "Streaming Device %1"
+msgstr "Streaming-Gerät %1"
+
+#: streaming.cpp:432 streaming.cpp:437
+msgid "Streaming Device %1, %2: %3"
+msgstr "Streaming-Gerät %1, %2: %3"
+
+#: streaming-configuration-ui.ui:16
+#, no-c-format
+msgid "StreamingConfigurationUI"
+msgstr "StreamingConfigurationUI"
+
+#: streaming-configuration-ui.ui:33 streaming-configuration-ui.ui:74
+#, no-c-format
+msgid "No."
+msgstr "Nr."
+
+#: streaming-configuration-ui.ui:44 streaming-configuration-ui.ui:85
+#, no-c-format
+msgid "URL"
+msgstr "URL"
+
+#: streaming-configuration-ui.ui:114
+#, no-c-format
+msgid "Capture URLs"
+msgstr "Aufnahme-URL"
+
+#: streaming-configuration-ui.ui:122
+#, no-c-format
+msgid "Playback URLs"
+msgstr "Wiedergabe-URL"
+
+#: streaming-configuration-ui.ui:434
+#, no-c-format
+msgid "URL Properties"
+msgstr "URL-Eigenschaften"
+
+#: streaming-configuration-ui.ui:446
+#, no-c-format
+msgid "Stereo"
+msgstr "Stereo"
+
+#: streaming-configuration-ui.ui:451
+#, no-c-format
+msgid "Mono"
+msgstr "Mono"
+
+#: streaming-configuration-ui.ui:471
+#, no-c-format
+msgid "Sample Bits"
+msgstr "Quantisierungs-Bits"
+
+#: streaming-configuration-ui.ui:479
+#, no-c-format
+msgid "Channels"
+msgstr "Kanäle"
+
+#: streaming-configuration-ui.ui:487
+#, no-c-format
+msgid "Endianess"
+msgstr "Byte-Reihenfolge"
+
+#: streaming-configuration-ui.ui:493
+#, no-c-format
+msgid "Little Endian"
+msgstr "Little Endian"
+
+#: streaming-configuration-ui.ui:498
+#, no-c-format
+msgid "Big Endian"
+msgstr "Big Endian"
+
+#: streaming-configuration-ui.ui:516
+#, no-c-format
+msgid "48000"
+msgstr "48000"
+
+#: streaming-configuration-ui.ui:521
+#, no-c-format
+msgid "44100"
+msgstr "44100"
+
+#: streaming-configuration-ui.ui:526
+#, no-c-format
+msgid "22050"
+msgstr "22050"
+
+#: streaming-configuration-ui.ui:531
+#, no-c-format
+msgid "11025"
+msgstr "11025"
+
+#: streaming-configuration-ui.ui:549
+#, no-c-format
+msgid "16"
+msgstr "16"
+
+#: streaming-configuration-ui.ui:554
+#, no-c-format
+msgid "8"
+msgstr "8"
+
+#: streaming-configuration-ui.ui:572
+#, no-c-format
+msgid "Raw"
+msgstr "Rohdaten"
+
+#: streaming-configuration-ui.ui:592
+#, no-c-format
+msgid "kB"
+msgstr "kB"
+
+#: streaming-configuration-ui.ui:609
+#, no-c-format
+msgid "Buffer Size"
+msgstr "Puffergröße"
+
+#: streaming-configuration-ui.ui:617
+#, no-c-format
+msgid "Format"
+msgstr "Format"
+
+#: streaming-configuration-ui.ui:625
+#, no-c-format
+msgid "Sample Rate"
+msgstr "Abtastrate"
+
+#: streaming-configuration-ui.ui:631
+#, no-c-format
+msgid "Signed"
+msgstr "Vorzeichenbehaftet"
+
+#: streaming-configuration-ui.ui:636
+#, no-c-format
+msgid "Unsigned"
+msgstr "Vorzeichenlos"
diff --git a/plugins/streaming/po/ru.po b/plugins/streaming/po/ru.po
new file mode 100644
index 0000000..0e681f3
--- /dev/null
+++ b/plugins/streaming/po/ru.po
@@ -0,0 +1,206 @@
+# translation of ru.po to
+# translation of tderadio-streaming.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: 2021-07-07 18:28+0000\n"
+"PO-Revision-Date: 2006-11-08 12:25+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 ""
+
+#: streaming-configuration.cpp:155 streaming-configuration.cpp:259
+msgid "new channel"
+msgstr "новый канал"
+
+#: streaming-job.cpp:204
+msgid "skipped %1 bytes"
+msgstr "Пропущено %1 байт"
+
+#: streaming.cpp:33
+msgid "Streaming Support"
+msgstr ""
+"Сетевое\n"
+"вещание"
+
+#: streaming.cpp:42
+msgid "TDERadio Streaming Plugin"
+msgstr "Модуль сетевого вещания для TDERadio"
+
+#: streaming.cpp:172
+msgid "Streaming"
+msgstr ""
+"Сетевое\n"
+"вещание"
+
+#: streaming.cpp:173
+msgid "Streaming Device Options"
+msgstr "Параметры сетевого вещания"
+
+#: streaming.cpp:393
+msgid "internal stream, not stored (%1)"
+msgstr ""
+
+#: streaming.cpp:403
+msgid ""
+"StreamingDevice %1::notifySoundStreamData: Playback Clients skipped %2 bytes"
+msgstr "StreamingDevice %1::notifySoundStreamData: Клиенты пропустили %2 байт"
+
+#: streaming.cpp:426
+#, c-format
+msgid "Streaming Device %1"
+msgstr "Устройство вещания %1"
+
+#: streaming.cpp:432 streaming.cpp:437
+msgid "Streaming Device %1, %2: %3"
+msgstr "Устройство вещания %1, %2: %3"
+
+#: streaming-configuration-ui.ui:16
+#, no-c-format
+msgid "StreamingConfigurationUI"
+msgstr "StreamingConfigurationUI"
+
+#: streaming-configuration-ui.ui:33 streaming-configuration-ui.ui:74
+#, no-c-format
+msgid "No."
+msgstr "No "
+
+#: streaming-configuration-ui.ui:44 streaming-configuration-ui.ui:85
+#, no-c-format
+msgid "URL"
+msgstr "Адрес"
+
+#: streaming-configuration-ui.ui:114
+#, no-c-format
+msgid "Capture URLs"
+msgstr "Адреса для записи"
+
+#: streaming-configuration-ui.ui:122
+#, no-c-format
+msgid "Playback URLs"
+msgstr "Адреса для воспроизведения"
+
+#: streaming-configuration-ui.ui:434
+#, no-c-format
+msgid "URL Properties"
+msgstr "Параметры для URL"
+
+#: streaming-configuration-ui.ui:446
+#, no-c-format
+msgid "Stereo"
+msgstr "2 (Стерео)"
+
+#: streaming-configuration-ui.ui:451
+#, no-c-format
+msgid "Mono"
+msgstr "1 (Моно)"
+
+#: streaming-configuration-ui.ui:471
+#, no-c-format
+msgid "Sample Bits"
+msgstr "Бит на элемент выборки"
+
+#: streaming-configuration-ui.ui:479
+#, no-c-format
+msgid "Channels"
+msgstr "Число каналов"
+
+#: streaming-configuration-ui.ui:487
+#, no-c-format
+msgid "Endianess"
+msgstr "Порядок байтов"
+
+#: streaming-configuration-ui.ui:493
+#, no-c-format
+msgid "Little Endian"
+msgstr "Little Endian"
+
+#: streaming-configuration-ui.ui:498
+#, no-c-format
+msgid "Big Endian"
+msgstr "Big Endian"
+
+#: streaming-configuration-ui.ui:516
+#, no-c-format
+msgid "48000"
+msgstr "48000"
+
+#: streaming-configuration-ui.ui:521
+#, no-c-format
+msgid "44100"
+msgstr "44100"
+
+#: streaming-configuration-ui.ui:526
+#, no-c-format
+msgid "22050"
+msgstr "22050"
+
+#: streaming-configuration-ui.ui:531
+#, no-c-format
+msgid "11025"
+msgstr "11025"
+
+#: streaming-configuration-ui.ui:549
+#, no-c-format
+msgid "16"
+msgstr "16"
+
+#: streaming-configuration-ui.ui:554
+#, no-c-format
+msgid "8"
+msgstr "8"
+
+#: streaming-configuration-ui.ui:572
+#, no-c-format
+msgid "Raw"
+msgstr "Raw"
+
+#: streaming-configuration-ui.ui:592
+#, no-c-format
+msgid "kB"
+msgstr "kB"
+
+#: streaming-configuration-ui.ui:609
+#, no-c-format
+msgid "Buffer Size"
+msgstr "Размер буфера"
+
+#: streaming-configuration-ui.ui:617
+#, no-c-format
+msgid "Format"
+msgstr "Формат"
+
+#: streaming-configuration-ui.ui:625
+#, no-c-format
+msgid "Sample Rate"
+msgstr "Частота дискретизации"
+
+#: streaming-configuration-ui.ui:631
+#, no-c-format
+msgid "Signed"
+msgstr "Со знаком"
+
+#: streaming-configuration-ui.ui:636
+#, no-c-format
+msgid "Unsigned"
+msgstr "Без знака"
diff --git a/plugins/streaming/po/tderadio-streaming.pot b/plugins/streaming/po/tderadio-streaming.pot
new file mode 100644
index 0000000..df9409e
--- /dev/null
+++ b/plugins/streaming/po/tderadio-streaming.pot
@@ -0,0 +1,200 @@
+# SOME DESCRIPTIVE TITLE.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2021-07-07 18:28+0000\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 ""
+
+#: streaming-configuration.cpp:155 streaming-configuration.cpp:259
+msgid "new channel"
+msgstr ""
+
+#: streaming-job.cpp:204
+msgid "skipped %1 bytes"
+msgstr ""
+
+#: streaming.cpp:33
+msgid "Streaming Support"
+msgstr ""
+
+#: streaming.cpp:42
+msgid "TDERadio Streaming Plugin"
+msgstr ""
+
+#: streaming.cpp:172
+msgid "Streaming"
+msgstr ""
+
+#: streaming.cpp:173
+msgid "Streaming Device Options"
+msgstr ""
+
+#: streaming.cpp:393
+msgid "internal stream, not stored (%1)"
+msgstr ""
+
+#: streaming.cpp:403
+msgid ""
+"StreamingDevice %1::notifySoundStreamData: Playback Clients skipped %2 bytes"
+msgstr ""
+
+#: streaming.cpp:426
+#, c-format
+msgid "Streaming Device %1"
+msgstr ""
+
+#: streaming.cpp:432 streaming.cpp:437
+msgid "Streaming Device %1, %2: %3"
+msgstr ""
+
+#: streaming-configuration-ui.ui:16
+#, no-c-format
+msgid "StreamingConfigurationUI"
+msgstr ""
+
+#: streaming-configuration-ui.ui:33 streaming-configuration-ui.ui:74
+#, no-c-format
+msgid "No."
+msgstr ""
+
+#: streaming-configuration-ui.ui:44 streaming-configuration-ui.ui:85
+#, no-c-format
+msgid "URL"
+msgstr ""
+
+#: streaming-configuration-ui.ui:114
+#, no-c-format
+msgid "Capture URLs"
+msgstr ""
+
+#: streaming-configuration-ui.ui:122
+#, no-c-format
+msgid "Playback URLs"
+msgstr ""
+
+#: streaming-configuration-ui.ui:434
+#, no-c-format
+msgid "URL Properties"
+msgstr ""
+
+#: streaming-configuration-ui.ui:446
+#, no-c-format
+msgid "Stereo"
+msgstr ""
+
+#: streaming-configuration-ui.ui:451
+#, no-c-format
+msgid "Mono"
+msgstr ""
+
+#: streaming-configuration-ui.ui:471
+#, no-c-format
+msgid "Sample Bits"
+msgstr ""
+
+#: streaming-configuration-ui.ui:479
+#, no-c-format
+msgid "Channels"
+msgstr ""
+
+#: streaming-configuration-ui.ui:487
+#, no-c-format
+msgid "Endianess"
+msgstr ""
+
+#: streaming-configuration-ui.ui:493
+#, no-c-format
+msgid "Little Endian"
+msgstr ""
+
+#: streaming-configuration-ui.ui:498
+#, no-c-format
+msgid "Big Endian"
+msgstr ""
+
+#: streaming-configuration-ui.ui:516
+#, no-c-format
+msgid "48000"
+msgstr ""
+
+#: streaming-configuration-ui.ui:521
+#, no-c-format
+msgid "44100"
+msgstr ""
+
+#: streaming-configuration-ui.ui:526
+#, no-c-format
+msgid "22050"
+msgstr ""
+
+#: streaming-configuration-ui.ui:531
+#, no-c-format
+msgid "11025"
+msgstr ""
+
+#: streaming-configuration-ui.ui:549
+#, no-c-format
+msgid "16"
+msgstr ""
+
+#: streaming-configuration-ui.ui:554
+#, no-c-format
+msgid "8"
+msgstr ""
+
+#: streaming-configuration-ui.ui:572
+#, no-c-format
+msgid "Raw"
+msgstr ""
+
+#: streaming-configuration-ui.ui:592
+#, no-c-format
+msgid "kB"
+msgstr ""
+
+#: streaming-configuration-ui.ui:609
+#, no-c-format
+msgid "Buffer Size"
+msgstr ""
+
+#: streaming-configuration-ui.ui:617
+#, no-c-format
+msgid "Format"
+msgstr ""
+
+#: streaming-configuration-ui.ui:625
+#, no-c-format
+msgid "Sample Rate"
+msgstr ""
+
+#: streaming-configuration-ui.ui:631
+#, no-c-format
+msgid "Signed"
+msgstr ""
+
+#: streaming-configuration-ui.ui:636
+#, no-c-format
+msgid "Unsigned"
+msgstr ""
diff --git a/plugins/streaming/streaming-configuration-ui.ui b/plugins/streaming/streaming-configuration-ui.ui
new file mode 100644
index 0000000..2d4cf7f
--- /dev/null
+++ b/plugins/streaming/streaming-configuration-ui.ui
@@ -0,0 +1,769 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>StreamingConfigurationUI</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>StreamingConfigurationUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>397</width>
+ <height>423</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>StreamingConfigurationUI</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout48</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TDEListView" row="1" column="0">
+ <column>
+ <property name="text">
+ <string>No.</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>URL</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_ListPlaybackURLs</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="selectionMode" stdset="0">
+ <enum>Single</enum>
+ </property>
+ <property name="defaultRenameAction">
+ <enum>Accept</enum>
+ </property>
+ </widget>
+ <widget class="TDEListView" row="1" column="2">
+ <column>
+ <property name="text">
+ <string>No.</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>URL</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>m_ListCaptureURLs</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="defaultRenameAction">
+ <enum>Accept</enum>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="2">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Capture URLs</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Playback URLs</string>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget" row="1" column="3">
+ <property name="name">
+ <cstring>layout38_2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>m_pbNewCaptureURL</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"filenew2"</iconset>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>m_pbDeleteCaptureURL</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"edit-delete"</iconset>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer46_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>10</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>m_pbUpCaptureURL</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"1uparrow"</iconset>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>m_pbDownCaptureURL</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"1downarrow"</iconset>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget" row="1" column="1">
+ <property name="name">
+ <cstring>layout38</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>m_pbNewPlaybackURL</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"filenew2"</iconset>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>m_pbDeletePlaybackURL</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"edit-delete"</iconset>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer46</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>10</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>m_pbUpPlaybackURL</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"1uparrow"</iconset>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>m_pbDownPlaybackURL</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>30</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"1downarrow"</iconset>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>groupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>URL Properties</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>10</number>
+ </property>
+ <widget class="KComboBox" row="5" column="1">
+ <item>
+ <property name="text">
+ <string>Stereo</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Mono</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_cbChannels</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>lableBits</cstring>
+ </property>
+ <property name="text">
+ <string>Sample Bits</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="5" column="0">
+ <property name="name">
+ <cstring>lableChannels</cstring>
+ </property>
+ <property name="text">
+ <string>Channels</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="4" column="0">
+ <property name="name">
+ <cstring>lableEndianess</cstring>
+ </property>
+ <property name="text">
+ <string>Endianess</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="4" column="1">
+ <item>
+ <property name="text">
+ <string>Little Endian</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Big Endian</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_cbEndianess</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="2" column="1">
+ <item>
+ <property name="text">
+ <string>48000</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>44100</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>22050</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>11025</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_cbRate</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="3" column="1">
+ <item>
+ <property name="text">
+ <string>16</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>8</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_cbBits</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="1">
+ <item>
+ <property name="text">
+ <string>Raw</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_cbFormat</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="0" column="1">
+ <property name="name">
+ <cstring>m_sbBufferSize</cstring>
+ </property>
+ <property name="suffix">
+ <string>kB</string>
+ </property>
+ <property name="maxValue">
+ <number>1024</number>
+ </property>
+ <property name="minValue">
+ <number>4</number>
+ </property>
+ <property name="lineStep">
+ <number>4</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>labelRate_2</cstring>
+ </property>
+ <property name="text">
+ <string>Buffer Size</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>labelRate_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Format</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>labelRate</cstring>
+ </property>
+ <property name="text">
+ <string>Sample Rate</string>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="3" column="2">
+ <item>
+ <property name="text">
+ <string>Signed</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Unsigned</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>m_cbSign</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <spacer row="2" column="2">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>140</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>spacer1_4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>140</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="0" column="2">
+ <property name="name">
+ <cstring>spacer1_4_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>140</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="4" column="2">
+ <property name="name">
+ <cstring>spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>140</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="5" column="2">
+ <property name="name">
+ <cstring>spacer1_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Minimum</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>140</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>m_ListPlaybackURLs</tabstop>
+ <tabstop>m_pbNewPlaybackURL</tabstop>
+ <tabstop>m_pbDeletePlaybackURL</tabstop>
+ <tabstop>m_pbUpPlaybackURL</tabstop>
+ <tabstop>m_pbDownPlaybackURL</tabstop>
+ <tabstop>m_ListCaptureURLs</tabstop>
+ <tabstop>m_pbNewCaptureURL</tabstop>
+ <tabstop>m_pbDeleteCaptureURL</tabstop>
+ <tabstop>m_pbUpCaptureURL</tabstop>
+ <tabstop>m_pbDownCaptureURL</tabstop>
+ <tabstop>m_sbBufferSize</tabstop>
+ <tabstop>m_cbFormat</tabstop>
+ <tabstop>m_cbRate</tabstop>
+ <tabstop>m_cbBits</tabstop>
+ <tabstop>m_cbSign</tabstop>
+ <tabstop>m_cbEndianess</tabstop>
+ <tabstop>m_cbChannels</tabstop>
+</tabstops>
+<pixmapfunction>SmallIconSet</pixmapfunction>
+<layoutdefaults spacing="6" margin="0"/>
+<includes>
+ <include location="global" impldecl="in implementation">kcombobox.h</include>
+ <include location="global" impldecl="in implementation">kiconloader.h</include>
+ <include location="global" impldecl="in implementation">knuminput.h</include>
+ <include location="global" impldecl="in implementation">tdelistview.h</include>
+</includes>
+</UI>
diff --git a/plugins/streaming/streaming-configuration.cpp b/plugins/streaming/streaming-configuration.cpp
new file mode 100644
index 0000000..ab57bea
--- /dev/null
+++ b/plugins/streaming/streaming-configuration.cpp
@@ -0,0 +1,567 @@
+/***************************************************************************
+ streaming-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 <tdelistview.h>
+#include <kcombobox.h>
+#include <knuminput.h>
+
+#include <tdelocale.h>
+
+#include "streaming-configuration.h"
+#include "streaming.h"
+
+StreamingConfiguration::StreamingConfiguration (TQWidget *parent, StreamingDevice *streamer)
+ : StreamingConfigurationUI(parent),
+ m_ignore_updates(false),
+ m_dirty(true),
+ m_StreamingDevice(streamer)
+{
+ connect(m_pbNewPlaybackURL, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotNewPlaybackChannel()));
+ connect(m_pbDeletePlaybackURL, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotDeletePlaybackChannel()));
+ connect(m_pbUpPlaybackURL, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotUpPlaybackChannel()));
+ connect(m_pbDownPlaybackURL, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotDownPlaybackChannel()));
+ connect(m_ListPlaybackURLs, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(slotPlaybackSelectionChanged()));
+ connect(m_ListPlaybackURLs, TQT_SIGNAL(itemRenamed(TQListViewItem *)), this, TQT_SLOT(slotSetDirty()));
+
+ connect(m_pbNewCaptureURL, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotNewCaptureChannel()));
+ connect(m_pbDeleteCaptureURL, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotDeleteCaptureChannel()));
+ connect(m_pbUpCaptureURL, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotUpCaptureChannel()));
+ connect(m_pbDownCaptureURL, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotDownCaptureChannel()));
+ connect(m_ListCaptureURLs, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(slotCaptureSelectionChanged()));
+ connect(m_ListCaptureURLs, TQT_SIGNAL(itemRenamed(TQListViewItem *)), this, TQT_SLOT(slotSetDirty()));
+
+ connect(m_cbBits, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotUpdateSoundFormat()));
+ connect(m_cbChannels, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotUpdateSoundFormat()));
+ connect(m_cbEndianess, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotUpdateSoundFormat()));
+ connect(m_cbFormat, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotUpdateSoundFormat()));
+ connect(m_cbRate, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotUpdateSoundFormat()));
+ connect(m_cbSign, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotUpdateSoundFormat()));
+ connect(m_sbBufferSize, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotUpdateSoundFormat()));
+
+ m_ListPlaybackURLs->setAllColumnsShowFocus(true);
+ m_ListPlaybackURLs->setSorting(-1);
+ m_ListCaptureURLs->setAllColumnsShowFocus(true);
+ m_ListCaptureURLs->setSorting(-1);
+
+ slotCancel();
+}
+
+
+StreamingConfiguration::~StreamingConfiguration ()
+{
+}
+
+
+void StreamingConfiguration::slotOK()
+{
+ if (!m_dirty)
+ return;
+
+ m_StreamingDevice->resetPlaybackStreams(false);
+ m_StreamingDevice->resetCaptureStreams(false);
+
+ TQListViewItem *item = m_ListPlaybackURLs->firstChild();
+ for (int i = 0; item; ++i, item = item->nextSibling()) {
+ m_StreamingDevice->addPlaybackStream(item->text(1), m_PlaybackSoundFormats[i], m_PlaybackBufferSizes[i], !item->nextSibling());
+ }
+
+ item = m_ListCaptureURLs->firstChild();
+ for (int i = 0; item; ++i, item = item->nextSibling()) {
+ m_StreamingDevice->addCaptureStream(item->text(1), m_CaptureSoundFormats[i], m_CaptureBufferSizes[i], !item->nextSibling());
+ }
+
+ m_dirty = false;
+}
+
+
+void StreamingConfiguration::slotCancel()
+{
+ if (!m_dirty)
+ return;
+
+ const TQStringList &playbackChannels = m_StreamingDevice->getPlaybackChannels();
+ const TQStringList &captureChannels = m_StreamingDevice->getCaptureChannels();
+
+ m_ListPlaybackURLs->clear();
+ m_PlaybackBufferSizes.clear();
+ m_PlaybackSoundFormats.clear();
+
+ for (unsigned int i = 0; i < playbackChannels.size(); ++i) {
+ SoundFormat sf;
+ size_t buffer_size;
+ TQString url;
+ m_StreamingDevice->getPlaybackStreamOptions(playbackChannels[i], url, sf, buffer_size);
+ m_PlaybackSoundFormats.append(sf);
+ m_PlaybackBufferSizes.append(buffer_size);
+
+ TQListViewItem *item = new TQListViewItem(m_ListPlaybackURLs, m_ListPlaybackURLs->lastChild());
+ item->setText(0, TQString::number(m_ListPlaybackURLs->childCount()));
+ item->setText(1, url);
+ item->setRenameEnabled(1, true);
+ }
+
+ m_ListCaptureURLs->clear();
+ m_CaptureBufferSizes.clear();
+ m_CaptureSoundFormats.clear();
+
+ for (unsigned int i = 0; i < captureChannels.size(); ++i) {
+ SoundFormat sf;
+ size_t buffer_size;
+ TQString url;
+ m_StreamingDevice->getCaptureStreamOptions(captureChannels[i], url, sf, buffer_size);
+ m_CaptureSoundFormats.append(sf);
+ m_CaptureBufferSizes.append(buffer_size);
+
+ TQListViewItem *item = new TQListViewItem(m_ListCaptureURLs, m_ListCaptureURLs->lastChild());
+ item->setText(0, TQString::number(m_ListCaptureURLs->childCount()));
+ item->setText(1, url);
+ item->setRenameEnabled(1, true);
+ }
+ slotPlaybackSelectionChanged();
+ slotCaptureSelectionChanged();
+
+ m_dirty = false;
+}
+
+void StreamingConfiguration::slotUpdateConfig()
+{
+ slotSetDirty();
+ slotCancel();
+}
+
+void StreamingConfiguration::slotNewPlaybackChannel()
+{
+ slotSetDirty();
+ TQListViewItem *item = new TQListViewItem(m_ListPlaybackURLs, m_ListPlaybackURLs->lastChild());
+ item->setText(0, TQString::number(m_ListPlaybackURLs->childCount()));
+ item->setText(1, i18n("new channel"));
+ item->setRenameEnabled(1,true);
+ item->startRename(1);
+
+ m_PlaybackSoundFormats.append(SoundFormat());
+ m_PlaybackBufferSizes.append(64*1024);
+ int n = m_PlaybackSoundFormats.size();
+ setStreamOptions(m_PlaybackSoundFormats[n-1], m_PlaybackBufferSizes[n-1]);
+}
+
+
+void StreamingConfiguration::slotDeletePlaybackChannel()
+{
+ slotSetDirty();
+ TQListViewItem *item = m_ListPlaybackURLs->selectedItem();
+ if (item) {
+ int idx = 0;
+ TQListViewItem *i = m_ListPlaybackURLs->firstChild(),
+ *prev = NULL,
+ *next = item->nextSibling();
+ for (; i && i != item; i = i->nextSibling()) {
+ prev = i;
+ ++idx;
+ }
+ if(next) {
+ m_ListPlaybackURLs->setSelected(next, true);
+ } else if (prev){
+ m_ListPlaybackURLs->setSelected(prev, true);
+ }
+ int x = item->text(0).toUInt();
+ for (i = next; i; i = i->nextSibling(), ++x) {
+ i->setText(0, TQString::number(x));
+ }
+ m_ListPlaybackURLs->takeItem(item);
+ delete item;
+
+ int n = m_PlaybackSoundFormats.size();
+ m_PlaybackSoundFormats.remove(m_PlaybackSoundFormats.at(idx));
+ m_PlaybackBufferSizes .remove(m_PlaybackBufferSizes.at(idx));
+ idx = idx < n - 1 ? idx : n - 1;
+ setStreamOptions( m_PlaybackSoundFormats[idx], m_PlaybackBufferSizes[idx]);
+ slotPlaybackSelectionChanged();
+ }
+}
+
+
+void StreamingConfiguration::slotUpPlaybackChannel()
+{
+ slotSetDirty();
+ TQListViewItem *prev = NULL;
+ TQListViewItem *i = m_ListPlaybackURLs->firstChild();
+ TQListViewItem *item = m_ListPlaybackURLs->selectedItem();
+ int idx = 0;
+ for (; i && i != item; i = i->nextSibling(), ++idx) {
+ prev = i;
+ }
+ if (prev && item) {
+ TQString s = prev->text(1);
+ prev->setText(1, item->text(1));
+ item->setText(1, s);
+ SoundFormat sf = m_PlaybackSoundFormats[idx];
+ m_PlaybackSoundFormats[idx] = m_PlaybackSoundFormats[idx-1];
+ m_PlaybackSoundFormats[idx-1] = sf;
+ size_t size = m_PlaybackBufferSizes[idx];
+ m_PlaybackBufferSizes[idx] = m_PlaybackBufferSizes[idx-1];
+ m_PlaybackBufferSizes[idx-1] = size;
+ m_ListPlaybackURLs->setSelected(prev, true);
+ }
+ m_ListPlaybackURLs->ensureItemVisible(prev);
+}
+
+
+void StreamingConfiguration::slotDownPlaybackChannel()
+{
+ slotSetDirty();
+ TQListViewItem *item = m_ListPlaybackURLs->selectedItem();
+ TQListViewItem *next = item ? item->nextSibling() : NULL;
+ TQListViewItem *i = m_ListPlaybackURLs->firstChild();
+ int idx = 0;
+ for (; i && i != item; i = i->nextSibling()) {
+ ++idx;
+ }
+ if (next && item) {
+ TQString s = next->text(1);
+ next->setText(1, item->text(1));
+ item->setText(1, s);
+ SoundFormat sf = m_PlaybackSoundFormats[idx];
+ m_PlaybackSoundFormats[idx] = m_PlaybackSoundFormats[idx+1];
+ m_PlaybackSoundFormats[idx+1] = sf;
+ size_t size = m_PlaybackBufferSizes[idx];
+ m_PlaybackBufferSizes[idx] = m_PlaybackBufferSizes[idx+1];
+ m_PlaybackBufferSizes[idx+1] = size;
+ m_ListPlaybackURLs->setSelected(next, true);
+ }
+ m_ListPlaybackURLs->ensureItemVisible(next);
+}
+
+
+
+void StreamingConfiguration::slotNewCaptureChannel()
+{
+ slotSetDirty();
+ TQListViewItem *item = new TQListViewItem(m_ListCaptureURLs, m_ListCaptureURLs->lastChild());
+ item->setText(0, TQString::number(m_ListCaptureURLs->childCount()));
+ item->setText(1, i18n("new channel"));
+ item->setRenameEnabled(1,true);
+ item->startRename(1);
+
+ m_CaptureSoundFormats.append(SoundFormat());
+ m_CaptureBufferSizes.append(64*1024);
+ int n = m_CaptureSoundFormats.size();
+ setStreamOptions(m_CaptureSoundFormats[n-1], m_CaptureBufferSizes[n-1]);
+}
+
+
+void StreamingConfiguration::slotDeleteCaptureChannel()
+{
+ slotSetDirty();
+ TQListViewItem *item = m_ListCaptureURLs->selectedItem();
+ if (item) {
+ int idx = 0;
+ TQListViewItem *i = m_ListCaptureURLs->firstChild(),
+ *prev = NULL,
+ *next = item->nextSibling();
+ for (; i && i != item; i = i->nextSibling()) {
+ prev = i;
+ ++idx;
+ }
+ if (next) {
+ m_ListCaptureURLs->setSelected(next, true);
+ } else if (prev){
+ m_ListCaptureURLs->setSelected(prev, true);
+ }
+ int x = item->text(0).toUInt();
+ for (i = next; i; i = i->nextSibling(), ++x) {
+ i->setText(0, TQString::number(x));
+ }
+ m_ListCaptureURLs->takeItem(item);
+ delete item;
+
+ int n = m_CaptureSoundFormats.size();
+ m_CaptureSoundFormats.remove(m_CaptureSoundFormats.at(idx));
+ m_CaptureBufferSizes .remove(m_CaptureBufferSizes.at(idx));
+ idx = idx < n - 1 ? idx : n - 1;
+ setStreamOptions( m_CaptureSoundFormats[idx], m_CaptureBufferSizes[idx]);
+ slotCaptureSelectionChanged();
+ }
+}
+
+
+void StreamingConfiguration::slotUpCaptureChannel()
+{
+ slotSetDirty();
+ TQListViewItem *prev = NULL;
+ TQListViewItem *i = m_ListCaptureURLs->firstChild();
+ TQListViewItem *item = m_ListCaptureURLs->selectedItem();
+ int idx = 0;
+ for (; i && i != item; i = i->nextSibling(), ++idx) {
+ prev = i;
+ }
+ if (prev && item) {
+ TQString s = prev->text(1);
+ prev->setText(1, item->text(1));
+ item->setText(1, s);
+ SoundFormat sf = m_CaptureSoundFormats[idx];
+ m_CaptureSoundFormats[idx] = m_CaptureSoundFormats[idx-1];
+ m_CaptureSoundFormats[idx-1] = sf;
+ size_t size = m_CaptureBufferSizes[idx];
+ m_CaptureBufferSizes[idx] = m_CaptureBufferSizes[idx-1];
+ m_CaptureBufferSizes[idx-1] = size;
+ m_ListCaptureURLs->setSelected(prev, true);
+ }
+ m_ListCaptureURLs->ensureItemVisible(prev);
+}
+
+
+void StreamingConfiguration::slotDownCaptureChannel()
+{
+ slotSetDirty();
+ TQListViewItem *item = m_ListCaptureURLs->selectedItem();
+ TQListViewItem *next = item ? item->nextSibling() : NULL;
+ TQListViewItem *i = m_ListCaptureURLs->firstChild();
+ int idx = 0;
+ for (; i && i != item; i = i->nextSibling()) {
+ ++idx;
+ }
+ if (next && item) {
+ TQString s = next->text(1);
+ next->setText(1, item->text(1));
+ item->setText(1, s);
+ SoundFormat sf = m_CaptureSoundFormats[idx];
+ m_CaptureSoundFormats[idx] = m_CaptureSoundFormats[idx+1];
+ m_CaptureSoundFormats[idx+1] = sf;
+ size_t size = m_CaptureBufferSizes[idx];
+ m_CaptureBufferSizes[idx] = m_CaptureBufferSizes[idx+1];
+ m_CaptureBufferSizes[idx+1] = size;
+ m_ListCaptureURLs->setSelected(next, true);
+ }
+ m_ListCaptureURLs->ensureItemVisible(next);
+}
+
+
+
+
+
+void StreamingConfiguration::slotPlaybackSelectionChanged()
+{
+ TQListViewItem *item = m_ListPlaybackURLs->selectedItem();
+ bool up_possible = false;
+ bool down_possible = false;
+ if (item) {
+ int idx = 0;
+ TQListViewItem *i = m_ListPlaybackURLs->firstChild();
+ for (; i && i != item; i = i->nextSibling()) {
+ ++idx;
+ }
+ up_possible = idx > 0;
+ down_possible = idx < m_ListPlaybackURLs->childCount() - 1;
+ setStreamOptions(m_PlaybackSoundFormats[idx], m_PlaybackBufferSizes[idx]);
+
+ item = m_ListCaptureURLs->selectedItem();
+ if (item)
+ m_ListCaptureURLs->setSelected(item, false);
+ }
+ TQListViewItem *playback_item = m_ListPlaybackURLs->selectedItem();
+ TQListViewItem *capture_item = m_ListCaptureURLs->selectedItem();
+ bool e = (playback_item || capture_item);
+ m_cbFormat ->setEnabled(e);
+ m_cbRate ->setEnabled(e);
+ m_cbBits ->setEnabled(e);
+ m_cbSign ->setEnabled(e);
+ m_cbChannels ->setEnabled(e);
+ m_cbEndianess ->setEnabled(e);
+ m_sbBufferSize->setEnabled(e);
+ m_pbUpPlaybackURL ->setEnabled(up_possible);
+ m_pbDownPlaybackURL->setEnabled(down_possible);
+}
+
+
+void StreamingConfiguration::slotCaptureSelectionChanged()
+{
+ TQListViewItem *item = m_ListCaptureURLs->selectedItem();
+ bool up_possible = false;
+ bool down_possible = false;
+ if (item) {
+ int idx = 0;
+ TQListViewItem *i = m_ListCaptureURLs->firstChild();
+ for (; i && i != item; i = i->nextSibling()) {
+ ++idx;
+ }
+ up_possible = idx > 0;
+ down_possible = idx < m_ListCaptureURLs->childCount() - 1;
+ setStreamOptions(m_CaptureSoundFormats[idx], m_CaptureBufferSizes[idx]);
+
+ item = m_ListPlaybackURLs->selectedItem();
+ if (item)
+ m_ListPlaybackURLs->setSelected(item, false);
+ }
+ TQListViewItem *playback_item = m_ListPlaybackURLs->selectedItem();
+ TQListViewItem *capture_item = m_ListCaptureURLs->selectedItem();
+ bool e = (playback_item || capture_item);
+ m_cbFormat ->setEnabled(e);
+ m_cbRate ->setEnabled(e);
+ m_cbBits ->setEnabled(e);
+ m_cbSign ->setEnabled(e);
+ m_cbChannels ->setEnabled(e);
+ m_cbEndianess ->setEnabled(e);
+ m_sbBufferSize->setEnabled(e);
+ m_pbUpCaptureURL ->setEnabled(up_possible);
+ m_pbDownCaptureURL->setEnabled(down_possible);
+}
+
+void StreamingConfiguration::slotSetDirty()
+{
+ m_dirty = true;
+}
+
+void StreamingConfiguration::slotUpdateSoundFormat()
+{
+ if (m_ignore_updates)
+ return;
+
+ slotSetDirty();
+ TQListViewItem *playback_item = m_ListPlaybackURLs->selectedItem();
+ TQListViewItem *capture_item = m_ListCaptureURLs->selectedItem();
+ if (playback_item) {
+ int idx = 0;
+ TQListViewItem *i = m_ListPlaybackURLs->firstChild();
+ for (; i && i != playback_item; i = i->nextSibling()) {
+ ++idx;
+ }
+ getStreamOptions(m_PlaybackSoundFormats[idx], m_PlaybackBufferSizes[idx]);
+ }
+ else if (capture_item) {
+ int idx = 0;
+ TQListViewItem *i = m_ListCaptureURLs->firstChild();
+ for (; i && i != capture_item; i = i->nextSibling()) {
+ ++idx;
+ }
+ getStreamOptions(m_CaptureSoundFormats[idx], m_CaptureBufferSizes[idx]);
+ }
+}
+
+
+void StreamingConfiguration::setStreamOptions(const SoundFormat &sf, int BufferSize)
+{
+ m_ignore_updates = true;
+
+ int idx_Format = FORMAT_RAW_IDX;
+ int idx_Rate = RATE_44100_IDX;
+ int idx_Bits = BITS_16_IDX;
+ int idx_Sign = SIGN_SIGNED_IDX;
+ int idx_Channels = CHANNELS_STEREO_IDX;
+ int idx_Endianess = ENDIAN_LITTLE_IDX;
+
+ if (sf.m_Encoding == "raw") {
+ idx_Format = FORMAT_RAW_IDX;
+ }
+ else {
+ // ...
+ }
+
+ switch(sf.m_SampleRate) {
+ case 48000 : idx_Rate = RATE_48000_IDX; break;
+ case 44100 : idx_Rate = RATE_44100_IDX; break;
+ case 22050 : idx_Rate = RATE_22050_IDX; break;
+ case 11025 : idx_Rate = RATE_11025_IDX; break;
+ }
+
+ switch(sf.m_SampleBits) {
+ case 8 : idx_Bits = BITS_8_IDX; break;
+ case 16 : idx_Bits = BITS_16_IDX; break;
+ }
+
+ switch(sf.m_IsSigned) {
+ case true : idx_Sign = SIGN_SIGNED_IDX; break;
+ case false : idx_Sign = SIGN_UNSIGNED_IDX; break;
+ }
+
+ switch(sf.m_Channels) {
+ case 2: idx_Channels = CHANNELS_STEREO_IDX; break;
+ case 1: idx_Channels = CHANNELS_MONO_IDX; break;
+ }
+
+ switch(sf.m_Endianess) {
+ case LITTLE_ENDIAN: idx_Endianess = ENDIAN_LITTLE_IDX; break;
+ case BIG_ENDIAN: idx_Endianess = ENDIAN_BIG_IDX; break;
+ }
+
+ m_cbFormat ->setCurrentItem(idx_Format);
+ m_cbRate ->setCurrentItem(idx_Rate);
+ m_cbBits ->setCurrentItem(idx_Bits);
+ m_cbSign ->setCurrentItem(idx_Sign);
+ m_cbChannels ->setCurrentItem(idx_Channels);
+ m_cbEndianess ->setCurrentItem(idx_Endianess);
+ m_sbBufferSize->setValue(BufferSize / 1024);
+
+ m_ignore_updates = false;
+}
+
+
+void StreamingConfiguration::getStreamOptions(SoundFormat &sf, int &BufferSize) const
+{
+ int idx_Format = m_cbFormat ->currentItem();
+ int idx_Rate = m_cbRate ->currentItem();
+ int idx_Bits = m_cbBits ->currentItem();
+ int idx_Sign = m_cbSign ->currentItem();
+ int idx_Channels = m_cbChannels ->currentItem();
+ int idx_Endianess = m_cbEndianess ->currentItem();
+
+ BufferSize = m_sbBufferSize->value() * 1024;
+
+ if (idx_Format == FORMAT_RAW_IDX) {
+ sf.m_Encoding = "raw";
+ }
+ else {
+ // ...
+ }
+
+ switch(idx_Rate) {
+ case RATE_48000_IDX : sf.m_SampleRate = 48000; break;
+ case RATE_44100_IDX : sf.m_SampleRate = 44100; break;
+ case RATE_22050_IDX : sf.m_SampleRate = 22050; break;
+ case RATE_11025_IDX : sf.m_SampleRate = 11025; break;
+ default : sf.m_SampleRate = 44100; break;
+ }
+
+ switch(idx_Bits) {
+ case BITS_8_IDX : sf.m_SampleBits = 8; break;
+ case BITS_16_IDX : sf.m_SampleBits = 16; break;
+ default : sf.m_SampleBits = 16; break;
+ }
+
+ switch(idx_Sign) {
+ case SIGN_SIGNED_IDX : sf.m_IsSigned = true; break;
+ case SIGN_UNSIGNED_IDX : sf.m_IsSigned = false; break;
+ default : sf.m_IsSigned = true; break;
+ }
+
+ switch(idx_Channels) {
+ case CHANNELS_STEREO_IDX : sf.m_Channels = 2; break;
+ case CHANNELS_MONO_IDX : sf.m_Channels = 1; break;
+ default : sf.m_Channels = 2; break;
+ }
+
+ switch(idx_Endianess) {
+ case ENDIAN_LITTLE_IDX : sf.m_Endianess = LITTLE_ENDIAN; break;
+ case ENDIAN_BIG_IDX : sf.m_Endianess = BIG_ENDIAN; break;
+ default : sf.m_Endianess = BYTE_ORDER; break;
+ }
+}
+
+#include "streaming-configuration.moc"
diff --git a/plugins/streaming/streaming-configuration.h b/plugins/streaming/streaming-configuration.h
new file mode 100644
index 0000000..c352f6a
--- /dev/null
+++ b/plugins/streaming/streaming-configuration.h
@@ -0,0 +1,98 @@
+/***************************************************************************
+ 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_STREAMING_CONFIGURATION_H
+#define KRADIO_STREAMING_CONFIGURATION_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "streaming-configuration-ui.h"
+#include "streaming.h"
+
+
+
+#define RATE_48000_IDX 0
+#define RATE_44100_IDX 1
+#define RATE_22050_IDX 2
+#define RATE_11025_IDX 3
+
+#define CHANNELS_STEREO_IDX 0
+#define CHANNELS_MONO_IDX 1
+
+#define SIGN_SIGNED_IDX 0
+#define SIGN_UNSIGNED_IDX 1
+
+#define BITS_16_IDX 0
+#define BITS_8_IDX 1
+
+#define ENDIAN_LITTLE_IDX 0
+#define ENDIAN_BIG_IDX 1
+
+#define FORMAT_RAW_IDX 0
+
+
+class StreamingConfiguration : public StreamingConfigurationUI
+{
+Q_OBJECT
+
+public :
+ StreamingConfiguration (TQWidget *parent, StreamingDevice *streamer);
+ ~StreamingConfiguration ();
+
+protected slots:
+
+ void slotOK();
+ void slotCancel();
+
+ void slotUpdateConfig();
+
+
+
+ void slotNewPlaybackChannel();
+ void slotDeletePlaybackChannel();
+ void slotUpPlaybackChannel();
+ void slotDownPlaybackChannel();
+
+ void slotNewCaptureChannel();
+ void slotDeleteCaptureChannel();
+ void slotUpCaptureChannel();
+ void slotDownCaptureChannel();
+
+ void slotPlaybackSelectionChanged();
+ void slotCaptureSelectionChanged();
+
+ void slotUpdateSoundFormat();
+ void slotSetDirty();
+
+protected:
+
+ void setStreamOptions(const SoundFormat &sf, int BufferSize);
+ void getStreamOptions(SoundFormat &sf, int &BufferSize) const ;
+
+
+ TQValueList<SoundFormat> m_PlaybackSoundFormats, m_CaptureSoundFormats;
+ TQValueList<int> m_PlaybackBufferSizes, m_CaptureBufferSizes;
+
+ bool m_ignore_updates;
+ bool m_dirty;
+ StreamingDevice *m_StreamingDevice;
+
+};
+
+#endif
diff --git a/plugins/streaming/streaming-job.cpp b/plugins/streaming/streaming-job.cpp
new file mode 100644
index 0000000..3318567
--- /dev/null
+++ b/plugins/streaming/streaming-job.cpp
@@ -0,0 +1,279 @@
+/***************************************************************************
+ streaming-job.cpp - description
+ -------------------
+ begin : Sun Sept 3 2006
+ copyright : (C) 2006 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 "streaming-job.h"
+
+#include "../../src/include/utils.h"
+#include <kurl.h>
+
+#include <tdeio/job.h>
+
+
+StreamingJob::StreamingJob()
+ : TQObject(),
+ m_URL(TQString()),
+ m_SoundFormat(),
+ m_BufferSize(65536),
+ m_Buffer(m_BufferSize),
+ m_OpenCounter(0),
+ m_StreamPos(0),
+ m_StartTime(0),
+ m_SkipCount(0),
+ m_TDEIO_Job(NULL),
+ m_capturing(false)
+{
+}
+
+StreamingJob::StreamingJob(const TQString &_URL, const SoundFormat &_SoundFormat, size_t _bufferSize)
+ : TQObject(),
+ m_URL(_URL),
+ m_SoundFormat(_SoundFormat),
+ m_BufferSize(_bufferSize),
+ m_Buffer(m_BufferSize),
+ m_OpenCounter(0),
+ m_StreamPos(0),
+ m_StartTime(0),
+ m_SkipCount(0),
+ m_TDEIO_Job(NULL),
+ m_capturing(false)
+{
+}
+
+StreamingJob::StreamingJob(const StreamingJob &c)
+ : TQObject(),
+ m_URL(c.m_URL),
+ m_SoundFormat(c.m_SoundFormat),
+ m_BufferSize(c.m_BufferSize),
+ m_Buffer(m_BufferSize),
+ m_OpenCounter(0),
+ m_StreamPos(0),
+ m_StartTime(0),
+ m_SkipCount(0),
+ m_TDEIO_Job(NULL),
+ m_capturing(c.m_capturing)
+{
+}
+
+StreamingJob::~StreamingJob()
+{
+}
+
+
+void StreamingJob::setURL(const TQString &url)
+{
+ if (m_URL != url) {
+ m_URL = url;
+ delete m_TDEIO_Job;
+ m_TDEIO_Job = NULL;
+ if (!m_capturing) {
+ startPutJob();
+ } else {
+ startGetJob();
+ }
+ }
+}
+
+
+void StreamingJob::setSoundFormat(const SoundFormat &sf)
+{
+ m_SoundFormat = sf;
+}
+
+
+void StreamingJob::setBufferSize(size_t buffer_size)
+{
+ if (m_BufferSize != buffer_size) {
+ m_Buffer.clear();
+ m_Buffer.resize(m_BufferSize = buffer_size);
+ }
+}
+
+
+bool StreamingJob::startPutJob()
+{
+ m_TDEIO_Job = TDEIO::put(m_URL, -1, true, false, false);
+ if (!m_TDEIO_Job)
+ return false;
+ m_TDEIO_Job->setAsyncDataEnabled(true);
+ connect (m_TDEIO_Job, TQT_SIGNAL(dataReq(TDEIO::Job *job, TQByteArray &data)),
+ this, TQT_SLOT(slotWriteData (TDEIO::Job *job, TQByteArray &data)));
+ connect (m_TDEIO_Job, TQT_SIGNAL(result(TDEIO::Job *)),
+ this, TQT_SLOT(slotIOJobResult(TDEIO::Job *)));
+ return true;
+}
+
+
+bool StreamingJob::startPlayback()
+{
+ if (!m_OpenCounter) {
+ m_Buffer.clear();
+ m_OpenCounter = 1;
+ if (!startPutJob())
+ return false;
+ m_StartTime = time(NULL);
+ m_StreamPos = 0;
+ if (m_TDEIO_Job->error()) {
+ emit logStreamError(m_URL, m_TDEIO_Job->errorString());
+ }
+ return m_TDEIO_Job->error() == 0;
+ }
+ else {
+ return true;
+ }
+}
+
+bool StreamingJob::stopPlayback()
+{
+ if (m_OpenCounter) {
+ if (!--m_OpenCounter) {
+ delete m_TDEIO_Job;
+ m_TDEIO_Job = NULL;
+ }
+ }
+ return true;
+}
+
+
+bool StreamingJob::startGetJob()
+{
+ m_TDEIO_Job = TDEIO::get(m_URL, false, false);
+ if (!m_TDEIO_Job)
+ return false;
+ m_TDEIO_Job->setAsyncDataEnabled(true);
+ connect (m_TDEIO_Job, TQT_SIGNAL(data(TDEIO::Job *, const TQByteArray &)),
+ this, TQT_SLOT(slotReadData(TDEIO::Job *, const TQByteArray &)));
+ connect (m_TDEIO_Job, TQT_SIGNAL(result(TDEIO::Job *)),
+ this, TQT_SLOT(slotIOJobResult(TDEIO::Job *)));
+ return true;
+}
+
+
+bool StreamingJob::startCapture(const SoundFormat &/*proposed_format*/,
+ SoundFormat &real_format,
+ bool /*force_format*/)
+{
+ if (!m_OpenCounter) {
+ m_capturing = true;
+ m_Buffer.clear();
+ if (!startGetJob())
+ return false;
+ m_StartTime = time(NULL);
+ m_StreamPos = 0;
+ if (m_TDEIO_Job->error()) {
+ emit logStreamError(m_URL, m_TDEIO_Job->errorString());
+ }
+ return m_TDEIO_Job->error() == 0;
+ }
+ ++m_OpenCounter;
+ real_format = m_SoundFormat;
+ return true;
+}
+
+
+bool StreamingJob::stopCapture()
+{
+ if (m_OpenCounter) {
+ if (!--m_OpenCounter) {
+ delete m_TDEIO_Job;
+ m_TDEIO_Job = NULL;
+ }
+ }
+ return true;
+}
+
+
+void StreamingJob::slotReadData (TDEIO::Job */*job*/, const TQByteArray &data)
+{
+ size_t free = m_Buffer.getFreeSize();
+ if (free < data.size()) {
+ m_SkipCount += data.size() - free;
+ emit logStreamWarning(m_URL, i18n("skipped %1 bytes").arg(data.size() - free));
+ }
+ else {
+ free = data.size();
+ }
+
+ m_Buffer.addData(data.data(), free);
+ m_StreamPos += free;
+
+ if (m_Buffer.getFreeSize() < data.size()) {
+ m_TDEIO_Job->suspend();
+ }
+}
+
+
+void StreamingJob::slotWriteData (TDEIO::Job */*job*/, TQByteArray &)
+{
+ size_t size = m_Buffer.getFillSize();
+ if (size) {
+ char *buf = new char [size];
+ size = m_Buffer.takeData(buf, size);
+ TQByteArray data;
+ data.assign(buf, size);
+ m_TDEIO_Job->sendAsyncData(data);
+ m_StreamPos += size;
+ }
+ else {
+ // does a warning really make sense here?
+ //emit logStreamWarning(m_URL, i18n("buffer underrun"));
+ m_SkipCount++;
+ }
+}
+
+
+void StreamingJob::playData(const char *data, size_t size, size_t &consumed_size)
+{
+ size_t free = m_Buffer.getFreeSize();
+ consumed_size = (consumed_size == SIZE_T_DONT_CARE) ? free : min(consumed_size, free);
+ if (free > size) {
+ free = size;
+ }
+ m_Buffer.addData(data, free);
+}
+
+
+bool StreamingJob::hasRecordedData() const
+{
+ return m_Buffer.getFillSize() > m_Buffer.getSize() / 3;
+}
+
+
+void StreamingJob::lockData(const char *&data, size_t &size, SoundMetaData &meta_data)
+{
+ data = m_Buffer.getData(size);
+ time_t cur_time = time(NULL);
+ meta_data = SoundMetaData(m_StreamPos, cur_time - m_StartTime, cur_time, m_URL);
+}
+
+
+void StreamingJob::removeData(size_t size)
+{
+ m_Buffer.removeData(size);
+ if (m_Buffer.getFreeSize() > m_Buffer.getSize() / 2) {
+ m_TDEIO_Job->resume();
+ }
+}
+
+void StreamingJob::slotIOJobResult (TDEIO::Job *job)
+{
+ if (job && job->error()) {
+ emit logStreamError(m_URL, job->errorString());
+ }
+}
+
+#include "streaming-job.moc"
+
diff --git a/plugins/streaming/streaming-job.h b/plugins/streaming/streaming-job.h
new file mode 100644
index 0000000..a8afe48
--- /dev/null
+++ b/plugins/streaming/streaming-job.h
@@ -0,0 +1,101 @@
+/***************************************************************************
+ streaming-job.h - description
+ -------------------
+ begin : Sun Sept 3 2006
+ copyright : (C) 2006 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_STREAMING_JOB_H
+#define _KRADIO_STREAMING_JOB_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/ringbuffer.h"
+#include "../../src/include/soundformat.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+
+#include <tqobject.h>
+
+#include <tdeio/jobclasses.h>
+
+class StreamingJob : public TQObject
+{
+Q_OBJECT
+
+public:
+ StreamingJob();
+ StreamingJob(const TQString &_URL, const SoundFormat &_SoundFormat, size_t _bufferSize);
+ StreamingJob(const StreamingJob &c);
+
+ virtual ~StreamingJob();
+
+ const TQString &getURL() const { return m_URL; }
+ const SoundFormat &getSoundFormat() const { return m_SoundFormat; }
+ int getBufferSize() const { return m_BufferSize; }
+
+ void setURL(const TQString &);
+ void setSoundFormat(const SoundFormat &);
+ void setBufferSize(size_t buffer_size);
+
+ bool startPlayback();
+ bool stopPlayback();
+
+ bool startCapture(const SoundFormat &proposed_format,
+ SoundFormat &real_format,
+ bool force_format);
+ bool stopCapture();
+
+
+ void playData(const char *data, size_t size, size_t &consumed_size);
+ bool hasRecordedData() const;
+ void lockData(const char *&data, size_t &size, SoundMetaData &meta_data);
+ void removeData(size_t);
+
+protected slots:
+
+ void slotReadData (TDEIO::Job *job, const TQByteArray &data);
+ void slotWriteData (TDEIO::Job *job, TQByteArray &data);
+ void slotIOJobResult (TDEIO::Job *job);
+
+signals:
+
+ void logStreamError(const KURL &url, const TQString &s);
+ void logStreamWarning(const KURL &url, const TQString &s);
+
+protected:
+
+ bool startGetJob();
+ bool startPutJob();
+
+
+ TQString m_URL;
+ SoundFormat m_SoundFormat;
+
+ size_t m_BufferSize;
+ RingBuffer m_Buffer;
+
+ unsigned m_OpenCounter;
+ TQ_UINT64 m_StreamPos;
+ time_t m_StartTime;
+
+ size_t m_SkipCount;
+
+ TDEIO::TransferJob *m_TDEIO_Job;
+ bool m_capturing;
+};
+
+
+
+#endif
diff --git a/plugins/streaming/streaming.cpp b/plugins/streaming/streaming.cpp
new file mode 100644
index 0000000..fcbc0cb
--- /dev/null
+++ b/plugins/streaming/streaming.cpp
@@ -0,0 +1,526 @@
+/***************************************************************************
+ streaming.cpp - description
+ -------------------
+ begin : Sun Sept 3 2006
+ copyright : (C) 2006 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 "streaming.h"
+
+#include "../../src/include/aboutwidget.h"
+#include "../../src/include/utils.h"
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kurl.h>
+#include <tdelocale.h>
+
+#include "streaming-job.h"
+#include "streaming-configuration.h"
+
+///////////////////////////////////////////////////////////////////////
+//// plugin library functions
+
+PLUGIN_LIBRARY_FUNCTIONS(StreamingDevice, "tderadio-streaming", i18n("Streaming Support"));
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+
+StreamingDevice::StreamingDevice(const TQString &name)
+ : TQObject(NULL, NULL),
+ PluginBase(name, i18n("TDERadio Streaming Plugin"))
+{
+ m_CaptureChannels.setAutoDelete(true);
+ m_PlaybackChannels.setAutoDelete(true);
+}
+
+
+StreamingDevice::~StreamingDevice()
+{
+ resetPlaybackStreams();
+ resetCaptureStreams();
+}
+
+
+bool StreamingDevice::connectI(Interface *i)
+{
+ bool a = PluginBase::connectI(i);
+ bool b = ISoundStreamClient::connectI(i);
+ return a || b;
+}
+
+
+bool StreamingDevice::disconnectI(Interface *i)
+{
+ bool a = PluginBase::disconnectI(i);
+ bool b = ISoundStreamClient::disconnectI(i);
+ return a || b;
+}
+
+void StreamingDevice::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_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);
+ s->register4_notifyReadyForPlaybackData(this);
+ }
+}
+
+// PluginBase
+
+void StreamingDevice::saveState (TDEConfig *c) const
+{
+ c->setGroup(TQString("streaming-") + PluginBase::name());
+ c->writeEntry("soundstreamclient-id", m_SoundStreamClientID);
+
+ c->writeEntry("playback-channels", m_PlaybackChannelList.size());
+ for (unsigned int i = 0; i < m_PlaybackChannelList.size(); ++i) {
+ TQString s = m_PlaybackChannelList[i];
+ const StreamingJob *j = m_PlaybackChannels[s];
+
+ const SoundFormat &sf = j->getSoundFormat();
+ KURL url = j->getURL();
+ size_t buffer_size = j->getBufferSize();
+
+ sf.saveConfig("playback-channel-" + TQString::number(i), c);
+ c->writeEntry("playback-channel-" + TQString::number(i) + "-url", url.url());
+ c->writeEntry("playback-channel-" + TQString::number(i) + "-buffer-size", buffer_size);
+ }
+
+ c->writeEntry("capture-channels", m_CaptureChannelList.size());
+ for (unsigned int i = 0; i < m_CaptureChannelList.size(); ++i) {
+ TQString s = m_CaptureChannelList[i];
+ const StreamingJob *j = m_CaptureChannels[s];
+
+ const SoundFormat &sf = j->getSoundFormat();
+ KURL url = j->getURL();
+ size_t buffer_size = j->getBufferSize();
+
+ sf.saveConfig("capture-channel-" + TQString::number(i), c);
+ c->writeEntry("capture-channel-" + TQString::number(i) + "-url", url.url());
+ c->writeEntry("capture-channel-" + TQString::number(i) + "-buffer-size", buffer_size);
+ }
+}
+
+void StreamingDevice::restoreState (TDEConfig *c)
+{
+ c->setGroup(TQString("streaming-") + PluginBase::name());
+ setSoundStreamClientID(c->readEntry("soundstreamclient-id", getSoundStreamClientID()));
+
+ resetPlaybackStreams(false);
+ resetCaptureStreams(false);
+
+ int n = c->readNumEntry("playback-channels", 0);
+ for (int i = 0; i < n; ++i) {
+ SoundFormat sf;
+ sf.restoreConfig("playback-channel-" + TQString::number(i), c);
+ TQString url = c->readEntry("playback-channel-" + TQString::number(i) + "-url", TQString());
+ size_t buffer_size = c->readNum64Entry("playback-channel-" + TQString::number(i) + "-buffer-size", 32*1024);
+
+ if (!url.isNull()) {
+ addPlaybackStream(url, sf, buffer_size, i == n-1);
+ }
+ }
+
+ n = c->readNumEntry("capture-channels", 0);
+ for (int i = 0; i < n; ++i) {
+ SoundFormat sf;
+ sf.restoreConfig("capture-channel-" + TQString::number(i), c);
+ TQString url = c->readEntry("capture-channel-" + TQString::number(i) + "-url", TQString());
+ size_t buffer_size = c->readNum64Entry("capture-channel-" + TQString::number(i) + "-buffer-size", 32*1024);
+
+ if (!url.isNull()) {
+ addCaptureStream(url, sf, buffer_size, i == n-1);
+ }
+ }
+
+ if (!m_CaptureChannelList.size()) {
+ addCaptureStream("/dev/video24", SoundFormat(48000, 2, 16, true, BYTE_ORDER, "raw"), 65536);
+ }
+
+ emit sigUpdateConfig();
+}
+
+
+ConfigPageInfo StreamingDevice::createConfigurationPage()
+{
+ StreamingConfiguration *conf = new StreamingConfiguration(NULL, this);
+ TQObject::connect(this, TQT_SIGNAL(sigUpdateConfig()), conf, TQT_SLOT(slotUpdateConfig()));
+ return ConfigPageInfo (conf,
+ i18n("Streaming"),
+ i18n("Streaming Device Options"),
+ "tderadio_streaming");
+}
+
+
+AboutPageInfo StreamingDevice::createAboutPage()
+{
+ return AboutPageInfo();
+}
+
+
+
+bool StreamingDevice::preparePlayback(SoundStreamID id, const TQString &channel, bool /*active_mode*/, bool start_immediately)
+{
+ if (id.isValid() && m_PlaybackChannels.find(channel)) {
+ m_AllPlaybackStreams.insert(id, channel);
+ if (start_immediately)
+ startPlayback(id);
+ return true;
+ }
+ return false;
+}
+
+
+bool StreamingDevice::prepareCapture(SoundStreamID id, const TQString &channel)
+{
+ logDebug("StreamingDevice::prepareCapture");
+ if (id.isValid() && m_CaptureChannels.find(channel)) {
+ m_AllCaptureStreams.insert(id, channel);
+ return true;
+ }
+ return false;
+}
+
+bool StreamingDevice::releasePlayback(SoundStreamID id)
+{
+ if (id.isValid() && m_AllPlaybackStreams.contains(id)) {
+ stopPlayback(id);
+ if (!m_EnabledPlaybackStreams.contains(id))
+ m_AllPlaybackStreams.remove(id);
+ return true;
+ }
+ return false;
+}
+
+bool StreamingDevice::releaseCapture(SoundStreamID id)
+{
+ logDebug("StreamingDevice::releaseCapture");
+ if (id.isValid() && m_AllCaptureStreams.contains(id)) {
+ stopCapture(id);
+ if (!m_EnabledCaptureStreams.contains(id))
+ m_AllCaptureStreams.remove(id);
+ return true;
+ }
+ return false;
+}
+
+bool StreamingDevice::supportsPlayback() const
+{
+ return m_PlaybackChannels.size() > 0;
+}
+
+
+bool StreamingDevice::supportsCapture() const
+{
+ return m_CaptureChannels.size() > 0;
+}
+
+
+bool StreamingDevice::startPlayback(SoundStreamID id)
+{
+ if (id.isValid() && m_AllPlaybackStreams.contains(id)) {
+ m_EnabledPlaybackStreams.insert(id, m_AllPlaybackStreams[id]);
+ StreamingJob &x = *m_PlaybackChannels.find(m_AllPlaybackStreams[id]);
+ x.startPlayback();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool StreamingDevice::pausePlayback(SoundStreamID /*id*/)
+{
+ //return stopPlayback(id);
+ return false;
+}
+
+
+bool StreamingDevice::stopPlayback(SoundStreamID id)
+{
+ if (id.isValid() && m_EnabledPlaybackStreams.contains(id)) {
+ StreamingJob &x = *m_PlaybackChannels.find(m_AllPlaybackStreams[id]);
+ if (x.stopPlayback()) {
+ m_EnabledPlaybackStreams.remove(id);
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool StreamingDevice::isPlaybackRunning(SoundStreamID id, bool &b) const
+{
+ if (id.isValid() && m_EnabledPlaybackStreams.contains(id)) {
+ b = true;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool StreamingDevice::startCaptureWithFormat(SoundStreamID id,
+ const SoundFormat &proposed_format,
+ SoundFormat &real_format,
+ bool force_format)
+{
+ logDebug("StreamingDevice::startCaptureWithFormat");
+ if (id.isValid() && m_AllCaptureStreams.contains(id)) {
+ m_EnabledCaptureStreams.insert(id, m_AllCaptureStreams[id]);
+ StreamingJob &x = *m_CaptureChannels.find(m_AllCaptureStreams[id]);
+ x.startCapture(proposed_format, real_format, force_format);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool StreamingDevice::stopCapture(SoundStreamID id)
+{
+ if (id.isValid() && m_EnabledCaptureStreams.contains(id)) {
+ StreamingJob &x = *m_CaptureChannels.find(m_AllCaptureStreams[id]);
+ if (x.stopCapture()) {
+ m_EnabledCaptureStreams.remove(id);
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool StreamingDevice::isCaptureRunning(SoundStreamID id, bool &b, SoundFormat &sf) const
+{
+ if (id.isValid() && m_EnabledCaptureStreams.contains(id)) {
+ StreamingJob &x = *m_CaptureChannels.find(m_AllCaptureStreams[id]);
+ sf = x.getSoundFormat();
+ b = true;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool StreamingDevice::noticeSoundStreamClosed(SoundStreamID id)
+{
+ bool found = (stopCapture(id) && releaseCapture(id)) ||
+ (stopPlayback(id) && releasePlayback(id));
+ return found;
+}
+
+
+bool StreamingDevice::noticeSoundStreamRedirected(SoundStreamID oldID, SoundStreamID newID)
+{
+ bool found = false;
+ if (newID != oldID) {
+ if (m_AllPlaybackStreams.contains(oldID)) {
+ m_AllPlaybackStreams.insert(newID, m_AllPlaybackStreams[oldID]);
+ m_AllPlaybackStreams.remove(oldID);
+ found = true;
+ }
+ if (m_EnabledPlaybackStreams.contains(oldID)) {
+ m_EnabledPlaybackStreams.insert(newID, m_EnabledPlaybackStreams[oldID]);
+ m_EnabledPlaybackStreams.remove(oldID);
+ found = true;
+ }
+ if (m_AllCaptureStreams.contains(oldID)) {
+ m_AllCaptureStreams.insert(newID, m_AllCaptureStreams[oldID]);
+ m_AllCaptureStreams.remove(oldID);
+ found = true;
+ }
+ if (m_EnabledCaptureStreams.contains(oldID)) {
+ m_EnabledCaptureStreams.insert(newID, m_EnabledCaptureStreams[oldID]);
+ m_EnabledCaptureStreams.remove(oldID);
+ found = true;
+ }
+ }
+ return found;
+}
+
+
+bool StreamingDevice::noticeSoundStreamData(SoundStreamID id,
+ const SoundFormat &/*format*/,
+ const char *data, size_t size, size_t &consumed_size,
+ const SoundMetaData &/*md*/
+ )
+{
+ if (id.isValid() && m_EnabledPlaybackStreams.contains(id)) {
+ StreamingJob &x = *m_CaptureChannels.find(m_AllCaptureStreams[id]);
+ x.playData(data, size, consumed_size);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+bool StreamingDevice::noticeReadyForPlaybackData(SoundStreamID id, size_t free_size)
+{
+ if (!id.isValid() || !m_AllCaptureStreams.contains(id))
+ return false;
+ StreamingJob &x = *m_CaptureChannels.find(m_AllCaptureStreams[id]);
+
+ while (x.hasRecordedData() && free_size > 0) {
+ const char *buffer = NULL;
+ size_t size = SIZE_T_DONT_CARE;
+ size_t consumed_size = SIZE_T_DONT_CARE;
+ SoundMetaData meta_data(0,0,0, i18n("internal stream, not stored (%1)").arg(m_AllCaptureStreams[id]));
+ x.lockData(buffer, size, meta_data); // get pointer to data and meta-data content
+ if (size > free_size)
+ size = free_size;
+ notifySoundStreamData(id, x.getSoundFormat(), buffer, size, consumed_size, meta_data);
+ if (consumed_size == SIZE_T_DONT_CARE)
+ consumed_size = size;
+ x.removeData(consumed_size);
+ free_size -= consumed_size;
+ if (consumed_size < size) {
+ logWarning(i18n("StreamingDevice %1::notifySoundStreamData: Playback Clients skipped %2 bytes").arg(name()).arg(size-consumed_size));
+ break;
+ }
+ }
+ return true;
+}
+
+
+
+const TQStringList &StreamingDevice::getPlaybackChannels() const
+{
+ return m_PlaybackChannelList;
+}
+
+
+const TQStringList &StreamingDevice::getCaptureChannels() const
+{
+ return m_CaptureChannelList;
+}
+
+
+TQString StreamingDevice::getSoundStreamClientDescription() const
+{
+ return i18n("Streaming Device %1").arg(PluginBase::name());
+}
+
+
+void StreamingDevice::logStreamError(const KURL &url, const TQString &s)
+{
+ logError(i18n("Streaming Device %1, %2: %3").arg(name()).arg(url.url()).arg(s));
+}
+
+void StreamingDevice::logStreamWarning(const KURL &url, const TQString &s)
+{
+ logWarning(i18n("Streaming Device %1, %2: %3").arg(name()).arg(url.url()).arg(s));
+}
+
+
+bool StreamingDevice::getPlaybackStreamOptions(const TQString &channel, TQString &url, SoundFormat &sf, size_t &buffer_size) const
+{
+ if (m_PlaybackChannels.find(channel)) {
+ const StreamingJob *j = m_PlaybackChannels[channel];
+ url = j->getURL();
+ sf = j->getSoundFormat();
+ buffer_size = j->getBufferSize();
+ return true;
+ }
+ return false;
+}
+
+
+bool StreamingDevice::getCaptureStreamOptions(const TQString &channel, TQString &url, SoundFormat &sf, size_t &buffer_size) const
+{
+ if (m_CaptureChannels.find(channel)) {
+ const StreamingJob *j = m_CaptureChannels[channel];
+ url = j->getURL();
+ sf = j->getSoundFormat();
+ buffer_size = j->getBufferSize();
+ return true;
+ }
+ return false;
+}
+
+void StreamingDevice::resetPlaybackStreams(bool notification_enabled)
+{
+ while (m_EnabledPlaybackStreams.begin() != m_EnabledPlaybackStreams.end()) {
+ sendStopPlayback(m_EnabledPlaybackStreams.begin().key());
+ }
+ while (m_AllPlaybackStreams.begin() != m_AllPlaybackStreams.end()) {
+ releasePlayback(m_AllPlaybackStreams.begin().key());
+ }
+ m_PlaybackChannelList.clear();
+ m_PlaybackChannels.clear();
+ if (notification_enabled) {
+ notifyPlaybackChannelsChanged(m_SoundStreamClientID, m_PlaybackChannelList);
+ }
+}
+
+
+void StreamingDevice::resetCaptureStreams(bool notification_enabled)
+{
+ while (m_EnabledCaptureStreams.begin() != m_EnabledCaptureStreams.end()) {
+ sendStopCapture(m_EnabledCaptureStreams.begin().key());
+ }
+ while (m_AllCaptureStreams.begin() != m_AllCaptureStreams.end()) {
+ releaseCapture(m_AllCaptureStreams.begin().key());
+ }
+ m_CaptureChannelList.clear();
+ m_CaptureChannels.clear();
+ if (notification_enabled) {
+ notifyCaptureChannelsChanged(m_SoundStreamClientID, m_CaptureChannelList);
+ }
+}
+
+
+void StreamingDevice::addPlaybackStream(const TQString &url, const SoundFormat &sf, size_t buffer_size, bool notification_enabled)
+{
+ StreamingJob *x = new StreamingJob(url, sf, buffer_size);
+ connect(x, TQT_SIGNAL(logStreamError(const KURL &, const TQString &)),
+ this, TQT_SLOT (logStreamError(const KURL &, const TQString &)));
+
+ m_PlaybackChannelList.append(url);
+ m_PlaybackChannels.insert(url, x);
+ if (notification_enabled) {
+ notifyPlaybackChannelsChanged(m_SoundStreamClientID, m_PlaybackChannelList);
+ }
+}
+
+
+void StreamingDevice::addCaptureStream (const TQString &url, const SoundFormat &sf, size_t buffer_size, bool notification_enabled)
+{
+ StreamingJob *x = new StreamingJob(url, sf, buffer_size);
+ connect(x, TQT_SIGNAL(logStreamError(const KURL &, const TQString &)),
+ this, TQT_SLOT (logStreamError(const KURL &, const TQString &)));
+
+ m_CaptureChannelList.append(url);
+ m_CaptureChannels.insert(url, x);
+ if (notification_enabled) {
+ notifyCaptureChannelsChanged(m_SoundStreamClientID, m_CaptureChannelList);
+ }
+}
+
+
+#include "streaming.moc"
diff --git a/plugins/streaming/streaming.h b/plugins/streaming/streaming.h
new file mode 100644
index 0000000..df55ff8
--- /dev/null
+++ b/plugins/streaming/streaming.h
@@ -0,0 +1,146 @@
+/***************************************************************************
+ streaming.h - description
+ -------------------
+ begin : Sun Sept 3 2006
+ copyright : (C) 2006 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_STREAMING_H
+#define _KRADIO_STREAMING_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/plugins.h"
+#include "../../src/include/soundformat.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+
+#include <tqobject.h>
+#include <tqdict.h>
+
+class StreamingJob;
+
+class StreamingDevice : public TQObject,
+ public PluginBase,
+ public ISoundStreamClient
+{
+Q_OBJECT
+
+
+public:
+ StreamingDevice (const TQString &name);
+ virtual ~StreamingDevice ();
+
+ virtual bool connectI(Interface *i);
+ virtual bool disconnectI(Interface *i);
+
+ bool getPlaybackStreamOptions(const TQString &channel, TQString &url, SoundFormat &sf, size_t &buffer_size) const;
+ bool getCaptureStreamOptions (const TQString &channel, TQString &url, SoundFormat &sf, size_t &buffer_size) const;
+
+ void resetPlaybackStreams(bool notification_enabled = true);
+ void resetCaptureStreams(bool notification_enabled = true);
+ void addPlaybackStream(const TQString &url, const SoundFormat &sf, size_t buffer_size, bool notification_enabled = true);
+ void addCaptureStream (const TQString &url, const SoundFormat &sf, size_t buffer_size, bool notification_enabled = true);
+
+ // PluginBase
+
+public:
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+ virtual TQString pluginClassName() const { return "StreamingDevice"; }
+
+ 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:
+
+ANSWERS:
+ const TQStringList &getPlaybackChannels() const;
+ const TQStringList &getCaptureChannels() 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 noticeReadyForPlaybackData(SoundStreamID id, size_t size);
+
+ bool noticeSoundStreamData(SoundStreamID id,
+ const SoundFormat &,
+ const char *data, size_t size, size_t &consumed_size,
+ const SoundMetaData &md
+ );
+
+public slots:
+
+ void logStreamError(const KURL &url, const TQString &s);
+ void logStreamWarning(const KURL &url, const TQString &s);
+
+signals:
+
+ void sigUpdateConfig();
+
+protected:
+
+ TQStringList m_PlaybackChannelList,
+ m_CaptureChannelList;
+
+ TQDict<StreamingJob>
+ m_PlaybackChannels,
+ m_CaptureChannels;
+
+ TQMap<SoundStreamID, TQString>
+ m_AllPlaybackStreams,
+ m_AllCaptureStreams,
+ m_EnabledPlaybackStreams,
+ m_EnabledCaptureStreams;
+};
+
+
+
+#endif
diff --git a/plugins/timecontrol/CMakeL10n.txt b/plugins/timecontrol/CMakeL10n.txt
new file mode 100644
index 0000000..1b6cf40
--- /dev/null
+++ b/plugins/timecontrol/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-timecontrol"
+ DESTINATION "po"
+)
diff --git a/plugins/timecontrol/Makefile.am b/plugins/timecontrol/Makefile.am
new file mode 100644
index 0000000..edcda42
--- /dev/null
+++ b/plugins/timecontrol/Makefile.am
@@ -0,0 +1,17 @@
+SUBDIRS = po icons .
+
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = libtimecontrol.la
+libtimecontrol_la_SOURCES = timecontrol-configuration.cpp \
+ timecontrol-configuration-ui.ui timecontrol.cpp
+libtimecontrol_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+noinst_HEADERS = timecontrol-configuration.h timecontrol.h
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-timecontrol.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-timecontrol.pot
diff --git a/plugins/timecontrol/icons/Makefile.am b/plugins/timecontrol/icons/Makefile.am
new file mode 100644
index 0000000..a594625
--- /dev/null
+++ b/plugins/timecontrol/icons/Makefile.am
@@ -0,0 +1,7 @@
+#icons_ICON = tderadio_*
+#iconsdir = $(datadir)/icons
+
+KDE_ICON = tderadio_zzz
+
+icons_ICON = tderadio_kalarm tderadio_zzz
+iconsdir = $(datadir)/icons
diff --git a/plugins/timecontrol/icons/hi16-action-tderadio_kalarm.png b/plugins/timecontrol/icons/hi16-action-tderadio_kalarm.png
new file mode 100644
index 0000000..3009d55
--- /dev/null
+++ b/plugins/timecontrol/icons/hi16-action-tderadio_kalarm.png
Binary files differ
diff --git a/plugins/timecontrol/icons/hi16-action-tderadio_zzz.png b/plugins/timecontrol/icons/hi16-action-tderadio_zzz.png
new file mode 100644
index 0000000..0d677f4
--- /dev/null
+++ b/plugins/timecontrol/icons/hi16-action-tderadio_zzz.png
Binary files differ
diff --git a/plugins/timecontrol/icons/hi22-action-tderadio_kalarm.png b/plugins/timecontrol/icons/hi22-action-tderadio_kalarm.png
new file mode 100644
index 0000000..e4273d6
--- /dev/null
+++ b/plugins/timecontrol/icons/hi22-action-tderadio_kalarm.png
Binary files differ
diff --git a/plugins/timecontrol/icons/hi22-action-tderadio_zzz.png b/plugins/timecontrol/icons/hi22-action-tderadio_zzz.png
new file mode 100644
index 0000000..2a5ad8d
--- /dev/null
+++ b/plugins/timecontrol/icons/hi22-action-tderadio_zzz.png
Binary files differ
diff --git a/plugins/timecontrol/icons/hi32-action-tderadio_kalarm.png b/plugins/timecontrol/icons/hi32-action-tderadio_kalarm.png
new file mode 100644
index 0000000..2ae2809
--- /dev/null
+++ b/plugins/timecontrol/icons/hi32-action-tderadio_kalarm.png
Binary files differ
diff --git a/plugins/timecontrol/icons/hi32-action-tderadio_zzz.png b/plugins/timecontrol/icons/hi32-action-tderadio_zzz.png
new file mode 100644
index 0000000..4089298
--- /dev/null
+++ b/plugins/timecontrol/icons/hi32-action-tderadio_zzz.png
Binary files differ
diff --git a/plugins/timecontrol/icons/hi48-action-tderadio_kalarm.png b/plugins/timecontrol/icons/hi48-action-tderadio_kalarm.png
new file mode 100644
index 0000000..e88778d
--- /dev/null
+++ b/plugins/timecontrol/icons/hi48-action-tderadio_kalarm.png
Binary files differ
diff --git a/plugins/timecontrol/icons/hi48-action-tderadio_zzz.png b/plugins/timecontrol/icons/hi48-action-tderadio_zzz.png
new file mode 100644
index 0000000..a131574
--- /dev/null
+++ b/plugins/timecontrol/icons/hi48-action-tderadio_zzz.png
Binary files differ
diff --git a/plugins/timecontrol/icons/tderadio_zzz.png b/plugins/timecontrol/icons/tderadio_zzz.png
new file mode 100644
index 0000000..063e502
--- /dev/null
+++ b/plugins/timecontrol/icons/tderadio_zzz.png
Binary files differ
diff --git a/plugins/timecontrol/po/Makefile.am b/plugins/timecontrol/po/Makefile.am
new file mode 100644
index 0000000..26d490c
--- /dev/null
+++ b/plugins/timecontrol/po/Makefile.am
@@ -0,0 +1,2 @@
+PACKAGE = tderadio-timecontrol
+POFILES = AUTO
diff --git a/plugins/timecontrol/po/de.po b/plugins/timecontrol/po/de.po
new file mode 100644
index 0000000..b84f50f
--- /dev/null
+++ b/plugins/timecontrol/po/de.po
@@ -0,0 +1,116 @@
+# translation of de.po to
+# translation of tderadio-timecontrol.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: 2006-11-06 01:16+0100\n"
+"Last-Translator: Ernst Martin Witte <emw@nocabal.de>\n"
+"Language-Team: <de@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.11.4\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"
+
+#: timecontrol-configuration.cpp:181
+msgid "<don't change>"
+msgstr "<nicht verändern>"
+
+#: timecontrol.cpp:42
+msgid "Time Control and Alarm Functions"
+msgstr "Zeitsteurungs- und Weckfunktionen"
+
+#: timecontrol.cpp:48
+msgid "TimeControl Plugin"
+msgstr "Zeitsteuerungs-Plugin"
+
+#: timecontrol-configuration-ui.ui:117 timecontrol.cpp:270
+#, no-c-format
+msgid "Alarms"
+msgstr "Wecker"
+
+#: timecontrol.cpp:270
+msgid "Setup Alarms"
+msgstr "Wecker einrichten"
+
+#: timecontrol-configuration-ui.ui:32
+#, no-c-format
+msgid "sleep countdown"
+msgstr "Schlummermodus"
+
+#: timecontrol-configuration-ui.ui:40
+#, no-c-format
+msgid " min"
+msgstr " min"
+
+#: timecontrol-configuration-ui.ui:180
+#, no-c-format
+msgid "Date"
+msgstr "Datum"
+
+#: timecontrol-configuration-ui.ui:203
+#, no-c-format
+msgid "Time"
+msgstr "Uhrzeit"
+
+#: timecontrol-configuration-ui.ui:226
+#, no-c-format
+msgid "Volume"
+msgstr "Lautstärke"
+
+#: timecontrol-configuration-ui.ui:234
+#, no-c-format
+msgid " %"
+msgstr " %"
+
+#: timecontrol-configuration-ui.ui:263
+#, no-c-format
+msgid "enabled"
+msgstr "aktiv"
+
+#: timecontrol-configuration-ui.ui:331
+#, no-c-format
+msgid "daily"
+msgstr "täglich"
+
+#: timecontrol-configuration-ui.ui:341
+#, no-c-format
+msgid "Radio Station"
+msgstr "Sender"
+
+#: timecontrol-configuration-ui.ui:393
+#, no-c-format
+msgid "Start Playing"
+msgstr "Radio einschalten"
+
+#: timecontrol-configuration-ui.ui:401
+#, no-c-format
+msgid "Stop Playing"
+msgstr "Radio ausschalten"
+
+#: timecontrol-configuration-ui.ui:409
+#, no-c-format
+msgid "Start Recording"
+msgstr "Aufnahme starten"
+
+#: timecontrol-configuration-ui.ui:417
+#, no-c-format
+msgid "Stop Recording"
+msgstr "Aufnahme beenden"
diff --git a/plugins/timecontrol/po/pt.po b/plugins/timecontrol/po/pt.po
new file mode 100644
index 0000000..30d85af
--- /dev/null
+++ b/plugins/timecontrol/po/pt.po
@@ -0,0 +1,111 @@
+# SOME DESCRIPTIVE TITLE.
+# Hugo Carvalho <hugokarvalho@hotmail.com>, 2020.
+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: Automatically generated\n"
+"Language-Team: none\n"
+"Language: pt\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).
+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 ""
+
+#: timecontrol-configuration.cpp:181
+msgid "<don't change>"
+msgstr ""
+
+#: timecontrol.cpp:42
+msgid "Time Control and Alarm Functions"
+msgstr ""
+
+#: timecontrol.cpp:48
+msgid "TimeControl Plugin"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:117 timecontrol.cpp:270
+#, no-c-format
+msgid "Alarms"
+msgstr ""
+
+#: timecontrol.cpp:270
+msgid "Setup Alarms"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:32
+#, no-c-format
+msgid "sleep countdown"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:40
+#, no-c-format
+msgid " min"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:180
+#, no-c-format
+msgid "Date"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:203
+#, no-c-format
+msgid "Time"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:226
+#, no-c-format
+msgid "Volume"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:234
+#, no-c-format
+msgid " %"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:263
+#, no-c-format
+msgid "enabled"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:331
+#, no-c-format
+msgid "daily"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:341
+#, no-c-format
+msgid "Radio Station"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:393
+#, no-c-format
+msgid "Start Playing"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:401
+#, no-c-format
+msgid "Stop Playing"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:409
+#, no-c-format
+msgid "Start Recording"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:417
+#, no-c-format
+msgid "Stop Recording"
+msgstr ""
diff --git a/plugins/timecontrol/po/ru.po b/plugins/timecontrol/po/ru.po
new file mode 100644
index 0000000..50bd8a9
--- /dev/null
+++ b/plugins/timecontrol/po/ru.po
@@ -0,0 +1,116 @@
+# translation of ru.po to
+# translation of tderadio-timecontrol.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:57+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"
+
+#: timecontrol-configuration.cpp:181
+msgid "<don't change>"
+msgstr "<не менять>"
+
+#: timecontrol.cpp:42
+msgid "Time Control and Alarm Functions"
+msgstr "Функции таймера и работы по расписанию"
+
+#: timecontrol.cpp:48
+msgid "TimeControl Plugin"
+msgstr "Модуль ремени"
+
+#: timecontrol-configuration-ui.ui:117 timecontrol.cpp:270
+#, no-c-format
+msgid "Alarms"
+msgstr "Расписание"
+
+#: timecontrol.cpp:270
+msgid "Setup Alarms"
+msgstr "Расписание"
+
+#: timecontrol-configuration-ui.ui:32
+#, no-c-format
+msgid "sleep countdown"
+msgstr "Период таймера отключения"
+
+#: timecontrol-configuration-ui.ui:40
+#, no-c-format
+msgid " min"
+msgstr " мин"
+
+#: timecontrol-configuration-ui.ui:180
+#, no-c-format
+msgid "Date"
+msgstr "Дата"
+
+#: timecontrol-configuration-ui.ui:203
+#, no-c-format
+msgid "Time"
+msgstr "Время"
+
+#: timecontrol-configuration-ui.ui:226
+#, no-c-format
+msgid "Volume"
+msgstr "Громкость"
+
+#: timecontrol-configuration-ui.ui:234
+#, no-c-format
+msgid " %"
+msgstr " %"
+
+#: timecontrol-configuration-ui.ui:263
+#, no-c-format
+msgid "enabled"
+msgstr "Включено"
+
+#: timecontrol-configuration-ui.ui:331
+#, no-c-format
+msgid "daily"
+msgstr "Ежедневно"
+
+#: timecontrol-configuration-ui.ui:341
+#, no-c-format
+msgid "Radio Station"
+msgstr "Радиостанция"
+
+#: timecontrol-configuration-ui.ui:393
+#, no-c-format
+msgid "Start Playing"
+msgstr "Начать воспроизведение"
+
+#: timecontrol-configuration-ui.ui:401
+#, no-c-format
+msgid "Stop Playing"
+msgstr "Остановить воспроизведение"
+
+#: timecontrol-configuration-ui.ui:409
+#, no-c-format
+msgid "Start Recording"
+msgstr "Начать запись"
+
+#: timecontrol-configuration-ui.ui:417
+#, no-c-format
+msgid "Stop Recording"
+msgstr "Остановить запись"
diff --git a/plugins/timecontrol/po/tderadio-timecontrol.pot b/plugins/timecontrol/po/tderadio-timecontrol.pot
new file mode 100644
index 0000000..a8b0c40
--- /dev/null
+++ b/plugins/timecontrol/po/tderadio-timecontrol.pot
@@ -0,0 +1,114 @@
+# 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 ""
+
+#: timecontrol-configuration.cpp:181
+msgid "<don't change>"
+msgstr ""
+
+#: timecontrol.cpp:42
+msgid "Time Control and Alarm Functions"
+msgstr ""
+
+#: timecontrol.cpp:48
+msgid "TimeControl Plugin"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:117 timecontrol.cpp:270
+#, no-c-format
+msgid "Alarms"
+msgstr ""
+
+#: timecontrol.cpp:270
+msgid "Setup Alarms"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:32
+#, no-c-format
+msgid "sleep countdown"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:40
+#, no-c-format
+msgid " min"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:180
+#, no-c-format
+msgid "Date"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:203
+#, no-c-format
+msgid "Time"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:226
+#, no-c-format
+msgid "Volume"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:234
+#, no-c-format
+msgid " %"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:263
+#, no-c-format
+msgid "enabled"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:331
+#, no-c-format
+msgid "daily"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:341
+#, no-c-format
+msgid "Radio Station"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:393
+#, no-c-format
+msgid "Start Playing"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:401
+#, no-c-format
+msgid "Stop Playing"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:409
+#, no-c-format
+msgid "Start Recording"
+msgstr ""
+
+#: timecontrol-configuration-ui.ui:417
+#, no-c-format
+msgid "Stop Recording"
+msgstr ""
diff --git a/plugins/timecontrol/timecontrol-configuration-ui.ui b/plugins/timecontrol/timecontrol-configuration-ui.ui
new file mode 100644
index 0000000..f528418
--- /dev/null
+++ b/plugins/timecontrol/timecontrol-configuration-ui.ui
@@ -0,0 +1,450 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>TimeControlConfigurationUI</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>TimeControlConfigurationUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>374</width>
+ <height>261</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelSleep</cstring>
+ </property>
+ <property name="text">
+ <string>sleep countdown</string>
+ </property>
+ </widget>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>editSleep</cstring>
+ </property>
+ <property name="suffix">
+ <string> min</string>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="lineStep">
+ <number>5</number>
+ </property>
+ <property name="value">
+ <number>30</number>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="Line" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout15</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelAlarmList</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Alarms</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonAlarmNew</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"filenew2"</iconset>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonDeleteAlarm</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"edit-delete"</iconset>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQListBox">
+ <property name="name">
+ <cstring>listAlarms</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout17</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout28</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout27</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelAlarmDate</cstring>
+ </property>
+ <property name="text">
+ <string>Date</string>
+ </property>
+ </widget>
+ <widget class="TQDateEdit">
+ <property name="name">
+ <cstring>editAlarmDate</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout28</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelAlarmTime</cstring>
+ </property>
+ <property name="text">
+ <string>Time</string>
+ </property>
+ </widget>
+ <widget class="TQTimeEdit">
+ <property name="name">
+ <cstring>editAlarmTime</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout29</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelAlarmVolume</cstring>
+ </property>
+ <property name="text">
+ <string>Volume</string>
+ </property>
+ </widget>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>editAlarmVolume</cstring>
+ </property>
+ <property name="suffix">
+ <string> %</string>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="minValue">
+ <number>-1</number>
+ </property>
+ <property name="value">
+ <number>-1</number>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout16</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>checkboxAlarmEnable</cstring>
+ </property>
+ <property name="text">
+ <string>enabled</string>
+ </property>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>100</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TDEListBox" row="0" column="1" rowspan="3" colspan="1">
+ <item>
+ <property name="text">
+ <string>Monday</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Tuesday</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Wednesday</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Thursday</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Friday</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Saturday</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Sunday</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>listWeekdays</cstring>
+ </property>
+ <property name="selectionMode">
+ <enum>Multi</enum>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>checkboxAlarmDaily</cstring>
+ </property>
+ <property name="text">
+ <string>daily</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelStationSelection</cstring>
+ </property>
+ <property name="text">
+ <string>Radio Station</string>
+ </property>
+ </widget>
+ <widget class="TQComboBox">
+ <property name="name">
+ <cstring>comboStationSelection</cstring>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout20</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>pixmapAlarmStation</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>150</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="TQComboBox">
+ <item>
+ <property name="text">
+ <string>Start Playing</string>
+ </property>
+ <property name="pixmap">
+ <pixmap>"tderadio_muteoff"</pixmap>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Stop Playing</string>
+ </property>
+ <property name="pixmap">
+ <pixmap>"tderadio_muteon"</pixmap>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Start Recording</string>
+ </property>
+ <property name="pixmap">
+ <pixmap>"tderadio_record"</pixmap>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Stop Recording</string>
+ </property>
+ <property name="pixmap">
+ <pixmap>"tderadio_muteon"</pixmap>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>comboAlarmType</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>listAlarms</tabstop>
+ <tabstop>buttonAlarmNew</tabstop>
+ <tabstop>buttonDeleteAlarm</tabstop>
+ <tabstop>editAlarmDate</tabstop>
+ <tabstop>editAlarmTime</tabstop>
+ <tabstop>editAlarmVolume</tabstop>
+ <tabstop>checkboxAlarmDaily</tabstop>
+ <tabstop>checkboxAlarmEnable</tabstop>
+ <tabstop>comboStationSelection</tabstop>
+</tabstops>
+<pixmapfunction>SmallIcon</pixmapfunction>
+<layoutdefaults spacing="6" margin="0"/>
+<includes>
+ <include location="global" impldecl="in implementation">kiconloader.h</include>
+ <include location="global" impldecl="in implementation">tdelistbox.h</include>
+</includes>
+</UI>
diff --git a/plugins/timecontrol/timecontrol-configuration.cpp b/plugins/timecontrol/timecontrol-configuration.cpp
new file mode 100644
index 0000000..db3a760
--- /dev/null
+++ b/plugins/timecontrol/timecontrol-configuration.cpp
@@ -0,0 +1,425 @@
+/***************************************************************************
+ timecontrol-configuration.cpp - description
+ -------------------
+ begin : Sam Aug 2 2003
+ copyright : (C) 2003 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 <math.h>
+#include <algorithm>
+using std::sort;
+
+#include <tqdatetime.h>
+#include <tqlistbox.h>
+#include <tqcombobox.h>
+#include <tqdatetimeedit.h>
+#include <tqlabel.h>
+#include <tqspinbox.h>
+#include <tqcheckbox.h>
+#include <tqpushbutton.h>
+
+#include <tdelistbox.h>
+#include <tdelocale.h>
+
+#include "../../src/include/stationlist.h"
+#include "../../src/include/alarm.h"
+#include "../../src/include/errorlog-interfaces.h"
+#include "../../src/include/radiostation.h"
+
+#include "timecontrol-configuration.h"
+
+class DateTimeCmp
+{
+public:
+ bool operator() (const Alarm &a, const Alarm &b) {
+ return a.nextAlarm(true) < b.nextAlarm(true);
+ }
+
+};
+
+TimeControlConfiguration::TimeControlConfiguration (TQWidget *parent)
+ : TimeControlConfigurationUI(parent),
+ ITimeControlClient(),
+ IRadioClient(),
+ ignoreChanges(false),
+ m_dirty(false)
+{
+
+ TQObject::connect(checkboxAlarmDaily, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotDailyChanged(bool)));
+ TQObject::connect(listWeekdays, TQT_SIGNAL(highlighted(int)), this, TQT_SLOT(slotWeekdaysChanged()));
+ TQObject::connect(checkboxAlarmEnable, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotEnabledChanged(bool)));
+ TQObject::connect(comboStationSelection, TQT_SIGNAL(highlighted(int)), this, TQT_SLOT(slotStationChanged(int)));
+ TQObject::connect(listAlarms, TQT_SIGNAL(highlighted(int)), this, TQT_SLOT(slotAlarmSelectChanged(int)));
+ TQObject::connect(editAlarmDate, TQT_SIGNAL(valueChanged(const TQDate &)), this, TQT_SLOT(slotDateChanged(const TQDate &)));
+ TQObject::connect(editAlarmTime, TQT_SIGNAL(valueChanged(const TQTime &)), this, TQT_SLOT(slotTimeChanged(const TQTime &)));
+ TQObject::connect(editAlarmVolume, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotVolumeChanged(int)));
+ TQObject::connect(buttonAlarmNew, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotNewAlarm()));
+ TQObject::connect(buttonDeleteAlarm, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotDeleteAlarm()));
+ TQObject::connect(comboAlarmType, TQT_SIGNAL(highlighted(int)), this, TQT_SLOT(slotAlarmTypeChanged(int)));
+
+ TQObject::connect(checkboxAlarmDaily, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(listWeekdays, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(checkboxAlarmEnable, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(comboStationSelection, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(editAlarmDate, TQT_SIGNAL(valueChanged(const TQDate &)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(editAlarmTime, TQT_SIGNAL(valueChanged(const TQTime &)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(editAlarmVolume, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(buttonAlarmNew, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(buttonDeleteAlarm, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(comboAlarmType, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSetDirty()));
+ TQObject::connect(editSleep, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotSetDirty()));
+}
+
+TimeControlConfiguration::~TimeControlConfiguration ()
+{
+}
+
+bool TimeControlConfiguration::connectI (Interface *i)
+{
+ bool a = ITimeControlClient::connectI(i);
+ bool b = IRadioClient::connectI(i);
+ return a || b;
+}
+
+
+bool TimeControlConfiguration::disconnectI (Interface *i)
+{
+ bool a = ITimeControlClient::disconnectI(i);
+ bool b = IRadioClient::disconnectI(i);
+ return a || b;
+}
+
+
+// ITimeControlClient
+
+bool TimeControlConfiguration::noticeAlarmsChanged(const AlarmVector &sl)
+{
+ int idx = listAlarms->currentItem();
+ int currentID = (idx >= 0 && (unsigned)idx < alarms.size()) ? alarms[idx].ID() : -1;
+
+ alarms = sl;
+ sort(alarms.begin(), alarms.end(), DateTimeCmp());
+
+ bool oldBlock = listAlarms->signalsBlocked();
+ listAlarms->blockSignals(true);
+
+ listAlarms->clear();
+ idx = -1;
+ int k = 0;
+ for (ciAlarmVector i = alarms.begin(); i != alarms.end(); ++i, ++k) {
+ listAlarms->insertItem(i->nextAlarm(true).toString());
+ if (i->ID() == currentID)
+ idx = k;
+ }
+ listAlarms->setCurrentItem(idx);
+
+ listAlarms->blockSignals(oldBlock);
+
+ slotAlarmSelectChanged(idx);
+ return true;
+}
+
+bool TimeControlConfiguration::noticeAlarm(const Alarm &)
+{
+ return false;
+}
+
+bool TimeControlConfiguration::noticeNextAlarmChanged(const Alarm *)
+{
+ noticeAlarmsChanged(alarms);
+ return true;
+}
+
+bool TimeControlConfiguration::noticeCountdownStarted(const TQDateTime &/*end*/)
+{
+ return false;
+}
+
+bool TimeControlConfiguration::noticeCountdownStopped()
+{
+ return false;
+}
+
+bool TimeControlConfiguration::noticeCountdownZero()
+{
+ return false;
+}
+
+bool TimeControlConfiguration::noticeCountdownSecondsChanged(int n)
+{
+ editSleep->setValue((int)rint(n / 60));
+ return false;
+}
+
+
+// IRadioClient
+
+bool TimeControlConfiguration::noticePowerChanged(bool /*on*/)
+{
+ return false;
+}
+
+bool TimeControlConfiguration::noticeStationChanged (const RadioStation &, int /*idx*/)
+{
+ return false;
+}
+
+bool TimeControlConfiguration::noticeStationsChanged(const StationList &sl)
+{
+ comboStationSelection->clear();
+ stationIDs.clear();
+ comboStationSelection->insertItem(i18n("<don't change>"));
+ stationIDs.push_back(TQString());
+
+ for (RawStationList::Iterator i(sl.all()); i.current(); ++i) {
+ comboStationSelection->insertItem(i.current()->iconName(),
+ i.current()->longName());
+ stationIDs.push_back(i.current()->stationID());
+ }
+ return true;
+}
+
+
+// Slots
+
+
+void TimeControlConfiguration::slotDateChanged( const TQDate &d )
+{
+ if (ignoreChanges) return;
+
+ int idx = listAlarms->currentItem();
+ if (idx >= 0 && (unsigned)idx < alarms.size()) {
+ Alarm &a = alarms[idx];
+ a.setDate(d);
+
+ ignoreChanges = true;
+ bool oldBlock = listAlarms->signalsBlocked();
+ listAlarms->blockSignals(true);
+ noticeAlarmsChanged(alarms);
+ listAlarms->blockSignals(oldBlock);
+ ignoreChanges = false;
+ }
+}
+
+
+void TimeControlConfiguration::slotTimeChanged(const TQTime &t)
+{
+ if (ignoreChanges) return;
+
+ int idx = listAlarms->currentItem();
+ if (idx >= 0 && (unsigned)idx < alarms.size()) {
+ Alarm &a = alarms[idx];
+ a.setTime(t);
+
+ ignoreChanges = true;
+ bool oldBlock = listAlarms->signalsBlocked();
+ listAlarms->blockSignals(true);
+ noticeAlarmsChanged(alarms);
+ listAlarms->blockSignals(oldBlock);
+ ignoreChanges = false;
+ }
+}
+
+
+void TimeControlConfiguration::slotDailyChanged (bool b)
+{
+ if (ignoreChanges) return;
+
+ int idx = listAlarms->currentItem();
+ if (idx >= 0 && (unsigned)idx < alarms.size()) {
+ Alarm &a = alarms[idx];
+ a.setDaily(b);
+
+ ignoreChanges = true;
+ bool oldBlock = listAlarms->signalsBlocked();
+ listAlarms->blockSignals(true);
+ noticeAlarmsChanged(alarms);
+ listAlarms->blockSignals(oldBlock);
+ ignoreChanges = false;
+
+ editAlarmDate ->setDisabled(b);
+ labelAlarmDate->setDisabled(b);
+ listWeekdays ->setDisabled(!b);
+ }
+}
+
+
+void TimeControlConfiguration::slotWeekdaysChanged ()
+{
+ if (ignoreChanges) return;
+
+ int mask = 0;
+ for (int i = 0; i < 7; ++i) {
+ if (listWeekdays->isSelected(i)) {
+ mask |= (1 << i);
+ }
+ }
+
+ int idx = listAlarms->currentItem();
+ if (idx >= 0 && (unsigned)idx < alarms.size()) {
+ Alarm &a = alarms[idx];
+ a.setWeekdayMask(mask);
+
+ ignoreChanges = true;
+ bool oldBlock = listAlarms->signalsBlocked();
+ listAlarms->blockSignals(true);
+ noticeAlarmsChanged(alarms);
+ listAlarms->blockSignals(oldBlock);
+ ignoreChanges = false;
+ }
+}
+
+
+void TimeControlConfiguration::slotEnabledChanged( bool b)
+{
+ int idx = listAlarms->currentItem();
+ if (idx >= 0 && (unsigned)idx < alarms.size()) {
+ alarms[idx].setEnabled(b);
+ }
+}
+
+
+void TimeControlConfiguration::slotStationChanged( int i )
+{
+ int idx = listAlarms->currentItem();
+ if ( idx >= 0 && (unsigned)idx < alarms.size()
+ && i >= 0 && (unsigned)i < stationIDs.size())
+ {
+ alarms[idx].setStationID( stationIDs[i] );
+ }
+}
+
+
+void TimeControlConfiguration::slotVolumeChanged( int v )
+{
+ int idx = listAlarms->currentItem();
+ if (idx >= 0 && (unsigned)idx < alarms.size()) {
+ alarms[idx].setVolumePreset(0.01 * (float)v);
+ }
+}
+
+
+void TimeControlConfiguration::slotAlarmTypeChanged(int t)
+{
+ int idx = listAlarms->currentItem();
+ if (idx >= 0 && (unsigned)idx < alarms.size()) {
+ alarms[idx].setAlarmType((Alarm::AlarmType)t);
+ }
+}
+
+
+void TimeControlConfiguration::slotAlarmSelectChanged(int idx)
+{
+ if (ignoreChanges) return;
+ ignoreChanges = true;
+
+ Alarm a;
+ bool valid = false;
+
+ if (idx >= 0 && (unsigned)idx < alarms.size()) {
+
+ a = alarms[idx];
+ valid = true;
+
+ }
+
+ editAlarmDate ->setDisabled(!valid || a.isDaily());
+ labelAlarmDate ->setDisabled(!valid || a.isDaily());
+ listWeekdays ->setDisabled(!valid ||!a.isDaily());
+ editAlarmTime ->setDisabled(!valid);
+ labelAlarmTime ->setDisabled(!valid);
+ labelAlarmVolume ->setDisabled(!valid);
+ editAlarmVolume ->setDisabled(!valid);
+ checkboxAlarmDaily ->setDisabled(!valid);
+ checkboxAlarmEnable ->setDisabled(!valid);
+ comboStationSelection->setDisabled(!valid);
+ labelStationSelection->setDisabled(!valid);
+ buttonDeleteAlarm ->setDisabled(!valid);
+ comboAlarmType ->setDisabled(!valid);
+
+ editAlarmDate ->setDate(a.alarmTime().date());
+ editAlarmTime ->setTime(a.alarmTime().time());
+ checkboxAlarmDaily ->setChecked(a.isDaily());
+ checkboxAlarmEnable ->setChecked(a.isEnabled());
+ editAlarmVolume ->setValue((int)rint(a.volumePreset() * 100));
+ comboAlarmType ->setCurrentItem(a.alarmType());
+
+ int k = 0;
+ const TQString &sID = a.stationID();
+ for (int i = 0; !k && i < (int)stationIDs.size(); ++i)
+ if (stationIDs[i] == sID) k = i;
+ comboStationSelection->setCurrentItem(k);
+
+ int m = a.weekdayMask();
+ for (int i = 0; i < 7; ++i) {
+ listWeekdays->setSelected(i, m & (1 << i));
+ }
+
+ ignoreChanges = false;
+}
+
+
+void TimeControlConfiguration::slotNewAlarm()
+{
+ TQDateTime dt(TQDateTime::currentDateTime());
+ Alarm a(dt, false, false);
+ alarms.push_back(a);
+ listAlarms->insertItem(a.alarmTime().toString());
+ listAlarms->setSelected(listAlarms->count() - 1, true);
+ noticeAlarmsChanged(alarms);
+}
+
+
+void TimeControlConfiguration::slotDeleteAlarm()
+{
+ int idx = listAlarms->currentItem();
+
+ if (idx >= 0 && (unsigned)idx < alarms.size()) {
+ // unfortunately a function vector<>::erase(idx) does not exist
+ iAlarmVector i = alarms.begin();
+ for (int k = 0; k < idx; ++k)
+ ++i;
+ if (i != alarms.end())
+ alarms.erase(i);
+ listAlarms->removeItem(idx);
+ }
+}
+
+
+void TimeControlConfiguration::slotOK()
+{
+ if (m_dirty) {
+ sendAlarms(alarms);
+ sendCountdownSeconds(editSleep->value() * 60);
+ m_dirty = false;
+ }
+}
+
+void TimeControlConfiguration::slotCancel()
+{
+ if (m_dirty) {
+ noticeAlarmsChanged(queryAlarms());
+ noticeCountdownSecondsChanged(queryCountdownSeconds());
+ m_dirty = false;
+ }
+}
+
+void TimeControlConfiguration::slotSetDirty()
+{
+ if (!ignoreChanges) {
+ m_dirty = true;
+ }
+}
+
+
+#include "timecontrol-configuration.moc"
diff --git a/plugins/timecontrol/timecontrol-configuration.h b/plugins/timecontrol/timecontrol-configuration.h
new file mode 100644
index 0000000..b53747e
--- /dev/null
+++ b/plugins/timecontrol/timecontrol-configuration.h
@@ -0,0 +1,91 @@
+/***************************************************************************
+ timecontro-configuration.h - description
+ -------------------
+ begin : Sam Aug 2 2003
+ copyright : (C) 2003 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_TIMECONTROL_CONFIGURATION_H
+#define KRADIO_TIMECONTROL_CONFIGURATION_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/radio_interfaces.h"
+#include "../../src/include/timecontrol_interfaces.h"
+#include "timecontrol-configuration-ui.h"
+
+class TimeControl;
+class TQWidget;
+
+class TimeControlConfiguration : public TimeControlConfigurationUI,
+ public ITimeControlClient,
+ public IRadioClient
+{
+Q_OBJECT
+
+public :
+ TimeControlConfiguration (TQWidget *parent);
+ ~TimeControlConfiguration ();
+
+ bool connectI (Interface *i);
+ bool disconnectI (Interface *i);
+
+// ITimeControlClient
+
+ bool noticeAlarmsChanged(const AlarmVector &sl);
+ bool noticeAlarm(const Alarm &);
+ bool noticeNextAlarmChanged(const Alarm *);
+ bool noticeCountdownStarted(const TQDateTime &end);
+ bool noticeCountdownStopped();
+ bool noticeCountdownZero();
+ bool noticeCountdownSecondsChanged(int n);
+
+// IRadioClient
+
+ bool noticePowerChanged(bool on);
+ bool noticeStationChanged (const RadioStation &, int idx);
+ bool noticeStationsChanged(const StationList &sl);
+ bool noticePresetFileChanged(const TQString &/*f*/) { return false; }
+
+ bool noticeCurrentSoundStreamIDChanged(SoundStreamID /*id*/) { return false; }
+
+protected slots:
+
+ void slotDailyChanged (bool daily);
+ void slotWeekdaysChanged ();
+ void slotEnabledChanged (bool enable);
+ void slotStationChanged (int idx);
+ void slotAlarmSelectChanged(int idx);
+ void slotDateChanged(const TQDate &d);
+ void slotTimeChanged(const TQTime &d);
+ void slotVolumeChanged(int v);
+ void slotAlarmTypeChanged(int idx);
+
+ void slotNewAlarm();
+ void slotDeleteAlarm();
+
+ void slotOK();
+ void slotCancel();
+ void slotSetDirty();
+
+protected:
+
+ AlarmVector alarms;
+ vector<TQString> stationIDs;
+
+ bool ignoreChanges;
+ bool m_dirty;
+};
+
+#endif
diff --git a/plugins/timecontrol/timecontrol.cpp b/plugins/timecontrol/timecontrol.cpp
new file mode 100644
index 0000000..1b56ff0
--- /dev/null
+++ b/plugins/timecontrol/timecontrol.cpp
@@ -0,0 +1,301 @@
+/***************************************************************************
+ timecontrol.cpp - description
+ -------------------
+ begin : Son Jan 12 2003
+ copyright : (C) 2003 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 <tdeaboutdata.h>
+#include <tdeconfig.h>
+
+#include "timecontrol.h"
+#include "timecontrol-configuration.h"
+#include "../../src/include/pluginmanager.h"
+#include "../../src/include/aboutwidget.h"
+
+//const char *AlarmListElement = "alarmlist";
+//const char *AlarmElement = "alarm";
+const char *AlarmDateElement = "date";
+const char *AlarmTimeElement = "time";
+const char *AlarmDailyElement = "daily";
+const char *AlarmWeekdayMaskElement = "weekdayMask";
+const char *AlarmEnabledElement = "enabled";
+const char *AlarmStationIDElement = "stationID";
+//const char *AlarmFrequencyElement = "frequency";
+const char *AlarmVolumeElement = "volume";
+const char *AlarmTypeElement = "type";
+
+
+///////////////////////////////////////////////////////////////////////
+//// plugin library functions
+
+PLUGIN_LIBRARY_FUNCTIONS(TimeControl, "tderadio-timecontrol", i18n("Time Control and Alarm Functions"));
+
+///////////////////////////////////////////////////////////////////////
+
+
+TimeControl::TimeControl (const TQString &n)
+ : PluginBase(n, i18n("TimeControl Plugin")),
+ m_waitingFor(NULL),
+ m_countdownSeconds(0),
+ m_alarmTimer(this),
+ m_countdownTimer(this)
+{
+ TQObject::connect(&m_alarmTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotQTimerAlarmTimeout()));
+ TQObject::connect(&m_countdownTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotQTimerCountdownTimeout()));
+}
+
+
+TimeControl::~TimeControl ()
+{
+ m_waitingFor = NULL;
+}
+
+bool TimeControl::connectI (Interface *i)
+{
+ bool a = ITimeControl::connectI(i);
+ bool b = PluginBase::connectI(i);
+ return a || b;
+}
+
+bool TimeControl::disconnectI (Interface *i)
+{
+ bool a = ITimeControl::disconnectI(i);
+ bool b = PluginBase::disconnectI(i);
+ return a || b;
+}
+
+bool TimeControl::setAlarms (const AlarmVector &al)
+{
+ if (m_alarms != al) {
+ m_waitingFor = NULL;
+
+ m_alarms = al;
+
+ slotQTimerAlarmTimeout();
+
+ notifyAlarmsChanged(m_alarms);
+ }
+ return true;
+}
+
+
+bool TimeControl::setCountdownSeconds(int n)
+{
+ int old = m_countdownSeconds;
+ m_countdownSeconds = n;
+ if (old != n)
+ notifyCountdownSecondsChanged(n);
+ return true;
+}
+
+
+bool TimeControl::startCountdown()
+{
+ m_countdownEnd = TQDateTime::currentDateTime().addSecs(m_countdownSeconds);
+ m_countdownTimer.start(m_countdownSeconds * 1000, true);
+
+ notifyCountdownStarted(getCountdownEnd());
+
+ return true;
+}
+
+
+bool TimeControl::stopCountdown()
+{
+ m_countdownTimer.stop();
+ m_countdownEnd = TQDateTime();
+
+ notifyCountdownStopped();
+
+ return true;
+}
+
+
+TQDateTime TimeControl::getNextAlarmTime() const
+{
+ const Alarm *a = getNextAlarm();
+ if (a)
+ return a->nextAlarm();
+ else
+ return TQDateTime();
+}
+
+
+const Alarm *TimeControl::getNextAlarm () const
+{
+ TQDateTime now = TQDateTime::currentDateTime(),
+ next;
+
+ const Alarm *retval = NULL;
+
+ for (ciAlarmVector i = m_alarms.begin(); i != m_alarms.end(); ++i) {
+ TQDateTime n = i->nextAlarm();
+ if (n.isValid() && n > now && ( ! next.isValid() || n < next)) {
+ next = n;
+ retval = &(*i);
+ }
+ }
+
+ TQDateTime old = m_nextAlarm_tmp;
+ m_nextAlarm_tmp = next;
+ if (old != m_nextAlarm_tmp) {
+ notifyNextAlarmChanged(retval);
+ }
+
+ return retval;
+}
+
+
+TQDateTime TimeControl::getCountdownEnd () const
+{
+ if (m_countdownTimer.isActive())
+ return m_countdownEnd;
+ else
+ return TQDateTime();
+}
+
+
+void TimeControl::slotQTimerCountdownTimeout()
+{
+ stopCountdown();
+
+ notifyCountdownZero();
+}
+
+
+void TimeControl::slotQTimerAlarmTimeout()
+{
+ if (m_waitingFor) {
+ notifyAlarm(*m_waitingFor);
+ }
+
+ TQDateTime now = TQDateTime::currentDateTime();
+ Alarm const *n = getNextAlarm();
+ TQDateTime na = getNextAlarmTime();
+
+ m_waitingFor = NULL;
+
+ if (na.isValid()) {
+
+ int days = now.daysTo(na);
+ int msecs = now.time().msecsTo(na.time());
+
+ if (days > 1) {
+ m_alarmTimer.start(24 * 3600 * 1000, true);
+
+ } else if (days >= 0) {
+
+ if (days > 0)
+ msecs += days * 24 * 3600 * 1000;
+
+ if (msecs > 0) {
+ m_waitingFor = n;
+ m_alarmTimer.start(msecs, true);
+ }
+ }
+ }
+}
+
+
+void TimeControl::restoreState (TDEConfig *config)
+{
+ AlarmVector al;
+
+ config->setGroup(TQString("timecontrol-") + name());
+
+ int nAlarms = config->readNumEntry ("nAlarms", 0);
+ for (int idx = 1; idx <= nAlarms; ++idx) {
+
+ TQString num = TQString().setNum(idx);
+ TQDateTime d = config->readDateTimeEntry(AlarmTimeElement + num);
+ bool enable = config->readBoolEntry(AlarmEnabledElement + num, false);
+ bool daily = config->readBoolEntry(AlarmDailyElement + num, false);
+ int weekdayMask = config->readNumEntry(AlarmWeekdayMaskElement + num, 0x7F);
+ float vol = config->readDoubleNumEntry(AlarmVolumeElement + num, 1);
+ TQString sid = config->readEntry(AlarmStationIDElement + num, TQString());
+ int type = config->readNumEntry(AlarmTypeElement + num, 0);
+
+ enable &= d.isValid();
+
+ Alarm a ( d, daily, enable);
+ a.setVolumePreset(vol);
+ a.setWeekdayMask(weekdayMask);
+ a.setStationID(sid);
+ a.setAlarmType((Alarm::AlarmType)type);
+ al.push_back(a);
+ }
+
+ setAlarms(al);
+ setCountdownSeconds(config->readNumEntry("countdownSeconds", 30*60));
+}
+
+
+void TimeControl::saveState (TDEConfig *config) const
+{
+ config->setGroup(TQString("timecontrol-") + name());
+
+ config->writeEntry("nAlarms", m_alarms.size());
+ int idx = 1;
+ ciAlarmVector end = m_alarms.end();
+ for (ciAlarmVector i = m_alarms.begin(); i != end; ++i, ++idx) {
+ TQString num = TQString().setNum(idx);
+ config->writeEntry (AlarmTimeElement + num, i->alarmTime());
+ config->writeEntry (AlarmEnabledElement + num, i->isEnabled());
+ config->writeEntry (AlarmDailyElement + num, i->isDaily());
+ config->writeEntry (AlarmWeekdayMaskElement + num, i->weekdayMask());
+ config->writeEntry (AlarmVolumeElement + num, i->volumePreset());
+ config->writeEntry (AlarmStationIDElement + num, i->stationID());
+ config->writeEntry (AlarmTypeElement + num, i->alarmType());
+ }
+
+ config->writeEntry("countdownSeconds", m_countdownSeconds);
+}
+
+
+ConfigPageInfo TimeControl::createConfigurationPage()
+{
+ TimeControlConfiguration *conf = new TimeControlConfiguration(NULL);
+ connectI(conf);
+ return ConfigPageInfo (conf, i18n("Alarms"), i18n("Setup Alarms"), "tderadio_kalarm");
+}
+
+
+AboutPageInfo TimeControl::createAboutPage()
+{
+/* TDEAboutData aboutData("tderadio",
+ NULL,
+ NULL,
+ I18N_NOOP("Time Control Plugin for TDERadio."
+ "<P>"
+ "Provides Alarms and Sleep Countdown"
+ "<P>"),
+ TDEAboutData::License_GPL,
+ "(c) 2002-2005 Martin Witte, Klas Kalass",
+ 0,
+ "http://sourceforge.net/projects/tderadio",
+ 0);
+ aboutData.addAuthor("Martin Witte", "", "witte@kawo1.rwth-aachen.de");
+ aboutData.addAuthor("Klas Kalass", "", "klas.kalass@gmx.de");
+
+ return AboutPageInfo(
+ new TDERadioAboutWidget(aboutData, TDERadioAboutWidget::AbtTabbed),
+ i18n("Alarms"),
+ i18n("Time Control Plugin"),
+ "tderadio_kalarm"
+ );*/
+ return AboutPageInfo();
+}
+
+
+#include "timecontrol.moc"
diff --git a/plugins/timecontrol/timecontrol.h b/plugins/timecontrol/timecontrol.h
new file mode 100644
index 0000000..933d8f2
--- /dev/null
+++ b/plugins/timecontrol/timecontrol.h
@@ -0,0 +1,96 @@
+/***************************************************************************
+ timecontrol.h - description
+ -------------------
+ begin : Son Jan 12 2003
+ copyright : (C) 2003 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_TIMECONTROL_H
+#define KRADIO_TIMECONTROL_H
+
+#include <tqobject.h>
+#include <tqtimer.h>
+
+#include "../../src/include/alarm.h"
+#include "../../src/include/plugins.h"
+#include "../../src/include/timecontrol_interfaces.h"
+
+// well, it has to be a TQObject :( , but only for
+// receiving TQTimer - timeouts
+
+class TimeControl : public TQObject,
+ public PluginBase,
+ public ITimeControl
+{
+ Q_OBJECT
+
+protected:
+ AlarmVector m_alarms;
+ Alarm const * m_waitingFor; // m_alarmTimer is exactly for this date/time
+
+ int m_countdownSeconds; // in seconds
+ TQDateTime m_countdownEnd;
+
+ TQTimer m_alarmTimer;
+ TQTimer m_countdownTimer;
+
+ mutable TQDateTime m_nextAlarm_tmp; // used to recognize nextAlarm changes
+
+public:
+ TimeControl (const TQString &name);
+ ~TimeControl();
+
+ virtual TQString pluginClassName() const { return "TimeControl"; }
+
+ virtual const TQString &name() const { return PluginBase::name(); }
+ virtual TQString &name() { return PluginBase::name(); }
+
+ virtual bool connectI (Interface *i);
+ virtual bool disconnectI (Interface *i);
+
+ // PluginBase
+
+public:
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+ virtual ConfigPageInfo createConfigurationPage();
+ virtual AboutPageInfo createAboutPage();
+
+
+ // ITimeControl Interface methods
+
+RECEIVERS:
+ bool setAlarms(const AlarmVector &sl);
+ bool setCountdownSeconds(int n);
+ bool startCountdown();
+ bool stopCountdown();
+
+ANSWERS:
+ TQDateTime getNextAlarmTime () const;
+ const Alarm* getNextAlarm () const;
+ const AlarmVector & getAlarms () const { return m_alarms; }
+ int getCountdownSeconds () const { return m_countdownSeconds; }
+ TQDateTime getCountdownEnd () const;
+
+
+ // slots for receiving timeout messages of timers
+
+protected slots:
+ virtual void slotQTimerAlarmTimeout();
+ virtual void slotQTimerCountdownTimeout();
+
+};
+
+
+#endif
diff --git a/plugins/timeshifter/CMakeL10n.txt b/plugins/timeshifter/CMakeL10n.txt
new file mode 100644
index 0000000..1da1b3d
--- /dev/null
+++ b/plugins/timeshifter/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-timeshifter"
+ DESTINATION "po"
+)
diff --git a/plugins/timeshifter/Makefile.am b/plugins/timeshifter/Makefile.am
new file mode 100644
index 0000000..38d99cb
--- /dev/null
+++ b/plugins/timeshifter/Makefile.am
@@ -0,0 +1,18 @@
+SUBDIRS = po icons .
+
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = libtimeshifter.la
+libtimeshifter_la_SOURCES = timeshifter.cpp timeshifter-configuration-ui.ui \
+ timeshifter-configuration.cpp
+libtimeshifter_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+
+noinst_HEADERS = timeshifter.h timeshifter-configuration.h
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-timeshifter.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-timeshifter.pot
diff --git a/plugins/timeshifter/icons/Makefile.am b/plugins/timeshifter/icons/Makefile.am
new file mode 100644
index 0000000..974b96b
--- /dev/null
+++ b/plugins/timeshifter/icons/Makefile.am
@@ -0,0 +1,2 @@
+icons_ICON = AUTO
+iconsdir = $(datadir)/icons
diff --git a/plugins/timeshifter/icons/hi16-action-tderadio_pause.png b/plugins/timeshifter/icons/hi16-action-tderadio_pause.png
new file mode 100644
index 0000000..8887f23
--- /dev/null
+++ b/plugins/timeshifter/icons/hi16-action-tderadio_pause.png
Binary files differ
diff --git a/plugins/timeshifter/icons/hi16-app-tderadio_plus_pause.png b/plugins/timeshifter/icons/hi16-app-tderadio_plus_pause.png
new file mode 100644
index 0000000..88b805a
--- /dev/null
+++ b/plugins/timeshifter/icons/hi16-app-tderadio_plus_pause.png
Binary files differ
diff --git a/plugins/timeshifter/icons/hi22-action-tderadio_pause.png b/plugins/timeshifter/icons/hi22-action-tderadio_pause.png
new file mode 100644
index 0000000..34d105d
--- /dev/null
+++ b/plugins/timeshifter/icons/hi22-action-tderadio_pause.png
Binary files differ
diff --git a/plugins/timeshifter/icons/hi22-app-tderadio_plus_pause.png b/plugins/timeshifter/icons/hi22-app-tderadio_plus_pause.png
new file mode 100644
index 0000000..06ed569
--- /dev/null
+++ b/plugins/timeshifter/icons/hi22-app-tderadio_plus_pause.png
Binary files differ
diff --git a/plugins/timeshifter/icons/hi32-action-tderadio_pause.png b/plugins/timeshifter/icons/hi32-action-tderadio_pause.png
new file mode 100644
index 0000000..5eb0982
--- /dev/null
+++ b/plugins/timeshifter/icons/hi32-action-tderadio_pause.png
Binary files differ
diff --git a/plugins/timeshifter/icons/hi32-app-tderadio_plus_pause.png b/plugins/timeshifter/icons/hi32-app-tderadio_plus_pause.png
new file mode 100644
index 0000000..093b79c
--- /dev/null
+++ b/plugins/timeshifter/icons/hi32-app-tderadio_plus_pause.png
Binary files differ
diff --git a/plugins/timeshifter/icons/hi48-app-tderadio_plus_pause.png b/plugins/timeshifter/icons/hi48-app-tderadio_plus_pause.png
new file mode 100644
index 0000000..25742c4
--- /dev/null
+++ b/plugins/timeshifter/icons/hi48-app-tderadio_plus_pause.png
Binary files differ
diff --git a/plugins/timeshifter/icons/hi64-app-tderadio_plus_pause.png b/plugins/timeshifter/icons/hi64-app-tderadio_plus_pause.png
new file mode 100644
index 0000000..41fd048
--- /dev/null
+++ b/plugins/timeshifter/icons/hi64-app-tderadio_plus_pause.png
Binary files differ
diff --git a/plugins/timeshifter/po/Makefile.am b/plugins/timeshifter/po/Makefile.am
new file mode 100644
index 0000000..0df80ff
--- /dev/null
+++ b/plugins/timeshifter/po/Makefile.am
@@ -0,0 +1,3 @@
+
+PACKAGE = tderadio-timeshifter
+POFILES = AUTO
diff --git a/plugins/timeshifter/po/de.po b/plugins/timeshifter/po/de.po
new file mode 100644
index 0000000..a24f50a
--- /dev/null
+++ b/plugins/timeshifter/po/de.po
@@ -0,0 +1,100 @@
+# translation of de.po to
+# translation of tderadio-timeshifter.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-08-31 00:46+0000\n"
+"Last-Translator: Chris <xchrisx@uber.space>\n"
+"Language-Team: German <https://mirror.git.trinitydesktop.org/weblate/"
+"projects/applications/tderadio-timeshifter/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.8\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 "Chris (TDE)"
+
+#. 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 "(Keine Email)"
+
+#: timeshifter-configuration.cpp:138
+msgid "any ( * )"
+msgstr "alle ( * )"
+
+#: timeshifter-configuration.cpp:140
+msgid "TimeShifter Temporary File Selection"
+msgstr "Auswahl der temporären Datei für die zeitversetzte Wiedergabe"
+
+#: timeshifter-configuration.cpp:143
+msgid "Select TimeShifter Temporary File"
+msgstr "Auswahl der temporären Datei für die zeitversetzte Wiedergabe"
+
+#: timeshifter.cpp:31
+msgid "TimeShift Support"
+msgstr "Unterstützung für die Zeitversetzte Wiedergabe"
+
+#: timeshifter.cpp:36
+msgid "TimeShifter Plugin"
+msgstr "Plugin für die zeitversetzte Wiedergabe"
+
+#: timeshifter.cpp:121
+msgid "Timeshifter"
+msgstr "Zeitversetzte Wiedergabe"
+
+#: timeshifter.cpp:122
+msgid "Timeshifter Options"
+msgstr "Optionen für die zeitversetzte Wiedergabe"
+
+#: timeshifter.cpp:355
+msgid "TimeShifter::notifySoundStreamData: clients skipped %1 bytes. Data Lost"
+msgstr ""
+"TimeShifter::notifySoundStreamData: %1 bytes der Sounddaten wurden ignoriert "
+"und sind verloren"
+
+#: timeshifter.cpp:412
+msgid "internal stream, not stored"
+msgstr "interner, nicht aufgezeichneter Datenstrom"
+
+#: timeshifter-configuration-ui.ui:16
+#, no-c-format
+msgid "SetupDialogGeneral"
+msgstr "SetupDialogGeneral"
+
+#: timeshifter-configuration-ui.ui:72
+#, no-c-format
+msgid " MB"
+msgstr " MB"
+
+#: timeshifter-configuration-ui.ui:92
+#, no-c-format
+msgid "Maximum File Size"
+msgstr "maximale Dateigröße"
+
+#: timeshifter-configuration-ui.ui:100
+#, no-c-format
+msgid "Playback Mixer Device"
+msgstr "Wiedergabemixer"
+
+#: timeshifter-configuration-ui.ui:108
+#, no-c-format
+msgid "Temporary File"
+msgstr "Temporäre Datei"
+
+#: timeshifter-configuration-ui.ui:121
+#, no-c-format
+msgid "Playback Mixer Channel"
+msgstr "Wiedergabemixerkanal"
diff --git a/plugins/timeshifter/po/ru.po b/plugins/timeshifter/po/ru.po
new file mode 100644
index 0000000..1c96f19
--- /dev/null
+++ b/plugins/timeshifter/po/ru.po
@@ -0,0 +1,98 @@
+# translation of ru.po to
+# translation of tderadio-timeshifter.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:19+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 ""
+
+#: timeshifter-configuration.cpp:138
+msgid "any ( * )"
+msgstr "Все ( * )"
+
+#: timeshifter-configuration.cpp:140
+msgid "TimeShifter Temporary File Selection"
+msgstr "Выбор временного файла для реализации приостановки вещания"
+
+#: timeshifter-configuration.cpp:143
+msgid "Select TimeShifter Temporary File"
+msgstr "Выберите временный файл"
+
+#: timeshifter.cpp:31
+msgid "TimeShift Support"
+msgstr "Поддержка приостановки вещания"
+
+#: timeshifter.cpp:36
+msgid "TimeShifter Plugin"
+msgstr "Модуль приостановки вещания"
+
+#: timeshifter.cpp:121
+msgid "Timeshifter"
+msgstr "Приостановка"
+
+#: timeshifter.cpp:122
+msgid "Timeshifter Options"
+msgstr "Параметры приостановки вещания"
+
+#: timeshifter.cpp:355
+msgid "TimeShifter::notifySoundStreamData: clients skipped %1 bytes. Data Lost"
+msgstr ""
+"TimeShifter::notifySoundStreamData: клиенты пропустили %1 байт. Данные "
+"утеряны."
+
+#: timeshifter.cpp:412
+msgid "internal stream, not stored"
+msgstr ""
+
+#: timeshifter-configuration-ui.ui:16
+#, no-c-format
+msgid "SetupDialogGeneral"
+msgstr "SetupDialogGeneral"
+
+#: timeshifter-configuration-ui.ui:72
+#, no-c-format
+msgid " MB"
+msgstr " Мб"
+
+#: timeshifter-configuration-ui.ui:92
+#, no-c-format
+msgid "Maximum File Size"
+msgstr "Размер файла, не более"
+
+#: timeshifter-configuration-ui.ui:100
+#, no-c-format
+msgid "Playback Mixer Device"
+msgstr "Устройство воспроизведения"
+
+#: timeshifter-configuration-ui.ui:108
+#, no-c-format
+msgid "Temporary File"
+msgstr "Временный файл"
+
+#: timeshifter-configuration-ui.ui:121
+#, no-c-format
+msgid "Playback Mixer Channel"
+msgstr "Канал воспроизведения"
diff --git a/plugins/timeshifter/po/tderadio-timeshifter.pot b/plugins/timeshifter/po/tderadio-timeshifter.pot
new file mode 100644
index 0000000..10636f8
--- /dev/null
+++ b/plugins/timeshifter/po/tderadio-timeshifter.pot
@@ -0,0 +1,94 @@
+# 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 ""
+
+#: timeshifter-configuration.cpp:138
+msgid "any ( * )"
+msgstr ""
+
+#: timeshifter-configuration.cpp:140
+msgid "TimeShifter Temporary File Selection"
+msgstr ""
+
+#: timeshifter-configuration.cpp:143
+msgid "Select TimeShifter Temporary File"
+msgstr ""
+
+#: timeshifter.cpp:31
+msgid "TimeShift Support"
+msgstr ""
+
+#: timeshifter.cpp:36
+msgid "TimeShifter Plugin"
+msgstr ""
+
+#: timeshifter.cpp:121
+msgid "Timeshifter"
+msgstr ""
+
+#: timeshifter.cpp:122
+msgid "Timeshifter Options"
+msgstr ""
+
+#: timeshifter.cpp:355
+msgid "TimeShifter::notifySoundStreamData: clients skipped %1 bytes. Data Lost"
+msgstr ""
+
+#: timeshifter.cpp:412
+msgid "internal stream, not stored"
+msgstr ""
+
+#: timeshifter-configuration-ui.ui:16
+#, no-c-format
+msgid "SetupDialogGeneral"
+msgstr ""
+
+#: timeshifter-configuration-ui.ui:72
+#, no-c-format
+msgid " MB"
+msgstr ""
+
+#: timeshifter-configuration-ui.ui:92
+#, no-c-format
+msgid "Maximum File Size"
+msgstr ""
+
+#: timeshifter-configuration-ui.ui:100
+#, no-c-format
+msgid "Playback Mixer Device"
+msgstr ""
+
+#: timeshifter-configuration-ui.ui:108
+#, no-c-format
+msgid "Temporary File"
+msgstr ""
+
+#: timeshifter-configuration-ui.ui:121
+#, no-c-format
+msgid "Playback Mixer Channel"
+msgstr ""
diff --git a/plugins/timeshifter/timeshifter-configuration-ui.ui b/plugins/timeshifter/timeshifter-configuration-ui.ui
new file mode 100644
index 0000000..16336fb
--- /dev/null
+++ b/plugins/timeshifter/timeshifter-configuration-ui.ui
@@ -0,0 +1,225 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>TimeShifterConfigurationUI</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>TimeShifterConfigurationUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>299</width>
+ <height>134</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>SetupDialogGeneral</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout10</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="1" column="3">
+ <property name="name">
+ <cstring>spacer18_3_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="1">
+ <property name="name">
+ <cstring>spacer18_3_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>104</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQSpinBox" row="1" column="2">
+ <property name="name">
+ <cstring>editTempFileSize</cstring>
+ </property>
+ <property name="suffix">
+ <string> MB</string>
+ </property>
+ <property name="maxValue">
+ <number>10000</number>
+ </property>
+ <property name="minValue">
+ <number>10</number>
+ </property>
+ <property name="lineStep">
+ <number>10</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>labelTempFileSize</cstring>
+ </property>
+ <property name="text">
+ <string>Maximum File Size</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>labelPlaybackMixerDevice</cstring>
+ </property>
+ <property name="text">
+ <string>Playback Mixer Device</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>labelTempFile</cstring>
+ </property>
+ <property name="text">
+ <string>Temporary File</string>
+ </property>
+ </widget>
+ <widget class="TQLineEdit" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>editTempFile</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>labelPlaybackMixerChannel</cstring>
+ </property>
+ <property name="text">
+ <string>Playback Mixer Channel</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="0" column="3">
+ <property name="name">
+ <cstring>buttonSelectTempFile</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>26</width>
+ <height>26</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"document-open"</iconset>
+ </property>
+ </widget>
+ <widget class="TQComboBox" row="2" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>comboPlaybackMixerDevice</cstring>
+ </property>
+ </widget>
+ <widget class="TQComboBox" row="3" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>comboPlaybackMixerChannel</cstring>
+ </property>
+ </widget>
+ <spacer row="3" column="3">
+ <property name="name">
+ <cstring>spacer18_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="3">
+ <property name="name">
+ <cstring>spacer18_3_4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer16</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>61</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>editTempFile</tabstop>
+ <tabstop>buttonSelectTempFile</tabstop>
+ <tabstop>comboPlaybackMixerChannel</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in implementation">kiconloader.h</include>
+ <include location="global" impldecl="in implementation">knuminput.h</include>
+</includes>
+<pixmapfunction>SmallIconSet</pixmapfunction>
+<layoutdefaults spacing="6" margin="0"/>
+</UI>
diff --git a/plugins/timeshifter/timeshifter-configuration.cpp b/plugins/timeshifter/timeshifter-configuration.cpp
new file mode 100644
index 0000000..1974ae7
--- /dev/null
+++ b/plugins/timeshifter/timeshifter-configuration.cpp
@@ -0,0 +1,203 @@
+/***************************************************************************
+ v4lradio-configuration.cpp - description
+ -------------------
+ begin : Fre Jun 20 2003
+ copyright : (C) 2003 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 <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/soundcard.h>
+
+#include <tqspinbox.h>
+#include <tqlineedit.h>
+#include <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqfile.h>
+#include <tqpushbutton.h>
+
+#include <tdefiledialog.h>
+#include <knuminput.h>
+#include <tdelocale.h>
+
+#include "../../src/include/utils.h"
+#include "../../src/include/gui_list_helper.h"
+#include "timeshifter-configuration.h"
+#include "timeshifter.h"
+
+TimeShifterConfiguration::TimeShifterConfiguration (TQWidget *parent, TimeShifter *shifter)
+ : TimeShifterConfigurationUI(parent),
+ m_ignoreGUIChanges(false),
+ m_myControlChange(0),
+ m_PlaybackMixerHelper(comboPlaybackMixerDevice, StringListHelper::SORT_BY_DESCR),
+ m_PlaybackChannelHelper(comboPlaybackMixerChannel),
+ m_Shifter(shifter),
+ m_dirty(true)
+{
+ TQObject::connect(buttonSelectTempFile, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(selectTempFile()));
+ TQObject::connect(comboPlaybackMixerDevice, TQT_SIGNAL(activated(int)),
+ this, TQT_SLOT(slotComboPlaybackMixerSelected(int)));
+
+ connect(editTempFile, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(slotSetDirty()));
+ connect(editTempFileSize, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotSetDirty()));
+ connect(comboPlaybackMixerChannel, TQT_SIGNAL(activated( int )), this, TQT_SLOT(slotSetDirty()));
+ connect(comboPlaybackMixerDevice, TQT_SIGNAL(activated( int )), this, TQT_SLOT(slotSetDirty()));
+ slotCancel();
+}
+
+
+TimeShifterConfiguration::~TimeShifterConfiguration ()
+{
+}
+
+
+bool TimeShifterConfiguration::connectI (Interface *i)
+{
+ bool a = ISoundStreamClient::connectI(i);
+ return a;
+}
+
+
+bool TimeShifterConfiguration::disconnectI (Interface *i)
+{
+ bool a = ISoundStreamClient::disconnectI(i);
+ return a;
+}
+
+void TimeShifterConfiguration::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid)
+{
+ ISoundStreamClient::noticeConnectedI(s, pointer_valid);
+ if (s && pointer_valid) {
+ s->register4_notifyPlaybackChannelsChanged(this);
+ }
+}
+
+void TimeShifterConfiguration::noticeConnectedSoundClient(ISoundStreamClient::thisInterface *i, bool pointer_valid)
+{
+ if (i && pointer_valid && i->supportsPlayback() && m_Shifter) {
+ const TQString &org_mid = m_Shifter->getPlaybackMixer();
+ bool org_present = m_PlaybackMixerHelper.contains(org_mid);
+ const TQString &mid = org_present ? m_PlaybackMixerHelper.getCurrentItem() : org_mid;
+ const TQString &org_ch = m_Shifter->getPlaybackMixerChannel();
+ const TQString &ch = org_present ? m_PlaybackChannelHelper.getCurrentText() : org_ch;
+ setPlaybackMixer(mid, ch);
+ }
+}
+
+
+void TimeShifterConfiguration::noticeDisconnectedSoundClient(ISoundStreamClient::thisInterface *i, bool pointer_valid)
+{
+ if (i && pointer_valid && i->supportsPlayback()) {
+ setPlaybackMixer(m_Shifter->getPlaybackMixer(), m_Shifter->getPlaybackMixerChannel());
+ }
+}
+
+
+
+bool TimeShifterConfiguration::setPlaybackMixer(const TQString &_mixer_id, const TQString &Channel)
+{
+ TQString mixer_id = _mixer_id;
+ bool old = m_ignoreGUIChanges;
+ m_ignoreGUIChanges = true;
+
+ m_PlaybackMixerHelper.setData(getPlaybackClientDescriptions());
+ m_PlaybackMixerHelper.setCurrentItem(mixer_id);
+ mixer_id = m_PlaybackMixerHelper.getCurrentItem();
+
+ ISoundStreamClient *mixer = getSoundStreamClientWithID(mixer_id);
+ if (mixer) {
+ m_PlaybackChannelHelper.setData(mixer->getPlaybackChannels());
+ m_PlaybackChannelHelper.setCurrentText(m_PlaybackChannelHelper.contains(Channel) ? Channel : m_Shifter->getPlaybackMixerChannel());
+ }
+ labelPlaybackMixerChannel->setEnabled(mixer != NULL);
+ comboPlaybackMixerChannel->setEnabled(mixer != NULL);
+
+ m_ignoreGUIChanges = old;
+ return true;
+}
+
+
+// GUI Slots
+
+
+void TimeShifterConfiguration::selectTempFile()
+{
+ KFileDialog fd("/tmp/",
+ i18n("any ( * )").ascii(),
+ this,
+ i18n("TimeShifter Temporary File Selection").ascii(),
+ TRUE);
+ fd.setMode(KFile::File);
+ fd.setCaption (i18n("Select TimeShifter Temporary File"));
+
+ if (fd.exec() == TQDialog::Accepted) {
+ editTempFile->setText(fd.selectedFile());
+ }
+}
+
+
+void TimeShifterConfiguration::slotComboPlaybackMixerSelected(int /*idx*/)
+{
+ if (m_ignoreGUIChanges) return;
+ setPlaybackMixer(m_PlaybackMixerHelper.getCurrentItem(), m_PlaybackChannelHelper.getCurrentText());
+}
+
+
+void TimeShifterConfiguration::slotOK()
+{
+ if (m_Shifter && m_dirty) {
+ m_Shifter->setTempFile(editTempFile->text(), editTempFileSize->value() * (TQ_UINT64)(1024 * 1024));
+ m_Shifter->setPlaybackMixer(m_PlaybackMixerHelper.getCurrentItem(),
+ m_PlaybackChannelHelper.getCurrentText());
+ m_dirty = false;
+ }
+}
+
+
+void TimeShifterConfiguration::slotCancel()
+{
+ if (m_Shifter && m_dirty) {
+ editTempFile->setText(m_Shifter->getTempFileName());
+ editTempFileSize->setValue(m_Shifter->getTempFileMaxSize() / 1024 / 1024);
+
+ setPlaybackMixer(m_Shifter->getPlaybackMixer(), m_Shifter->getPlaybackMixerChannel());
+ m_dirty = false;
+ }
+}
+
+
+bool TimeShifterConfiguration::noticePlaybackChannelsChanged(const TQString & client_id, const TQStringList &/*channels*/)
+{
+ if (m_PlaybackMixerHelper.getCurrentItem() == client_id) {
+ setPlaybackMixer(client_id, m_PlaybackChannelHelper.getCurrentText());
+ }
+ return true;
+}
+
+
+void TimeShifterConfiguration::slotSetDirty()
+{
+ if (!m_ignoreGUIChanges) {
+ m_dirty = true;
+ }
+}
+
+void TimeShifterConfiguration::slotUpdateConfig()
+{
+ slotSetDirty();
+ slotCancel();
+}
+
+#include "timeshifter-configuration.moc"
diff --git a/plugins/timeshifter/timeshifter-configuration.h b/plugins/timeshifter/timeshifter-configuration.h
new file mode 100644
index 0000000..302f303
--- /dev/null
+++ b/plugins/timeshifter/timeshifter-configuration.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+ v4lradio-configuration.h - description
+ -------------------
+ begin : Fre Jun 20 2003
+ copyright : (C) 2003 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_TIMESHIFTER_CONFIGURATION_H
+#define KRADIO_TIMESHIFTER_CONFIGURATION_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/soundstreamclient_interfaces.h"
+#include "../../src/include/gui_list_helper.h"
+
+#include "timeshifter-configuration-ui.h"
+
+class TQWidget;
+class TimeShifter;
+
+class TimeShifterConfiguration : public TimeShifterConfigurationUI,
+ public ISoundStreamClient
+{
+Q_OBJECT
+
+public :
+ TimeShifterConfiguration (TQWidget *parent, TimeShifter *shifter);
+ ~TimeShifterConfiguration ();
+
+ bool connectI (Interface *i);
+ bool disconnectI (Interface *i);
+
+ void noticeConnectedSoundClient(ISoundStreamClient::thisInterface *i, bool pointer_valid);
+ void noticeDisconnectedSoundClient(ISoundStreamClient::thisInterface *i, bool pointer_valid);
+
+// ISoundStreamClient
+
+RECEIVERS:
+ void noticeConnectedI (ISoundStreamServer *s, bool pointer_valid);
+ bool noticePlaybackChannelsChanged(const TQString & /*client_id*/, const TQStringList &/*channels*/);
+
+protected:
+
+ bool setPlaybackMixer(const TQString &_mixer_id, const TQString &Channel);
+
+
+protected slots:
+
+ void selectTempFile();
+ void slotComboPlaybackMixerSelected(int idx);
+
+ void slotOK();
+ void slotCancel();
+ void slotSetDirty();
+ void slotUpdateConfig();
+
+protected:
+
+ bool m_ignoreGUIChanges;
+ int m_myControlChange;
+
+ typedef GUIListHelper<TQComboBox, TQString> StringListHelper;
+ typedef GUISimpleListHelper<TQComboBox> ChannelListHelper;
+
+ StringListHelper m_PlaybackMixerHelper;
+ ChannelListHelper m_PlaybackChannelHelper;
+
+ TimeShifter *m_Shifter;
+ bool m_dirty;
+};
+
+#endif
diff --git a/plugins/timeshifter/timeshifter.cpp b/plugins/timeshifter/timeshifter.cpp
new file mode 100644
index 0000000..146e530
--- /dev/null
+++ b/plugins/timeshifter/timeshifter.cpp
@@ -0,0 +1,455 @@
+/***************************************************************************
+ timeshifter.cpp - description
+ -------------------
+ begin : Mon May 16 13:39:31 CEST 2005
+ copyright : (C) 2005 by Ernst 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. *
+ * *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tdelocale.h>
+#include <linux/soundcard.h>
+
+#include "../../src/include/utils.h"
+#include "timeshifter.h"
+#include "timeshifter-configuration.h"
+
+///////////////////////////////////////////////////////////////////////
+
+PLUGIN_LIBRARY_FUNCTIONS(TimeShifter, "tderadio-timeshifter", i18n("TimeShift Support"));
+
+///////////////////////////////////////////////////////////////////////
+
+TimeShifter::TimeShifter (const TQString &name)
+ : PluginBase(name, i18n("TimeShifter Plugin")),
+ m_TempFileName("/tmp/tderadio-timeshifter-tempfile"),
+ m_TempFileMaxSize(256*1024*1024),
+ m_PlaybackMixerID(TQString()),
+ m_PlaybackMixerChannel("PCM"),
+ m_orgVolume(0.0),
+ m_PlaybackMetaData(0,0,0),
+ m_PlaybackDataLeftInBuffer(0),
+ m_RingBuffer(m_TempFileName, m_TempFileMaxSize)
+{
+}
+
+
+TimeShifter::~TimeShifter ()
+{
+}
+
+
+bool TimeShifter::connectI (Interface *i)
+{
+ bool a = PluginBase::connectI(i);
+ bool b = ISoundStreamClient::connectI(i);
+ return a || b;
+}
+
+
+bool TimeShifter::disconnectI (Interface *i)
+{
+ bool a = PluginBase::disconnectI(i);
+ bool b = ISoundStreamClient::disconnectI(i);
+ return a || b;
+}
+
+
+void TimeShifter::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid)
+{
+ ISoundStreamClient::noticeConnectedI(s, pointer_valid);
+ if (s && pointer_valid) {
+ s->register4_notifySoundStreamClosed(this);
+ s->register4_sendStartPlayback(this);
+ s->register4_sendStopPlayback(this);
+ s->register4_sendPausePlayback(this);
+ s->register4_notifySoundStreamData(this);
+ s->register4_notifyReadyForPlaybackData(this);
+ s->register4_querySoundStreamDescription(this);
+ s->register4_sendStartCaptureWithFormat(this);
+ s->register4_sendStopCapture(this);
+ }
+}
+
+
+void TimeShifter::saveState (TDEConfig *config) const
+{
+ config->setGroup(TQString("timeshifter-") + name());
+
+ config->writeEntry("temp-file-name", m_TempFileName);
+ config->writeEntry("max-file-size", m_TempFileMaxSize / 1024 / 1024);
+
+ config->writeEntry("PlaybackMixerID", m_PlaybackMixerID);
+ config->writeEntry("PlaybackMixerChannel", m_PlaybackMixerChannel);
+}
+
+
+void TimeShifter::restoreState (TDEConfig *config)
+{
+ config->setGroup(TQString("timeshifter-") + name());
+
+ TQString fname = config->readEntry("temp-file-name", "/tmp/tderadio-timeshifter-tempfile");
+ TQ_UINT64 fsize = 1024 * 1024 * config->readNumEntry("max-file-size", 256);
+
+ TQString mixerID = config->readEntry ("PlaybackMixerID", TQString());
+ TQString channel = config->readEntry ("PlaybackMixerChannel", "PCM");
+
+ setPlaybackMixer(mixerID, channel);
+ setTempFile(fname, fsize);
+
+ emit sigUpdateConfig();
+}
+
+
+ConfigPageInfo TimeShifter::createConfigurationPage()
+{
+ TimeShifterConfiguration *conf = new TimeShifterConfiguration(NULL, this);
+ TQObject::connect(this, TQT_SIGNAL(sigUpdateConfig()), conf, TQT_SLOT(slotUpdateConfig()));
+ return ConfigPageInfo (conf,
+ i18n("Timeshifter"),
+ i18n("Timeshifter Options"),
+ "tderadio_pause");
+}
+
+AboutPageInfo TimeShifter::createAboutPage()
+{
+ return AboutPageInfo();
+}
+
+
+bool TimeShifter::noticeSoundStreamClosed(SoundStreamID id)
+{
+ return stopPlayback(id);
+}
+
+bool TimeShifter::startPlayback(SoundStreamID id)
+{
+ if (id == m_OrgStreamID) {
+ m_StreamPaused = false;
+ return true;
+ }
+ return false;
+}
+
+bool TimeShifter::stopPlayback(SoundStreamID id)
+{
+ if (id == m_NewStreamID) {
+
+ return sendStopPlayback(m_OrgStreamID);
+
+ } else if (id == m_OrgStreamID) {
+
+ SoundStreamID tmp_newID = m_NewStreamID;
+ SoundStreamID tmp_orgID = m_OrgStreamID;
+
+ m_OrgStreamID.invalidate();
+ m_NewStreamID.invalidate();
+
+ sendStopCapture(tmp_newID);
+ closeSoundStream(tmp_newID);
+ stopPlayback(tmp_newID);
+ m_RingBuffer.clear();
+ m_PlaybackMetaData = SoundMetaData(0,0,0);
+ m_PlaybackDataLeftInBuffer = 0;
+ return true;
+ }
+ return false;
+}
+
+
+bool TimeShifter::pausePlayback(SoundStreamID id)
+{
+ if (!m_OrgStreamID.isValid()) {
+ SoundStreamID orgid = id;
+ SoundStreamID newid = createNewSoundStream(orgid, false);
+ m_OrgStreamID = orgid;
+ m_NewStreamID = newid;
+ notifySoundStreamCreated(newid);
+ notifySoundStreamRedirected(orgid, newid);
+ queryPlaybackVolume(newid, m_orgVolume);
+ sendMute(newid);
+ sendPlaybackVolume(newid, 0);
+
+ m_NewStreamID.invalidate();
+ sendStopPlayback(newid);
+ m_NewStreamID = newid;
+
+ m_StreamPaused = true;
+
+ m_RingBuffer.clear();
+ m_PlaybackMetaData = SoundMetaData(0,0,0);
+ m_PlaybackDataLeftInBuffer = 0;
+
+ sendStartCaptureWithFormat(m_NewStreamID, m_SoundFormat, m_realSoundFormat);
+
+ ISoundStreamClient *playback_mixer = searchPlaybackMixer();
+ if (playback_mixer) {
+ playback_mixer->preparePlayback(m_OrgStreamID, m_PlaybackMixerChannel, /*active*/true, /*startimmediately*/ true);
+ m_PlaybackMixerID = playback_mixer->getSoundStreamClientID();
+ }
+
+ return true;
+
+ } else if (id == m_OrgStreamID) {
+ m_StreamPaused = !m_StreamPaused;
+ if (!m_StreamPaused) {
+// sendStartPlayback(m_OrgStreamID);
+ sendUnmute(m_OrgStreamID);
+ sendPlaybackVolume(m_OrgStreamID, m_orgVolume);
+ } else {
+ queryPlaybackVolume(m_OrgStreamID, m_orgVolume);
+ }
+ return true;
+ }
+ return false;
+}
+
+
+size_t TimeShifter::writeMetaDataToBuffer(const SoundMetaData &md, char *buffer, size_t buffer_size)
+{
+ TQ_UINT64 pos = md.position();
+ time_t abs = md.absoluteTimestamp();
+ time_t rel = md.relativeTimestamp();
+ size_t url_len = md.url().url().length() + 1;
+ size_t req_size = sizeof(req_size) + sizeof(pos) + sizeof(abs) + sizeof(rel) + sizeof(url_len) + url_len;
+ if (req_size <= buffer_size) {
+ *(size_t*)buffer = req_size;
+ buffer += sizeof(req_size);
+ *(TQ_UINT64*)buffer = pos;
+ buffer += sizeof(pos);
+ *(time_t*)buffer = abs;
+ buffer += sizeof(abs);
+ *(time_t*)buffer = rel;
+ buffer += sizeof(rel);
+ *(size_t*)buffer = url_len;
+ buffer += sizeof(url_len);
+ memcpy(buffer, md.url().url().ascii(), url_len);
+ buffer += url_len;
+ return req_size;
+ } else if (buffer_size >= sizeof(req_size)) {
+ *(size_t*)buffer = sizeof(req_size);
+ return sizeof(req_size);
+ } else {
+ return 0;
+ }
+}
+
+size_t TimeShifter::readMetaDataFromBuffer(SoundMetaData &md, const char *buffer, size_t buffer_size)
+{
+ size_t req_size = 0;
+ TQ_UINT64 pos = 0;
+ time_t abs = 0;
+ time_t rel = 0;
+ size_t url_len = 0;
+ KURL url;
+ if (buffer_size >= sizeof(req_size)) {
+ req_size = *(size_t*)buffer;
+ buffer += sizeof(req_size);
+ if (req_size > sizeof(req_size)) {
+ pos = *(TQ_UINT64*)buffer;
+ buffer += sizeof(TQ_UINT64);
+ abs = *(time_t*)buffer;
+ buffer += sizeof(abs);
+ rel = *(time_t*)buffer;
+ buffer += sizeof(rel);
+ url_len = *(size_t*)buffer;
+ buffer += sizeof(url_len);
+ url = buffer;
+ buffer += url_len;
+ }
+ }
+ md = SoundMetaData(pos, rel, abs, url);
+ return req_size;
+}
+
+
+bool TimeShifter::noticeSoundStreamData(SoundStreamID id, const SoundFormat &/*sf*/, const char *data, size_t size, size_t &consumed_size, const SoundMetaData &md)
+{
+ if (id == m_NewStreamID) {
+ char buffer_meta[1024];
+ size_t meta_buffer_size = writeMetaDataToBuffer(md, buffer_meta, 1024);
+ size_t packet_size = meta_buffer_size + sizeof(size) + size;
+ if (packet_size > m_RingBuffer.getMaxSize())
+ return false;
+ TQ_INT64 diff = m_RingBuffer.getFreeSize() - packet_size;
+ while (diff < 0) {
+ skipPacketInRingBuffer();
+ diff = m_RingBuffer.getFreeSize() - packet_size;
+ }
+ m_RingBuffer.addData(buffer_meta, meta_buffer_size);
+ m_RingBuffer.addData((const char*)&size, sizeof(size));
+ m_RingBuffer.addData(data, size);
+ consumed_size = (consumed_size == SIZE_T_DONT_CARE) ? size : min(consumed_size, size);
+ return true;
+ }
+ return false;
+}
+
+
+void TimeShifter::skipPacketInRingBuffer()
+{
+ if (m_PlaybackDataLeftInBuffer > 0) {
+ m_RingBuffer.removeData(m_PlaybackDataLeftInBuffer);
+ } else {
+ size_t meta_size = 0;
+ m_RingBuffer.takeData((char*)&meta_size, sizeof(meta_size));
+ m_RingBuffer.removeData(meta_size - sizeof(meta_size));
+ size_t packet_size = 0;
+ m_RingBuffer.takeData((char*)&packet_size, sizeof(packet_size));
+ m_RingBuffer.removeData(packet_size - sizeof(packet_size));
+ }
+}
+
+
+bool TimeShifter::noticeReadyForPlaybackData(SoundStreamID id, size_t free_size)
+{
+ if (id == m_OrgStreamID && !m_StreamPaused) {
+
+ while (!m_RingBuffer.error() && m_RingBuffer.getFillSize() > 0 && free_size > 0) {
+ if (m_PlaybackDataLeftInBuffer == 0) {
+ char meta_buffer[1024];
+ size_t &meta_size = *(size_t*)meta_buffer;
+ meta_size = 0;
+ m_RingBuffer.takeData(meta_buffer, sizeof(meta_size));
+ if (meta_size && meta_size <= 1024) {
+ m_RingBuffer.takeData(meta_buffer + sizeof(meta_size), meta_size - sizeof(meta_size));
+ readMetaDataFromBuffer(m_PlaybackMetaData, meta_buffer, meta_size);
+ } else {
+ m_RingBuffer.removeData(meta_size - sizeof(meta_size));
+ }
+
+ m_PlaybackDataLeftInBuffer = 0;
+ m_RingBuffer.takeData((char*)&m_PlaybackDataLeftInBuffer, sizeof(m_PlaybackDataLeftInBuffer));
+ }
+
+ const size_t buffer_size = 65536;
+ char buffer[buffer_size];
+
+ while (!m_RingBuffer.error() && m_PlaybackDataLeftInBuffer > 0 && free_size > 0) {
+ size_t s = m_PlaybackDataLeftInBuffer < free_size ? m_PlaybackDataLeftInBuffer : free_size;
+
+ if (s > buffer_size)
+ s = buffer_size;
+ s = m_RingBuffer.takeData(buffer, s);
+
+ size_t consumed_size = SIZE_T_DONT_CARE;
+ notifySoundStreamData(m_OrgStreamID, m_realSoundFormat, buffer, s, consumed_size, m_PlaybackMetaData);
+ if (consumed_size == SIZE_T_DONT_CARE)
+ consumed_size = s;
+
+ free_size -= consumed_size;
+ m_PlaybackDataLeftInBuffer -= consumed_size;
+ if (consumed_size < s) {
+ logError(i18n("TimeShifter::notifySoundStreamData: clients skipped %1 bytes. Data Lost").arg(s - consumed_size));
+ free_size = 0; // break condition for outer loop
+ break;
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+
+
+ISoundStreamClient *TimeShifter::searchPlaybackMixer()
+{
+ ISoundStreamClient *playback_mixer = getSoundStreamClientWithID(m_PlaybackMixerID);
+
+ // some simple sort of autodetection if one mixer isn't present any more
+ if (!playback_mixer) {
+ TQPtrList<ISoundStreamClient> playback_mixers = queryPlaybackMixers();
+ if (!playback_mixers.isEmpty())
+ playback_mixer = playback_mixers.first();
+ }
+ return playback_mixer;
+}
+
+
+bool TimeShifter::setPlaybackMixer(const TQString &soundStreamClientID, const TQString &ch)
+{
+ m_PlaybackMixerID = soundStreamClientID;
+ m_PlaybackMixerChannel = ch;
+
+ ISoundStreamClient *playback_mixer = searchPlaybackMixer();
+
+ float oldVolume;
+ if (m_OrgStreamID.isValid()) {
+ queryPlaybackVolume(m_OrgStreamID, oldVolume);
+ sendStopPlayback(m_OrgStreamID);
+ sendReleasePlayback(m_OrgStreamID);
+ }
+
+ if (playback_mixer)
+ playback_mixer->preparePlayback(m_OrgStreamID, m_PlaybackMixerChannel, /*active*/true, /*start_imm*/false);
+
+ if (m_OrgStreamID.isValid()) {
+ sendStartPlayback(m_OrgStreamID);
+ sendPlaybackVolume(m_OrgStreamID, oldVolume);
+ }
+
+ return true;
+}
+
+
+void TimeShifter::setTempFile(const TQString &filename, TQ_UINT64 s)
+{
+ m_RingBuffer.clear();
+ m_RingBuffer.resize(m_TempFileName = filename, m_TempFileMaxSize = s);
+ m_PlaybackMetaData = SoundMetaData(0,0,0, i18n("internal stream, not stored"));
+ m_PlaybackDataLeftInBuffer = 0;
+}
+
+bool TimeShifter::getSoundStreamDescription(SoundStreamID id, TQString &descr) const
+{
+ if (id == m_NewStreamID) {
+ descr = name();
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+bool TimeShifter::startCaptureWithFormat(
+ SoundStreamID id,
+ const SoundFormat &proposed_format,
+ SoundFormat &real_format,
+ bool force_format
+)
+{
+ if (id == m_OrgStreamID) {
+ if (force_format && m_realSoundFormat != proposed_format) {
+ sendStopCapture(m_NewStreamID);
+ sendStartCaptureWithFormat(m_NewStreamID, proposed_format, m_realSoundFormat);
+ }
+ real_format = m_realSoundFormat;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool TimeShifter::stopCapture(SoundStreamID id)
+{
+ if (id == m_OrgStreamID) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+#include "timeshifter.moc"
diff --git a/plugins/timeshifter/timeshifter.h b/plugins/timeshifter/timeshifter.h
new file mode 100644
index 0000000..cada015
--- /dev/null
+++ b/plugins/timeshifter/timeshifter.h
@@ -0,0 +1,121 @@
+/***************************************************************************
+ timeshifter.h - description
+ -------------------
+ begin : May 16 2005
+ copyright : (C) 2005 Ernst 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_TIMESHIFTER_H
+#define KRADIO_TIMESHIFTER_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/plugins.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+#include "../../src/include/fileringbuffer.h"
+
+
+class TimeShifter : public TQObject,
+ public PluginBase,
+ public ISoundStreamClient
+{
+Q_OBJECT
+
+public:
+ TimeShifter (const TQString &name);
+ virtual ~TimeShifter ();
+
+ virtual bool connectI (Interface *);
+ virtual bool disconnectI (Interface *);
+
+ virtual TQString pluginClassName() const { return "TimeShifter"; }
+
+ virtual const TQString &name() const { return PluginBase::name(); }
+ virtual TQString &name() { return PluginBase::name(); }
+
+ // config
+
+ const TQString &getPlaybackMixer() const { return m_PlaybackMixerID; }
+ const TQString &getPlaybackMixerChannel() const { return m_PlaybackMixerChannel; }
+ const TQString &getTempFileName() const { return m_TempFileName; }
+ TQ_UINT64 getTempFileMaxSize() const { return m_TempFileMaxSize; }
+
+ void setTempFile(const TQString &filename, TQ_UINT64 s);
+ bool setPlaybackMixer(const TQString &soundStreamClientID, const TQString &ch);
+
+ // PluginBase
+
+public:
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+
+ virtual ConfigPageInfo createConfigurationPage();
+ virtual AboutPageInfo createAboutPage();
+
+protected:
+
+ ISoundStreamClient *searchPlaybackMixer();
+
+ size_t writeMetaDataToBuffer(const SoundMetaData &md, char *buffer, size_t buffer_size);
+ size_t readMetaDataFromBuffer(SoundMetaData &md, const char *buffer, size_t buffer_size);
+ void skipPacketInRingBuffer();
+
+ // SoundStreamClient
+ void noticeConnectedI (ISoundStreamServer *s, bool pointer_valid);
+
+ bool startCaptureWithFormat(SoundStreamID id,
+ const SoundFormat &proposed_format,
+ SoundFormat &real_format,
+ bool force_format);
+ bool stopCapture(SoundStreamID id);
+ bool noticeSoundStreamClosed(SoundStreamID id);
+ bool startPlayback(SoundStreamID id);
+ bool stopPlayback(SoundStreamID id);
+ bool pausePlayback(SoundStreamID id);
+ bool noticeSoundStreamData(SoundStreamID id, const SoundFormat &sf, const char *data, size_t size, size_t &consumed_size, const SoundMetaData &md);
+ bool noticeReadyForPlaybackData(SoundStreamID id, size_t size);
+
+ bool getSoundStreamDescription(SoundStreamID id, TQString &descr) const;
+
+ // FIXME: react on redirect request
+
+signals:
+
+ void sigUpdateConfig();
+
+protected:
+
+ TQString m_TempFileName;
+ size_t m_TempFileMaxSize;
+ SoundFormat m_SoundFormat;
+ SoundFormat m_realSoundFormat;
+
+ TQString m_PlaybackMixerID;
+ TQString m_PlaybackMixerChannel;
+
+ TQString m_StreamFile;
+ bool m_StreamPaused;
+ SoundStreamID m_OrgStreamID;
+ SoundStreamID m_NewStreamID;
+ SoundFormat m_RealSoundFormat;
+ float m_orgVolume;
+
+ SoundMetaData m_PlaybackMetaData;
+ size_t m_PlaybackDataLeftInBuffer;
+
+ FileRingBuffer m_RingBuffer;
+};
+
+#endif
diff --git a/plugins/v4lradio/CMakeL10n.txt b/plugins/v4lradio/CMakeL10n.txt
new file mode 100644
index 0000000..5501e1b
--- /dev/null
+++ b/plugins/v4lradio/CMakeL10n.txt
@@ -0,0 +1,6 @@
+##### create translation templates ##############
+
+tde_l10n_create_template(
+ CATALOG "tderadio-v4lradio"
+ DESTINATION "po"
+)
diff --git a/plugins/v4lradio/Makefile.am b/plugins/v4lradio/Makefile.am
new file mode 100644
index 0000000..1a991d6
--- /dev/null
+++ b/plugins/v4lradio/Makefile.am
@@ -0,0 +1,18 @@
+SUBDIRS = po .
+
+INCLUDES = $(all_includes)
+METASOURCES = AUTO
+
+libtderadio_LTLIBRARIES = libv4lradio.la
+libv4lradio_la_SOURCES = v4lcfg_interfaces.cpp v4lradio-configuration.cpp \
+ v4lradio-configuration-ui.ui v4lradio.cpp
+libv4lradio_la_LDFLAGS = -module -avoid-version $(KDE_RPATH) $(all_libraries)
+
+noinst_HEADERS = v4lcfg_interfaces.h v4lradio-configuration.h v4lradio.h
+
+#messages: rc.cpp
+# $(XGETTEXT) *.cpp *.h -o po/tderadio-v4lradio.pot
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o po/tderadio-v4lradio.pot
diff --git a/plugins/v4lradio/linux/videodev.h b/plugins/v4lradio/linux/videodev.h
new file mode 100644
index 0000000..291c2f2
--- /dev/null
+++ b/plugins/v4lradio/linux/videodev.h
@@ -0,0 +1,426 @@
+#ifndef __LINUX_VIDEODEV_H
+#define __LINUX_VIDEODEV_H
+
+#include <linux/types.h>
+#include <linux/version.h>
+//#include <linux/device.h>
+
+//#define HAVE_V4L2 1
+//#include <linux/videodev2.h>
+
+#ifdef __KERNEL__
+
+#include <linux/poll.h>
+#include <linux/mm.h>
+
+struct video_device
+{
+ /* device info */
+ struct device *dev;
+ char name[32];
+ int type; /* v4l1 */
+ int type2; /* v4l2 */
+ int hardware;
+ int minor;
+
+ /* device ops + callbacks */
+ struct file_operations *fops;
+ void (*release)(struct video_device *vfd);
+
+
+#if 1 /* to be removed in 2.7.x */
+ /* obsolete -- fops->owner is used instead */
+ struct module *owner;
+ /* dev->driver_data will be used instead some day.
+ * Use the video_{get|set}_drvdata() helper functions,
+ * so the switch over will be transparent for you.
+ * Or use {pci|usb}_{get|set}_drvdata() directly. */
+ void *priv;
+#endif
+
+ /* for videodev.c intenal usage -- please don't touch */
+ int users; /* video_exclusive_{open|close} ... */
+ struct semaphore lock; /* ... helper function uses these */
+ char devfs_name[64]; /* devfs */
+ struct class_device class_dev; /* sysfs */
+};
+
+#define VIDEO_MAJOR 81
+
+#define VFL_TYPE_GRABBER 0
+#define VFL_TYPE_VBI 1
+#define VFL_TYPE_RADIO 2
+#define VFL_TYPE_VTX 3
+
+extern int video_register_device(struct video_device *, int type, int nr);
+extern void video_unregister_device(struct video_device *);
+extern struct video_device* video_devdata(struct file*);
+
+#define to_video_device(cd) container_of(cd, struct video_device, class_dev)
+static inline void
+video_device_create_file(struct video_device *vfd,
+ struct class_device_attribute *attr)
+{
+ class_device_create_file(&vfd->class_dev, attr);
+}
+
+/* helper functions to alloc / release struct video_device, the
+ later can be used for video_device->release() */
+struct video_device *video_device_alloc(void);
+void video_device_release(struct video_device *vfd);
+
+/* helper functions to access driver private data. */
+static inline void *video_get_drvdata(struct video_device *dev)
+{
+ return dev->priv;
+}
+
+static inline void video_set_drvdata(struct video_device *dev, void *data)
+{
+ dev->priv = data;
+}
+
+extern int video_exclusive_open(struct inode *inode, struct file *file);
+extern int video_exclusive_release(struct inode *inode, struct file *file);
+extern int video_usercopy(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg,
+ int (*func)(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg));
+#endif /* __KERNEL__ */
+
+#define VID_TYPE_CAPTURE 1 /* Can capture */
+#define VID_TYPE_TUNER 2 /* Can tune */
+#define VID_TYPE_TELETEXT 4 /* Does teletext */
+#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */
+#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */
+#define VID_TYPE_CLIPPING 32 /* Can clip */
+#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */
+#define VID_TYPE_SCALES 128 /* Scalable */
+#define VID_TYPE_MONOCHROME 256 /* Monochrome only */
+#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */
+#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */
+#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */
+#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */
+#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */
+
+struct video_capability
+{
+ char name[32];
+ int type;
+ int channels; /* Num channels */
+ int audios; /* Num audio devices */
+ int maxwidth; /* Supported width */
+ int maxheight; /* And height */
+ int minwidth; /* Supported width */
+ int minheight; /* And height */
+};
+
+
+struct video_channel
+{
+ int channel;
+ char name[32];
+ int tuners;
+ __u32 flags;
+#define VIDEO_VC_TUNER 1 /* Channel has a tuner */
+#define VIDEO_VC_AUDIO 2 /* Channel has audio */
+ __u16 type;
+#define VIDEO_TYPE_TV 1
+#define VIDEO_TYPE_CAMERA 2
+ __u16 norm; /* Norm set by channel */
+};
+
+struct video_tuner
+{
+ int tuner;
+ char name[32];
+ unsigned long rangelow, rangehigh; /* Tuner range */
+ __u32 flags;
+#define VIDEO_TUNER_PAL 1
+#define VIDEO_TUNER_NTSC 2
+#define VIDEO_TUNER_SECAM 4
+#define VIDEO_TUNER_LOW 8 /* Uses KHz not MHz */
+#define VIDEO_TUNER_NORM 16 /* Tuner can set norm */
+#define VIDEO_TUNER_STEREO_ON 128 /* Tuner is seeing stereo */
+#define VIDEO_TUNER_RDS_ON 256 /* Tuner is seeing an RDS datastream */
+#define VIDEO_TUNER_MBS_ON 512 /* Tuner is seeing an MBS datastream */
+ __u16 mode; /* PAL/NTSC/SECAM/OTHER */
+#define VIDEO_MODE_PAL 0
+#define VIDEO_MODE_NTSC 1
+#define VIDEO_MODE_SECAM 2
+#define VIDEO_MODE_AUTO 3
+ __u16 signal; /* Signal strength 16bit scale */
+};
+
+struct video_picture
+{
+ __u16 brightness;
+ __u16 hue;
+ __u16 colour;
+ __u16 contrast;
+ __u16 whiteness; /* Black and white only */
+ __u16 depth; /* Capture depth */
+ __u16 palette; /* Palette in use */
+#define VIDEO_PALETTE_GREY 1 /* Linear greyscale */
+#define VIDEO_PALETTE_HI240 2 /* High 240 cube (BT848) */
+#define VIDEO_PALETTE_RGB565 3 /* 565 16 bit RGB */
+#define VIDEO_PALETTE_RGB24 4 /* 24bit RGB */
+#define VIDEO_PALETTE_RGB32 5 /* 32bit RGB */
+#define VIDEO_PALETTE_RGB555 6 /* 555 15bit RGB */
+#define VIDEO_PALETTE_YUV422 7 /* YUV422 capture */
+#define VIDEO_PALETTE_YUYV 8
+#define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */
+#define VIDEO_PALETTE_YUV420 10
+#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */
+#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */
+#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */
+#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */
+#define VIDEO_PALETTE_YUV420P 15 /* YUV 4:2:0 Planar */
+#define VIDEO_PALETTE_YUV410P 16 /* YUV 4:1:0 Planar */
+#define VIDEO_PALETTE_PLANAR 13 /* start of planar entries */
+#define VIDEO_PALETTE_COMPONENT 7 /* start of component entries */
+};
+
+struct video_audio
+{
+ int audio; /* Audio channel */
+ __u16 volume; /* If settable */
+ __u16 bass, treble;
+ __u32 flags;
+#define VIDEO_AUDIO_MUTE 1
+#define VIDEO_AUDIO_MUTABLE 2
+#define VIDEO_AUDIO_VOLUME 4
+#define VIDEO_AUDIO_BASS 8
+#define VIDEO_AUDIO_TREBLE 16
+#define VIDEO_AUDIO_BALANCE 32
+ char name[16];
+#define VIDEO_SOUND_MONO 1
+#define VIDEO_SOUND_STEREO 2
+#define VIDEO_SOUND_LANG1 4
+#define VIDEO_SOUND_LANG2 8
+ __u16 mode;
+ __u16 balance; /* Stereo balance */
+ __u16 step; /* Step actual volume uses */
+};
+
+struct video_clip
+{
+ __s32 x,y;
+ __s32 width, height;
+ struct video_clip *next; /* For user use/driver use only */
+};
+
+struct video_window
+{
+ __u32 x,y; /* Position of window */
+ __u32 width,height; /* Its size */
+ __u32 chromakey;
+ __u32 flags;
+ struct video_clip *clips; /* Set only */
+ int clipcount;
+#define VIDEO_WINDOW_INTERLACE 1
+#define VIDEO_WINDOW_CHROMAKEY 16 /* Overlay by chromakey */
+#define VIDEO_CLIP_BITMAP -1
+/* bitmap is 1024x625, a '1' bit represents a clipped pixel */
+#define VIDEO_CLIPMAP_SIZE (128 * 625)
+};
+
+struct video_capture
+{
+ __u32 x,y; /* Offsets into image */
+ __u32 width, height; /* Area to capture */
+ __u16 decimation; /* Decimation divider */
+ __u16 flags; /* Flags for capture */
+#define VIDEO_CAPTURE_ODD 0 /* Temporal */
+#define VIDEO_CAPTURE_EVEN 1
+};
+
+struct video_buffer
+{
+ void *base;
+ int height,width;
+ int depth;
+ int bytesperline;
+};
+
+struct video_mmap
+{
+ unsigned int frame; /* Frame (0 - n) for double buffer */
+ int height,width;
+ unsigned int format; /* should be VIDEO_PALETTE_* */
+};
+
+struct video_key
+{
+ __u8 key[8];
+ __u32 flags;
+};
+
+
+#define VIDEO_MAX_FRAME 32
+
+struct video_mbuf
+{
+ int size; /* Total memory to map */
+ int frames; /* Frames */
+ int offsets[VIDEO_MAX_FRAME];
+};
+
+
+#define VIDEO_NO_UNIT (-1)
+
+
+struct video_unit
+{
+ int video; /* Video minor */
+ int vbi; /* VBI minor */
+ int radio; /* Radio minor */
+ int audio; /* Audio minor */
+ int teletext; /* Teletext minor */
+};
+
+struct vbi_format {
+ __u32 sampling_rate; /* in Hz */
+ __u32 samples_per_line;
+ __u32 sample_format; /* VIDEO_PALETTE_RAW only (1 byte) */
+ __s32 start[2]; /* starting line for each frame */
+ __u32 count[2]; /* count of lines for each frame */
+ __u32 flags;
+#define VBI_UNSYNC 1 /* can distingues between top/bottom field */
+#define VBI_INTERLACED 2 /* lines are interlaced */
+};
+
+/* video_info is biased towards hardware mpeg encode/decode */
+/* but it could apply generically to any hardware compressor/decompressor */
+struct video_info
+{
+ __u32 frame_count; /* frames output since decode/encode began */
+ __u32 h_size; /* current unscaled horizontal size */
+ __u32 v_size; /* current unscaled veritcal size */
+ __u32 smpte_timecode; /* current SMPTE timecode (for current GOP) */
+ __u32 picture_type; /* current picture type */
+ __u32 temporal_reference; /* current temporal reference */
+ __u8 user_data[256]; /* user data last found in compressed stream */
+ /* user_data[0] contains user data flags, user_data[1] has count */
+};
+
+/* generic structure for setting playback modes */
+struct video_play_mode
+{
+ int mode;
+ int p1;
+ int p2;
+};
+
+/* for loading microcode / fpga programming */
+struct video_code
+{
+ char loadwhat[16]; /* name or tag of file being passed */
+ int datasize;
+ __u8 *data;
+};
+
+#define VIDIOCGCAP _IOR('v',1,struct video_capability) /* Get capabilities */
+#define VIDIOCGCHAN _IOWR('v',2,struct video_channel) /* Get channel info (sources) */
+#define VIDIOCSCHAN _IOW('v',3,struct video_channel) /* Set channel */
+#define VIDIOCGTUNER _IOWR('v',4,struct video_tuner) /* Get tuner abilities */
+#define VIDIOCSTUNER _IOW('v',5,struct video_tuner) /* Tune the tuner for the current channel */
+#define VIDIOCGPICT _IOR('v',6,struct video_picture) /* Get picture properties */
+#define VIDIOCSPICT _IOW('v',7,struct video_picture) /* Set picture properties */
+#define VIDIOCCAPTURE _IOW('v',8,int) /* Start, end capture */
+#define VIDIOCGWIN _IOR('v',9, struct video_window) /* Get the video overlay window */
+#define VIDIOCSWIN _IOW('v',10, struct video_window) /* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
+#define VIDIOCGFBUF _IOR('v',11, struct video_buffer) /* Get frame buffer */
+#define VIDIOCSFBUF _IOW('v',12, struct video_buffer) /* Set frame buffer - root only */
+#define VIDIOCKEY _IOR('v',13, struct video_key) /* Video key event - to dev 255 is to all - cuts capture on all DMA windows with this key (0xFFFFFFFF == all) */
+#define VIDIOCGFREQ _IOR('v',14, unsigned long) /* Set tuner */
+#define VIDIOCSFREQ _IOW('v',15, unsigned long) /* Set tuner */
+#define VIDIOCGAUDIO _IOR('v',16, struct video_audio) /* Get audio info */
+#define VIDIOCSAUDIO _IOW('v',17, struct video_audio) /* Audio source, mute etc */
+#define VIDIOCSYNC _IOW('v',18, int) /* Sync with mmap grabbing */
+#define VIDIOCMCAPTURE _IOW('v',19, struct video_mmap) /* Grab frames */
+#define VIDIOCGMBUF _IOR('v',20, struct video_mbuf) /* Memory map buffer info */
+#define VIDIOCGUNIT _IOR('v',21, struct video_unit) /* Get attached units */
+#define VIDIOCGCAPTURE _IOR('v',22, struct video_capture) /* Get subcapture */
+#define VIDIOCSCAPTURE _IOW('v',23, struct video_capture) /* Set subcapture */
+#define VIDIOCSPLAYMODE _IOW('v',24, struct video_play_mode) /* Set output video mode/feature */
+#define VIDIOCSWRITEMODE _IOW('v',25, int) /* Set write mode */
+#define VIDIOCGPLAYINFO _IOR('v',26, struct video_info) /* Get current playback info from hardware */
+#define VIDIOCSMICROCODE _IOW('v',27, struct video_code) /* Load microcode into hardware */
+#define VIDIOCGVBIFMT _IOR('v',28, struct vbi_format) /* Get VBI information */
+#define VIDIOCSVBIFMT _IOW('v',29, struct vbi_format) /* Set VBI information */
+
+
+#define BASE_VIDIOCPRIVATE 192 /* 192-255 are private */
+
+/* VIDIOCSWRITEMODE */
+#define VID_WRITE_MPEG_AUD 0
+#define VID_WRITE_MPEG_VID 1
+#define VID_WRITE_OSD 2
+#define VID_WRITE_TTX 3
+#define VID_WRITE_CC 4
+#define VID_WRITE_MJPEG 5
+
+/* VIDIOCSPLAYMODE */
+#define VID_PLAY_VID_OUT_MODE 0
+ /* p1: = VIDEO_MODE_PAL, VIDEO_MODE_NTSC, etc ... */
+#define VID_PLAY_GENLOCK 1
+ /* p1: 0 = OFF, 1 = ON */
+ /* p2: GENLOCK FINE DELAY value */
+#define VID_PLAY_NORMAL 2
+#define VID_PLAY_PAUSE 3
+#define VID_PLAY_SINGLE_FRAME 4
+#define VID_PLAY_FAST_FORWARD 5
+#define VID_PLAY_SLOW_MOTION 6
+#define VID_PLAY_IMMEDIATE_NORMAL 7
+#define VID_PLAY_SWITCH_CHANNELS 8
+#define VID_PLAY_FREEZE_FRAME 9
+#define VID_PLAY_STILL_MODE 10
+#define VID_PLAY_MASTER_MODE 11
+ /* p1: see below */
+#define VID_PLAY_MASTER_NONE 1
+#define VID_PLAY_MASTER_VIDEO 2
+#define VID_PLAY_MASTER_AUDIO 3
+#define VID_PLAY_ACTIVE_SCANLINES 12
+ /* p1 = first active; p2 = last active */
+#define VID_PLAY_RESET 13
+#define VID_PLAY_END_MARK 14
+
+
+
+#define VID_HARDWARE_BT848 1
+#define VID_HARDWARE_TQCAM_BW 2
+#define VID_HARDWARE_PMS 3
+#define VID_HARDWARE_TQCAM_C 4
+#define VID_HARDWARE_PSEUDO 5
+#define VID_HARDWARE_SAA5249 6
+#define VID_HARDWARE_AZTECH 7
+#define VID_HARDWARE_SF16MI 8
+#define VID_HARDWARE_RTRACK 9
+#define VID_HARDWARE_ZOLTRIX 10
+#define VID_HARDWARE_SAA7146 11
+#define VID_HARDWARE_VIDEUM 12 /* Reserved for Winnov videum */
+#define VID_HARDWARE_RTRACK2 13
+#define VID_HARDWARE_PERMEDIA2 14 /* Reserved for Permedia2 */
+#define VID_HARDWARE_RIVA128 15 /* Reserved for RIVA 128 */
+#define VID_HARDWARE_PLANB 16 /* PowerMac motherboard video-in */
+#define VID_HARDWARE_BROADWAY 17 /* Broadway project */
+#define VID_HARDWARE_GEMTEK 18
+#define VID_HARDWARE_TYPHOON 19
+#define VID_HARDWARE_VINO 20 /* SGI Indy Vino */
+#define VID_HARDWARE_CADET 21 /* Cadet radio */
+#define VID_HARDWARE_TRUST 22 /* Trust FM Radio */
+#define VID_HARDWARE_TERRATEC 23 /* TerraTec ActiveRadio */
+#define VID_HARDWARE_CPIA 24
+#define VID_HARDWARE_ZR36120 25 /* Zoran ZR36120/ZR36125 */
+#define VID_HARDWARE_ZR36067 26 /* Zoran ZR36067/36060 */
+#define VID_HARDWARE_OV511 27
+#define VID_HARDWARE_ZR356700 28 /* Zoran 36700 series */
+#define VID_HARDWARE_W9966 29
+#define VID_HARDWARE_SE401 30 /* SE401 USB webcams */
+#define VID_HARDWARE_PWC 31 /* Philips webcams */
+#define VID_HARDWARE_MEYE 32 /* Sony Vaio MotionEye cameras */
+#define VID_HARDWARE_CPIA2 33
+#define VID_HARDWARE_VICAM 34
+#define VID_HARDWARE_SF16FMR2 35
+#endif /* __LINUX_VIDEODEV_H */
diff --git a/plugins/v4lradio/linux/videodev2.h b/plugins/v4lradio/linux/videodev2.h
new file mode 100644
index 0000000..2ad6a9d
--- /dev/null
+++ b/plugins/v4lradio/linux/videodev2.h
@@ -0,0 +1,934 @@
+#ifndef __LINUX_VIDEODEV2_H
+#define __LINUX_VIDEODEV2_H
+/*
+ * Video for Linux Two
+ *
+ * Header file for v4l or V4L2 drivers and applications, for
+ * Linux kernels 2.2.x or 2.4.x.
+ *
+ * See http://bytesex.org/v4l/ for API specs and other
+ * v4l2 documentation.
+ *
+ * Author: Bill Dirks <bdirks@pacbell.net>
+ * Justin Schoeman
+ * et al.
+ */
+
+#include <asm/types.h>
+#ifdef __KERNEL__
+#include <linux/time.h> /* need struct timeval */
+#endif
+
+/*
+ * M I S C E L L A N E O U S
+ */
+
+/* Four-character-code (FOURCC) */
+#define v4l2_fourcc(a,b,c,d)\
+ (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24))
+
+/*
+ * E N U M S
+ */
+enum v4l2_field {
+ V4L2_FIELD_ANY = 0, /* driver can choose from none,
+ top, bottom, interlaced
+ depending on whatever it thinks
+ is approximate ... */
+ V4L2_FIELD_NONE = 1, /* this device has no fields ... */
+ V4L2_FIELD_TOP = 2, /* top field only */
+ V4L2_FIELD_BOTTOM = 3, /* bottom field only */
+ V4L2_FIELD_INTERLACED = 4, /* both fields interlaced */
+ V4L2_FIELD_SEQ_TB = 5, /* both fields sequential into one
+ buffer, top-bottom order */
+ V4L2_FIELD_SEQ_BT = 6, /* same as above + bottom-top order */
+ V4L2_FIELD_ALTERNATE = 7 /* both fields alternating into
+ separate buffers */
+};
+#define V4L2_FIELD_HAS_TOP(field) \
+ ((field) == V4L2_FIELD_TOP ||\
+ (field) == V4L2_FIELD_INTERLACED ||\
+ (field) == V4L2_FIELD_SEQ_TB ||\
+ (field) == V4L2_FIELD_SEQ_BT)
+#define V4L2_FIELD_HAS_BOTTOM(field) \
+ ((field) == V4L2_FIELD_BOTTOM ||\
+ (field) == V4L2_FIELD_INTERLACED ||\
+ (field) == V4L2_FIELD_SEQ_TB ||\
+ (field) == V4L2_FIELD_SEQ_BT)
+#define V4L2_FIELD_HAS_BOTH(field) \
+ ((field) == V4L2_FIELD_INTERLACED ||\
+ (field) == V4L2_FIELD_SEQ_TB ||\
+ (field) == V4L2_FIELD_SEQ_BT)
+
+enum v4l2_buf_type {
+ V4L2_BUF_TYPE_VIDEO_CAPTURE = 1,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT = 2,
+ V4L2_BUF_TYPE_VIDEO_OVERLAY = 3,
+ V4L2_BUF_TYPE_VBI_CAPTURE = 4,
+ V4L2_BUF_TYPE_VBI_OUTPUT = 5,
+ V4L2_BUF_TYPE_PRIVATE = 0x80
+};
+
+enum v4l2_ctrl_type {
+ V4L2_CTRL_TYPE_INTEGER = 1,
+ V4L2_CTRL_TYPE_BOOLEAN = 2,
+ V4L2_CTRL_TYPE_MENU = 3,
+ V4L2_CTRL_TYPE_BUTTON = 4
+};
+
+enum v4l2_tuner_type {
+ V4L2_TUNER_RADIO = 1,
+ V4L2_TUNER_ANALOG_TV = 2
+};
+
+enum v4l2_memory {
+ V4L2_MEMORY_MMAP = 1,
+ V4L2_MEMORY_USERPTR = 2,
+ V4L2_MEMORY_OVERLAY = 3
+};
+
+/* see also http://vektor.theorem.ca/graphics/ycbcr/ */
+enum v4l2_colorspace {
+ /* ITU-R 601 -- broadcast NTSC/PAL */
+ V4L2_COLORSPACE_SMPTE170M = 1,
+
+ /* 1125-Line (US) HDTV */
+ V4L2_COLORSPACE_SMPTE240M = 2,
+
+ /* HD and modern captures. */
+ V4L2_COLORSPACE_REC709 = 3,
+
+ /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */
+ V4L2_COLORSPACE_BT878 = 4,
+
+ /* These should be useful. Assume 601 extents. */
+ V4L2_COLORSPACE_470_SYSTEM_M = 5,
+ V4L2_COLORSPACE_470_SYSTEM_BG = 6,
+
+ /* I know there will be cameras that send this. So, this is
+ * unspecified chromaticities and full 0-255 on each of the
+ * Y'CbCr components
+ */
+ V4L2_COLORSPACE_JPEG = 7,
+
+ /* For RGB colourspaces, this is probably a good start. */
+ V4L2_COLORSPACE_SRGB = 8
+};
+
+enum v4l2_priority {
+ V4L2_PRIORITY_UNSET = 0, /* not initialized */
+ V4L2_PRIORITY_BACKGROUND = 1,
+ V4L2_PRIORITY_INTERACTIVE = 2,
+ V4L2_PRIORITY_RECORD = 3,
+ V4L2_PRIORITY_DEFAULT = V4L2_PRIORITY_INTERACTIVE
+};
+
+struct v4l2_rect {
+ __s32 left;
+ __s32 top;
+ __s32 width;
+ __s32 height;
+};
+
+struct v4l2_fract {
+ __u32 numerator;
+ __u32 denominator;
+};
+
+/*
+ * D R I V E R C A P A B I L I T I E S
+ */
+struct v4l2_capability
+{
+ __u8 driver[16]; /* i.e. "bttv" */
+ __u8 card[32]; /* i.e. "Hauppauge WinTV" */
+ __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */
+ __u32 version; /* should use KERNEL_VERSION() */
+ __u32 capabilities; /* Device capabilities */
+ __u32 reserved[4];
+};
+
+/* Values for 'capabilities' field */
+#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */
+#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */
+#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */
+#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a VBI capture device */
+#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a VBI output device */
+#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */
+
+#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
+#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
+#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */
+
+#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */
+#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */
+#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */
+
+/*
+ * V I D E O I M A G E F O R M A T
+ */
+
+struct v4l2_pix_format
+{
+ __u32 width;
+ __u32 height;
+ __u32 pixelformat;
+ enum v4l2_field field;
+ __u32 bytesperline; /* for padding, zero if unused */
+ __u32 sizeimage;
+ enum v4l2_colorspace colorspace;
+ __u32 priv; /* private data, depends on pixelformat */
+};
+
+/* Pixel format FOURCC depth Description */
+#define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R','G','B','1') /* 8 RGB-3-3-2 */
+#define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R','G','B','O') /* 16 RGB-5-5-5 */
+#define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R','G','B','P') /* 16 RGB-5-6-5 */
+#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R','G','B','Q') /* 16 RGB-5-5-5 BE */
+#define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R','G','B','R') /* 16 RGB-5-6-5 BE */
+#define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B','G','R','3') /* 24 BGR-8-8-8 */
+#define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R','G','B','3') /* 24 RGB-8-8-8 */
+#define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B','G','R','4') /* 32 BGR-8-8-8-8 */
+#define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R','G','B','4') /* 32 RGB-8-8-8-8 */
+#define V4L2_PIX_FMT_GREY v4l2_fourcc('G','R','E','Y') /* 8 Greyscale */
+#define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y','V','U','9') /* 9 YVU 4:1:0 */
+#define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */
+#define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y','U','Y','V') /* 16 YUV 4:2:2 */
+#define V4L2_PIX_FMT_UYVY v4l2_fourcc('U','Y','V','Y') /* 16 YUV 4:2:2 */
+#define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4','2','2','P') /* 16 YVU422 planar */
+#define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4','1','1','P') /* 16 YVU411 planar */
+#define V4L2_PIX_FMT_Y41P v4l2_fourcc('Y','4','1','P') /* 12 YUV 4:1:1 */
+
+/* two planes -- one Y, one Cr + Cb interleaved */
+#define V4L2_PIX_FMT_NV12 v4l2_fourcc('N','V','1','2') /* 12 Y/CbCr 4:2:0 */
+#define V4L2_PIX_FMT_NV21 v4l2_fourcc('N','V','2','1') /* 12 Y/CrCb 4:2:0 */
+
+/* The following formats are not defined in the V4L2 specification */
+#define V4L2_PIX_FMT_YUV410 v4l2_fourcc('Y','U','V','9') /* 9 YUV 4:1:0 */
+#define V4L2_PIX_FMT_YUV420 v4l2_fourcc('Y','U','1','2') /* 12 YUV 4:2:0 */
+#define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y','Y','U','V') /* 16 YUV 4:2:2 */
+#define V4L2_PIX_FMT_HI240 v4l2_fourcc('H','I','2','4') /* 8 8-bit color */
+
+/* compressed formats */
+#define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M','J','P','G') /* Motion-JPEG */
+#define V4L2_PIX_FMT_JPEG v4l2_fourcc('J','P','E','G') /* JFIF JPEG */
+#define V4L2_PIX_FMT_DV v4l2_fourcc('d','v','s','d') /* 1394 */
+#define V4L2_PIX_FMT_MPEG v4l2_fourcc('M','P','E','G') /* MPEG */
+
+/* Vendor-specific formats */
+#define V4L2_PIX_FMT_WNVA v4l2_fourcc('W','N','V','A') /* Winnov hw compress */
+
+/*
+ * F O R M A T E N U M E R A T I O N
+ */
+struct v4l2_fmtdesc
+{
+ __u32 index; /* Format number */
+ enum v4l2_buf_type type; /* buffer type */
+ __u32 flags;
+ __u8 description[32]; /* Description string */
+ __u32 pixelformat; /* Format fourcc */
+ __u32 reserved[4];
+};
+
+#define V4L2_FMT_FLAG_COMPRESSED 0x0001
+
+
+/*
+ * T I M E C O D E
+ */
+struct v4l2_timecode
+{
+ __u32 type;
+ __u32 flags;
+ __u8 frames;
+ __u8 seconds;
+ __u8 minutes;
+ __u8 hours;
+ __u8 userbits[4];
+};
+
+/* Type */
+#define V4L2_TC_TYPE_24FPS 1
+#define V4L2_TC_TYPE_25FPS 2
+#define V4L2_TC_TYPE_30FPS 3
+#define V4L2_TC_TYPE_50FPS 4
+#define V4L2_TC_TYPE_60FPS 5
+
+/* Flags */
+#define V4L2_TC_FLAG_DROPFRAME 0x0001 /* "drop-frame" mode */
+#define V4L2_TC_FLAG_COLORFRAME 0x0002
+#define V4L2_TC_USERBITS_field 0x000C
+#define V4L2_TC_USERBITS_USERDEFINED 0x0000
+#define V4L2_TC_USERBITS_8BITCHARS 0x0008
+/* The above is based on SMPTE timecodes */
+
+
+/*
+ * C O M P R E S S I O N P A R A M E T E R S
+ */
+#if 0
+/* ### generic compression settings don't work, there is too much
+ * ### codec-specific stuff. Maybe reuse that for MPEG codec settings
+ * ### later ... */
+struct v4l2_compression
+{
+ __u32 quality;
+ __u32 keyframerate;
+ __u32 pframerate;
+ __u32 reserved[5];
+
+/* what we'll need for MPEG, extracted from some postings on
+ the v4l list (Gert Vervoort, PlasmaJohn).
+
+system stream:
+ - type: elementary stream(ES), packatised elementary stream(s) (PES)
+ program stream(PS), transport stream(TS)
+ - system bitrate
+ - PS packet size (DVD: 2048 bytes, VCD: 2324 bytes)
+ - TS video PID
+ - TS audio PID
+ - TS PCR PID
+ - TS system information tables (PAT, PMT, CAT, NIT and SIT)
+ - (MPEG-1 systems stream vs. MPEG-2 program stream (TS not supported
+ by MPEG-1 systems)
+
+audio:
+ - type: MPEG (+Layer I,II,III), AC-3, LPCM
+ - bitrate
+ - sampling frequency (DVD: 48 Khz, VCD: 44.1 KHz, 32 kHz)
+ - Trick Modes? (ff, rew)
+ - Copyright
+ - Inverse Telecine
+
+video:
+ - picturesize (SIF, 1/2 D1, 2/3 D1, D1) and PAL/NTSC norm can be set
+ through excisting V4L2 controls
+ - noise reduction, parameters encoder specific?
+ - MPEG video version: MPEG-1, MPEG-2
+ - GOP (Group Of Pictures) definition:
+ - N: number of frames per GOP
+ - M: distance between reference (I,P) frames
+ - open/closed GOP
+ - quantiser matrix: inter Q matrix (64 bytes) and intra Q matrix (64 bytes)
+ - quantiser scale: linear or logarithmic
+ - scanning: alternate or zigzag
+ - bitrate mode: CBR (constant bitrate) or VBR (variable bitrate).
+ - target video bitrate for CBR
+ - target video bitrate for VBR
+ - maximum video bitrate for VBR - min. quantiser value for VBR
+ - max. quantiser value for VBR
+ - adaptive quantisation value
+ - return the number of bytes per GOP or bitrate for bitrate monitoring
+
+*/
+};
+#endif
+
+struct v4l2_jpegcompression
+{
+ int quality;
+
+ int APPn; /* Number of APP segment to be written,
+ * must be 0..15 */
+ int APP_len; /* Length of data in JPEG APPn segment */
+ char APP_data[60]; /* Data in the JPEG APPn segment. */
+
+ int COM_len; /* Length of data in JPEG COM segment */
+ char COM_data[60]; /* Data in JPEG COM segment */
+
+ __u32 jpeg_markers; /* Which markers should go into the JPEG
+ * output. Unless you exactly know what
+ * you do, leave them untouched.
+ * Inluding less markers will make the
+ * resulting code smaller, but there will
+ * be fewer aplications which can read it.
+ * The presence of the APP and COM marker
+ * is influenced by APP_len and COM_len
+ * ONLY, not by this property! */
+
+#define V4L2_JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */
+#define V4L2_JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */
+#define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */
+#define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */
+#define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will
+ * allways use APP0 */
+};
+
+
+/*
+ * M E M O R Y - M A P P I N G B U F F E R S
+ */
+struct v4l2_requestbuffers
+{
+ __u32 count;
+ enum v4l2_buf_type type;
+ enum v4l2_memory memory;
+ __u32 reserved[2];
+};
+
+struct v4l2_buffer
+{
+ __u32 index;
+ enum v4l2_buf_type type;
+ __u32 bytesused;
+ __u32 flags;
+ enum v4l2_field field;
+ struct timeval timestamp;
+ struct v4l2_timecode timecode;
+ __u32 sequence;
+
+ /* memory location */
+ enum v4l2_memory memory;
+ union {
+ __u32 offset;
+ unsigned long userptr;
+ } m;
+ __u32 length;
+
+ __u32 reserved[2];
+};
+
+/* Flags for 'flags' field */
+#define V4L2_BUF_FLAG_MAPPED 0x0001 /* Buffer is mapped (flag) */
+#define V4L2_BUF_FLAG_QUEUED 0x0002 /* Buffer is queued for processing */
+#define V4L2_BUF_FLAG_DONE 0x0004 /* Buffer is ready */
+#define V4L2_BUF_FLAG_KEYFRAME 0x0008 /* Image is a keyframe (I-frame) */
+#define V4L2_BUF_FLAG_PFRAME 0x0010 /* Image is a P-frame */
+#define V4L2_BUF_FLAG_BFRAME 0x0020 /* Image is a B-frame */
+#define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */
+
+/*
+ * O V E R L A Y P R E V I E W
+ */
+struct v4l2_framebuffer
+{
+ __u32 capability;
+ __u32 flags;
+/* FIXME: in theory we should pass something like PCI device + memory
+ * region + offset instead of some physical address */
+ void* base;
+ struct v4l2_pix_format fmt;
+};
+/* Flags for the 'capability' field. Read only */
+#define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001
+#define V4L2_FBUF_CAP_CHROMAKEY 0x0002
+#define V4L2_FBUF_CAP_LIST_CLIPPING 0x0004
+#define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008
+/* Flags for the 'flags' field. */
+#define V4L2_FBUF_FLAG_PRIMARY 0x0001
+#define V4L2_FBUF_FLAG_OVERLAY 0x0002
+#define V4L2_FBUF_FLAG_CHROMAKEY 0x0004
+
+struct v4l2_clip
+{
+ struct v4l2_rect c;
+ struct v4l2_clip *next;
+};
+
+struct v4l2_window
+{
+ struct v4l2_rect w;
+ enum v4l2_field field;
+ __u32 chromakey;
+ struct v4l2_clip *clips;
+ __u32 clipcount;
+ void *bitmap;
+};
+
+
+/*
+ * C A P T U R E P A R A M E T E R S
+ */
+struct v4l2_captureparm
+{
+ __u32 capability; /* Supported modes */
+ __u32 capturemode; /* Current mode */
+ struct v4l2_fract timeperframe; /* Time per frame in .1us units */
+ __u32 extendedmode; /* Driver-specific extensions */
+ __u32 readbuffers; /* # of buffers for read */
+ __u32 reserved[4];
+};
+/* Flags for 'capability' and 'capturemode' fields */
+#define V4L2_MODE_HIGHQUALITY 0x0001 /* High quality imaging mode */
+#define V4L2_CAP_TIMEPERFRAME 0x1000 /* timeperframe field is supported */
+
+struct v4l2_outputparm
+{
+ __u32 capability; /* Supported modes */
+ __u32 outputmode; /* Current mode */
+ struct v4l2_fract timeperframe; /* Time per frame in seconds */
+ __u32 extendedmode; /* Driver-specific extensions */
+ __u32 writebuffers; /* # of buffers for write */
+ __u32 reserved[4];
+};
+
+/*
+ * I N P U T I M A G E C R O P P I N G
+ */
+
+struct v4l2_cropcap {
+ enum v4l2_buf_type type;
+ struct v4l2_rect bounds;
+ struct v4l2_rect defrect;
+ struct v4l2_fract pixelaspect;
+};
+
+struct v4l2_crop {
+ enum v4l2_buf_type type;
+ struct v4l2_rect c;
+};
+
+/*
+ * A N A L O G V I D E O S T A N D A R D
+ */
+
+typedef unsigned long long v4l2_std_id;
+
+/* one bit for each */
+#define V4L2_STD_PAL_B ((v4l2_std_id)0x00000001)
+#define V4L2_STD_PAL_B1 ((v4l2_std_id)0x00000002)
+#define V4L2_STD_PAL_G ((v4l2_std_id)0x00000004)
+#define V4L2_STD_PAL_H ((v4l2_std_id)0x00000008)
+#define V4L2_STD_PAL_I ((v4l2_std_id)0x00000010)
+#define V4L2_STD_PAL_D ((v4l2_std_id)0x00000020)
+#define V4L2_STD_PAL_D1 ((v4l2_std_id)0x00000040)
+#define V4L2_STD_PAL_K ((v4l2_std_id)0x00000080)
+
+#define V4L2_STD_PAL_M ((v4l2_std_id)0x00000100)
+#define V4L2_STD_PAL_N ((v4l2_std_id)0x00000200)
+#define V4L2_STD_PAL_Nc ((v4l2_std_id)0x00000400)
+#define V4L2_STD_PAL_60 ((v4l2_std_id)0x00000800)
+
+#define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000)
+#define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000)
+
+#define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000)
+#define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000)
+#define V4L2_STD_SECAM_G ((v4l2_std_id)0x00040000)
+#define V4L2_STD_SECAM_H ((v4l2_std_id)0x00080000)
+#define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000)
+#define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000)
+#define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000)
+
+/* ATSC/HDTV */
+#define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000)
+#define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000)
+
+/* some common needed stuff */
+#define V4L2_STD_PAL_BG (V4L2_STD_PAL_B |\
+ V4L2_STD_PAL_B1 |\
+ V4L2_STD_PAL_G)
+#define V4L2_STD_PAL_DK (V4L2_STD_PAL_D |\
+ V4L2_STD_PAL_D1 |\
+ V4L2_STD_PAL_K)
+#define V4L2_STD_PAL (V4L2_STD_PAL_BG |\
+ V4L2_STD_PAL_DK |\
+ V4L2_STD_PAL_H |\
+ V4L2_STD_PAL_I)
+#define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\
+ V4L2_STD_NTSC_M_JP)
+#define V4L2_STD_SECAM (V4L2_STD_SECAM_B |\
+ V4L2_STD_SECAM_D |\
+ V4L2_STD_SECAM_G |\
+ V4L2_STD_SECAM_H |\
+ V4L2_STD_SECAM_K |\
+ V4L2_STD_SECAM_K1 |\
+ V4L2_STD_SECAM_L)
+
+#define V4L2_STD_525_60 (V4L2_STD_PAL_M |\
+ V4L2_STD_PAL_60 |\
+ V4L2_STD_NTSC)
+#define V4L2_STD_625_50 (V4L2_STD_PAL |\
+ V4L2_STD_PAL_N |\
+ V4L2_STD_PAL_Nc |\
+ V4L2_STD_SECAM)
+
+#define V4L2_STD_UNKNOWN 0
+#define V4L2_STD_ALL (V4L2_STD_525_60 |\
+ V4L2_STD_625_50)
+
+struct v4l2_standard
+{
+ __u32 index;
+ v4l2_std_id id;
+ __u8 name[24];
+ struct v4l2_fract frameperiod; /* Frames, not fields */
+ __u32 framelines;
+ __u32 reserved[4];
+};
+
+
+/*
+ * V I D E O I N P U T S
+ */
+struct v4l2_input
+{
+ __u32 index; /* Which input */
+ __u8 name[32]; /* Label */
+ __u32 type; /* Type of input */
+ __u32 audioset; /* Associated audios (bitfield) */
+ __u32 tuner; /* Associated tuner */
+ v4l2_std_id std;
+ __u32 status;
+ __u32 reserved[4];
+};
+/* Values for the 'type' field */
+#define V4L2_INPUT_TYPE_TUNER 1
+#define V4L2_INPUT_TYPE_CAMERA 2
+
+/* field 'status' - general */
+#define V4L2_IN_ST_NO_POWER 0x00000001 /* Attached device is off */
+#define V4L2_IN_ST_NO_SIGNAL 0x00000002
+#define V4L2_IN_ST_NO_COLOR 0x00000004
+
+/* field 'status' - analog */
+#define V4L2_IN_ST_NO_H_LOCK 0x00000100 /* No horizontal sync lock */
+#define V4L2_IN_ST_COLOR_KILL 0x00000200 /* Color killer is active */
+
+/* field 'status' - digital */
+#define V4L2_IN_ST_NO_SYNC 0x00010000 /* No synchronization lock */
+#define V4L2_IN_ST_NO_EQU 0x00020000 /* No equalizer lock */
+#define V4L2_IN_ST_NO_CARRIER 0x00040000 /* Carrier recovery failed */
+
+/* field 'status' - VCR and set-top box */
+#define V4L2_IN_ST_MACROVISION 0x01000000 /* Macrovision detected */
+#define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */
+#define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */
+
+/*
+ * V I D E O O U T P U T S
+ */
+struct v4l2_output
+{
+ __u32 index; /* Which output */
+ __u8 name[32]; /* Label */
+ __u32 type; /* Type of output */
+ __u32 audioset; /* Associated audios (bitfield) */
+ __u32 modulator; /* Associated modulator */
+ v4l2_std_id std;
+ __u32 reserved[4];
+};
+/* Values for the 'type' field */
+#define V4L2_OUTPUT_TYPE_MODULATOR 1
+#define V4L2_OUTPUT_TYPE_ANALOG 2
+#define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3
+
+/*
+ * C O N T R O L S
+ */
+struct v4l2_control
+{
+ __u32 id;
+ __s32 value;
+};
+
+/* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
+struct v4l2_queryctrl
+{
+ __u32 id;
+ enum v4l2_ctrl_type type;
+ __u8 name[32]; /* Whatever */
+ __s32 minimum; /* Note signedness */
+ __s32 maximum;
+ __s32 step;
+ __s32 default_value;
+ __u32 flags;
+ __u32 reserved[2];
+};
+
+/* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */
+struct v4l2_querymenu
+{
+ __u32 id;
+ __u32 index;
+ __u8 name[32]; /* Whatever */
+ __u32 reserved;
+};
+
+/* Control flags */
+#define V4L2_CTRL_FLAG_DISABLED 0x0001
+#define V4L2_CTRL_FLAG_GRABBED 0x0002
+
+/* Control IDs defined by V4L2 */
+#define V4L2_CID_BASE 0x00980900
+/* IDs reserved for driver specific controls */
+#define V4L2_CID_PRIVATE_BASE 0x08000000
+
+#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0)
+#define V4L2_CID_CONTRAST (V4L2_CID_BASE+1)
+#define V4L2_CID_SATURATION (V4L2_CID_BASE+2)
+#define V4L2_CID_HUE (V4L2_CID_BASE+3)
+#define V4L2_CID_AUDIO_VOLUME (V4L2_CID_BASE+5)
+#define V4L2_CID_AUDIO_BALANCE (V4L2_CID_BASE+6)
+#define V4L2_CID_AUDIO_BASS (V4L2_CID_BASE+7)
+#define V4L2_CID_AUDIO_TREBLE (V4L2_CID_BASE+8)
+#define V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9)
+#define V4L2_CID_AUDIO_LOUDNESS (V4L2_CID_BASE+10)
+#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11)
+#define V4L2_CID_AUTO_WHITE_BALANCE (V4L2_CID_BASE+12)
+#define V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13)
+#define V4L2_CID_RED_BALANCE (V4L2_CID_BASE+14)
+#define V4L2_CID_BLUE_BALANCE (V4L2_CID_BASE+15)
+#define V4L2_CID_GAMMA (V4L2_CID_BASE+16)
+#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* ? Not sure */
+#define V4L2_CID_EXPOSURE (V4L2_CID_BASE+17)
+#define V4L2_CID_AUTOGAIN (V4L2_CID_BASE+18)
+#define V4L2_CID_GAIN (V4L2_CID_BASE+19)
+#define V4L2_CID_HFLIP (V4L2_CID_BASE+20)
+#define V4L2_CID_VFLIP (V4L2_CID_BASE+21)
+#define V4L2_CID_HCENTER (V4L2_CID_BASE+22)
+#define V4L2_CID_VCENTER (V4L2_CID_BASE+23)
+#define V4L2_CID_LASTP1 (V4L2_CID_BASE+24) /* last CID + 1 */
+
+/*
+ * T U N I N G
+ */
+struct v4l2_tuner
+{
+ __u32 index;
+ __u8 name[32];
+ enum v4l2_tuner_type type;
+ __u32 capability;
+ __u32 rangelow;
+ __u32 rangehigh;
+ __u32 rxsubchans;
+ __u32 audmode;
+ __s32 signal;
+ __s32 afc;
+ __u32 reserved[4];
+};
+
+struct v4l2_modulator
+{
+ __u32 index;
+ __u8 name[32];
+ __u32 capability;
+ __u32 rangelow;
+ __u32 rangehigh;
+ __u32 txsubchans;
+ __u32 reserved[4];
+};
+
+/* Flags for the 'capability' field */
+#define V4L2_TUNER_CAP_LOW 0x0001
+#define V4L2_TUNER_CAP_NORM 0x0002
+#define V4L2_TUNER_CAP_STEREO 0x0010
+#define V4L2_TUNER_CAP_LANG2 0x0020
+#define V4L2_TUNER_CAP_SAP 0x0020
+#define V4L2_TUNER_CAP_LANG1 0x0040
+
+/* Flags for the 'rxsubchans' field */
+#define V4L2_TUNER_SUB_MONO 0x0001
+#define V4L2_TUNER_SUB_STEREO 0x0002
+#define V4L2_TUNER_SUB_LANG2 0x0004
+#define V4L2_TUNER_SUB_SAP 0x0004
+#define V4L2_TUNER_SUB_LANG1 0x0008
+
+/* Values for the 'audmode' field */
+#define V4L2_TUNER_MODE_MONO 0x0000
+#define V4L2_TUNER_MODE_STEREO 0x0001
+#define V4L2_TUNER_MODE_LANG2 0x0002
+#define V4L2_TUNER_MODE_SAP 0x0002
+#define V4L2_TUNER_MODE_LANG1 0x0003
+
+struct v4l2_frequency
+{
+ __u32 tuner;
+ enum v4l2_tuner_type type;
+ __u32 frequency;
+ __u32 reserved[8];
+};
+
+/*
+ * A U D I O
+ */
+struct v4l2_audio
+{
+ __u32 index;
+ __u8 name[32];
+ __u32 capability;
+ __u32 mode;
+ __u32 reserved[2];
+};
+/* Flags for the 'capability' field */
+#define V4L2_AUDCAP_STEREO 0x00001
+#define V4L2_AUDCAP_AVL 0x00002
+
+/* Flags for the 'mode' field */
+#define V4L2_AUDMODE_AVL 0x00001
+
+struct v4l2_audioout
+{
+ __u32 index;
+ __u8 name[32];
+ __u32 capability;
+ __u32 mode;
+ __u32 reserved[2];
+};
+
+/*
+ * D A T A S E R V I C E S ( V B I )
+ *
+ * Data services API by Michael Schimek
+ */
+
+struct v4l2_vbi_format
+{
+ __u32 sampling_rate; /* in 1 Hz */
+ __u32 offset;
+ __u32 samples_per_line;
+ __u32 sample_format; /* V4L2_PIX_FMT_* */
+ __s32 start[2];
+ __u32 count[2];
+ __u32 flags; /* V4L2_VBI_* */
+ __u32 reserved[2]; /* must be zero */
+};
+
+/* VBI flags */
+#define V4L2_VBI_UNSYNC (1<< 0)
+#define V4L2_VBI_INTERLACED (1<< 1)
+
+
+/*
+ * A G G R E G A T E S T R U C T U R E S
+ */
+
+/* Stream data format
+ */
+struct v4l2_format
+{
+ enum v4l2_buf_type type;
+ union
+ {
+ struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE
+ struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY
+ struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE
+ __u8 raw_data[200]; // user-defined
+ } fmt;
+};
+
+
+/* Stream type-dependent parameters
+ */
+struct v4l2_streamparm
+{
+ enum v4l2_buf_type type;
+ union
+ {
+ struct v4l2_captureparm capture;
+ struct v4l2_outputparm output;
+ __u8 raw_data[200]; /* user-defined */
+ } parm;
+};
+
+
+
+/*
+ * I O C T L C O D E S F O R V I D E O D E V I C E S
+ *
+ */
+#define VIDIOC_QUERYCAP _IOR ('V', 0, struct v4l2_capability)
+#define VIDIOC_RESERVED _IO ('V', 1)
+#define VIDIOC_ENUM_FMT _IOWR ('V', 2, struct v4l2_fmtdesc)
+#define VIDIOC_G_FMT _IOWR ('V', 4, struct v4l2_format)
+#define VIDIOC_S_FMT _IOWR ('V', 5, struct v4l2_format)
+#if 0
+#define VIDIOC_G_COMP _IOR ('V', 6, struct v4l2_compression)
+#define VIDIOC_S_COMP _IOW ('V', 7, struct v4l2_compression)
+#endif
+#define VIDIOC_REQBUFS _IOWR ('V', 8, struct v4l2_requestbuffers)
+#define VIDIOC_QUERYBUF _IOWR ('V', 9, struct v4l2_buffer)
+#define VIDIOC_G_FBUF _IOR ('V', 10, struct v4l2_framebuffer)
+#define VIDIOC_S_FBUF _IOW ('V', 11, struct v4l2_framebuffer)
+#define VIDIOC_OVERLAY _IOW ('V', 14, int)
+#define VIDIOC_TQBUF _IOWR ('V', 15, struct v4l2_buffer)
+#define VIDIOC_DTQBUF _IOWR ('V', 17, struct v4l2_buffer)
+#define VIDIOC_STREAMON _IOW ('V', 18, int)
+#define VIDIOC_STREAMOFF _IOW ('V', 19, int)
+#define VIDIOC_G_PARM _IOWR ('V', 21, struct v4l2_streamparm)
+#define VIDIOC_S_PARM _IOWR ('V', 22, struct v4l2_streamparm)
+#define VIDIOC_G_STD _IOR ('V', 23, v4l2_std_id)
+#define VIDIOC_S_STD _IOW ('V', 24, v4l2_std_id)
+#define VIDIOC_ENUMSTD _IOWR ('V', 25, struct v4l2_standard)
+#define VIDIOC_ENUMINPUT _IOWR ('V', 26, struct v4l2_input)
+#define VIDIOC_G_CTRL _IOWR ('V', 27, struct v4l2_control)
+#define VIDIOC_S_CTRL _IOWR ('V', 28, struct v4l2_control)
+#define VIDIOC_G_TUNER _IOWR ('V', 29, struct v4l2_tuner)
+#define VIDIOC_S_TUNER _IOW ('V', 30, struct v4l2_tuner)
+#define VIDIOC_G_AUDIO _IOR ('V', 33, struct v4l2_audio)
+#define VIDIOC_S_AUDIO _IOW ('V', 34, struct v4l2_audio)
+#define VIDIOC_QUERYCTRL _IOWR ('V', 36, struct v4l2_queryctrl)
+#define VIDIOC_QUERYMENU _IOWR ('V', 37, struct v4l2_querymenu)
+#define VIDIOC_G_INPUT _IOR ('V', 38, int)
+#define VIDIOC_S_INPUT _IOWR ('V', 39, int)
+#define VIDIOC_G_OUTPUT _IOR ('V', 46, int)
+#define VIDIOC_S_OUTPUT _IOWR ('V', 47, int)
+#define VIDIOC_ENUMOUTPUT _IOWR ('V', 48, struct v4l2_output)
+#define VIDIOC_G_AUDOUT _IOR ('V', 49, struct v4l2_audioout)
+#define VIDIOC_S_AUDOUT _IOW ('V', 50, struct v4l2_audioout)
+#define VIDIOC_G_MODULATOR _IOWR ('V', 54, struct v4l2_modulator)
+#define VIDIOC_S_MODULATOR _IOW ('V', 55, struct v4l2_modulator)
+#define VIDIOC_G_FREQUENCY _IOWR ('V', 56, struct v4l2_frequency)
+#define VIDIOC_S_FREQUENCY _IOW ('V', 57, struct v4l2_frequency)
+#define VIDIOC_CROPCAP _IOR ('V', 58, struct v4l2_cropcap)
+#define VIDIOC_G_CROP _IOWR ('V', 59, struct v4l2_crop)
+#define VIDIOC_S_CROP _IOW ('V', 60, struct v4l2_crop)
+#define VIDIOC_G_JPEGCOMP _IOR ('V', 61, struct v4l2_jpegcompression)
+#define VIDIOC_S_JPEGCOMP _IOW ('V', 62, struct v4l2_jpegcompression)
+#define VIDIOC_QUERYSTD _IOR ('V', 63, v4l2_std_id)
+#define VIDIOC_TRY_FMT _IOWR ('V', 64, struct v4l2_format)
+#define VIDIOC_ENUMAUDIO _IOWR ('V', 65, struct v4l2_audio)
+#define VIDIOC_ENUMAUDOUT _IOWR ('V', 66, struct v4l2_audioout)
+#define VIDIOC_G_PRIORITY _IOR ('V', 67, enum v4l2_priority)
+#define VIDIOC_S_PRIORITY _IOW ('V', 68, enum v4l2_priority)
+
+/* for compatibility, will go away some day */
+#define VIDIOC_OVERLAY_OLD _IOWR ('V', 14, int)
+#define VIDIOC_S_PARM_OLD _IOW ('V', 22, struct v4l2_streamparm)
+#define VIDIOC_S_CTRL_OLD _IOW ('V', 28, struct v4l2_control)
+#define VIDIOC_G_AUDIO_OLD _IOWR ('V', 33, struct v4l2_audio)
+#define VIDIOC_G_AUDOUT_OLD _IOWR ('V', 49, struct v4l2_audioout)
+
+#define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */
+
+
+#ifdef __KERNEL__
+/*
+ *
+ * V 4 L 2 D R I V E R H E L P E R A P I
+ *
+ * Some commonly needed functions for drivers (v4l2-common.o module)
+ */
+#include <linux/fs.h>
+
+/* Video standard functions */
+extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs);
+extern int v4l2_video_std_construct(struct v4l2_standard *vs,
+ int id, char *name);
+
+/* prority handling */
+struct v4l2_prio_state {
+ atomic_t prios[4];
+};
+int v4l2_prio_init(struct v4l2_prio_state *global);
+int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
+ enum v4l2_priority new);
+int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local);
+int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local);
+enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global);
+int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local);
+
+/* names for fancy debug output */
+extern char *v4l2_field_names[];
+extern char *v4l2_type_names[];
+extern char *v4l2_ioctl_names[];
+
+/* Compatibility layer interface -- v4l1-compat module */
+typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg);
+int v4l_compat_translate_ioctl(struct inode *inode, struct file *file,
+ int cmd, void *arg, v4l2_kioctl driver_ioctl);
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_VIDEODEV2_H */
diff --git a/plugins/v4lradio/po/Makefile.am b/plugins/v4lradio/po/Makefile.am
new file mode 100644
index 0000000..7169487
--- /dev/null
+++ b/plugins/v4lradio/po/Makefile.am
@@ -0,0 +1,3 @@
+
+PACKAGE = tderadio-v4lradio
+POFILES = AUTO
diff --git a/plugins/v4lradio/po/de.po b/plugins/v4lradio/po/de.po
new file mode 100644
index 0000000..13e5acc
--- /dev/null
+++ b/plugins/v4lradio/po/de.po
@@ -0,0 +1,336 @@
+# translation of de.po to
+# translation of tderadio-v4lradio.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: 2021-07-07 18:28+0000\n"
+"PO-Revision-Date: 2006-11-06 00:24+0100\n"
+"Last-Translator: Ernst Martin Witte <emw@nocabal.de>\n"
+"Language-Team: <de@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.11.4\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"
+
+#: v4lradio-configuration.cpp:443
+msgid "any ( * )"
+msgstr "Alle ( * )"
+
+#: v4lradio-configuration.cpp:445
+msgid "Radio Device Selection"
+msgstr "Auswahl der Radio-Gerätedatei"
+
+#: v4lradio-configuration.cpp:448
+msgid "Select Radio Device"
+msgstr "Wählen Sie die Radio-Gerätedatei aus"
+
+#: v4lradio.cpp:57
+msgid "Support for V4L(2) Radio Devices"
+msgstr "Unterstützung für V4L(2)-Radiogeräte"
+
+#: v4lradio.cpp:62
+msgid "Video For Linux Plugin"
+msgstr "Video für Linux (V4L) Plugin"
+
+#: v4lradio.cpp:660
+#, c-format
+msgid "invalid frequency %1"
+msgstr "ungültige Frequenz: %1"
+
+#: v4lradio.cpp:681 v4lradio.cpp:1359 v4lradio.cpp:1508
+#, c-format
+msgid "don't known how to handle V4L-version %1"
+msgstr "Keine Ahnung, wie die V4L-Version %1 behandelt werden soll"
+
+#: v4lradio.cpp:687
+msgid "error setting frequency to %1 (%2)"
+msgstr "Fehler (%2) beim Einstellen der Frequenz auf %1."
+
+#: v4lradio.cpp:1005
+msgid ""
+"Device %1 does exist but is not readable/writable. Please check device "
+"permissions."
+msgstr ""
+"Das Gerät %1 existiert, ist aber nicht lesbar/schreibbar. Bitte überprüfen "
+"Sie die Einstellung der Zugriffsrechte für das Gerät."
+
+#: v4lradio.cpp:1015
+msgid "Could not find an accessible v4l(2) radio device."
+msgstr "Kann kein verwendbares V4L(2)-Radiogerät finden."
+
+#: v4lradio.cpp:1078
+msgid "V4L Radio"
+msgstr "V4L Radio"
+
+#: v4lradio.cpp:1079
+msgid "V4L Radio Options"
+msgstr "Optionen des V4L-Radios"
+
+#: v4lradio.cpp:1089
+msgid ""
+"V4L/V4L2 Plugin for TDERadio.<P>Provides Support for V4L/V4L2 based Radio "
+"Cards<P>"
+msgstr ""
+"V4L/V4L2-Plugin für TDERadio.<P>Dieses Plugin bindet vom V4L/V4L2-Treiber "
+"unterstützte Radio-Karten in TDERadio ein.<P>"
+
+#: v4lradio.cpp:1104
+msgid "V4L/V4L2"
+msgstr "V4L/V4L2"
+
+#: v4lradio.cpp:1105
+msgid "V4L/V4L2 Plugin"
+msgstr "V4L/V4L2-Plugin"
+
+#: v4lradio.cpp:1136
+#, c-format
+msgid "Cannot open radio device %1"
+msgstr "Die Radiogerätedatei %1 kann nicht geöffnet werden"
+
+#: v4lradio.cpp:1187
+#, c-format
+msgid "cannot open %1"
+msgstr "%1 kann nicht geöffnet werden"
+
+#: v4lradio.cpp:1211
+#, c-format
+msgid "audio caps = %1"
+msgstr "Audio-Fähigkeiten: %1"
+
+#: v4lradio.cpp:1225
+msgid "error reading V4L1 caps"
+msgstr "Fehler beim Lesen der V4L1-Fähigkeiten"
+
+#: v4lradio.cpp:1234
+#, c-format
+msgid "V4L2 - Version: %1"
+msgstr "V4L2 - Version: %1"
+
+#: v4lradio.cpp:1254
+msgid "V4L2: Querying mute control failed"
+msgstr "V4L2: Die Abfrage des Stummschaltungs-Reglers schlug fehl"
+
+#: v4lradio.cpp:1261
+msgid "V4L2: Querying volume control failed"
+msgstr "V4L2: Die Abfrage des Lautstärke-Reglers schlug fehl"
+
+#: v4lradio.cpp:1269
+msgid "V4L2: Querying treble control failed"
+msgstr "V4L2: Die Abfrage des Höhen-Reglers schlug fehl"
+
+#: v4lradio.cpp:1277
+msgid "V4L2: Querying bass control failed"
+msgstr "V4L2: Die Abfrage des Bass-Reglers schlug fehl"
+
+#: v4lradio.cpp:1285
+msgid "V4L2: Querying balance control failed"
+msgstr "V4L2: Die Abfrage des Balance-Reglers schlug fehl"
+
+#: v4lradio.cpp:1289
+msgid "V4LRadio::readV4LCaps: Reading V4L2 caps failed"
+msgstr "V4LRadio::readV4LCaps: Das Lesen der V4L2-Fähigkeiten schlug fehl"
+
+#: v4lradio.cpp:1293
+msgid "V4L %1 detected"
+msgstr "V4L %1 wurde gefunden"
+
+#: v4lradio.cpp:1295
+msgid "V4L not detected"
+msgstr "Das Radiogerät unterstützt V4L nicht"
+
+#: v4lradio.cpp:1298
+msgid "Radio is mutable"
+msgstr "Das Radio kann stummgeschaltet werden"
+
+#: v4lradio.cpp:1298
+msgid "Radio is not mutable"
+msgstr "Das Radio kann nicht stummgeschaltet werden"
+
+#: v4lradio.cpp:1299
+msgid "Radio has Volume Control"
+msgstr "Das Radio hat einen Lautstärkeregler"
+
+#: v4lradio.cpp:1299
+msgid "Radio has no Volume Control"
+msgstr "Das Radio hat keinen Lautstärkeregler"
+
+#: v4lradio.cpp:1300
+msgid "Radio has Bass Control"
+msgstr "Das Radio hat einen Bass-Regler"
+
+#: v4lradio.cpp:1300
+msgid "Radio has no Bass Control"
+msgstr "Das Radio hat keinen Bass-Regler"
+
+#: v4lradio.cpp:1301
+msgid "Radio has Treble Control"
+msgstr "Das Radio hat einen Höhen-Regler"
+
+#: v4lradio.cpp:1301
+msgid "Radio has no Treble Control"
+msgstr "Das Radio hat keinen Bass-Regler"
+
+#: v4lradio.cpp:1366
+msgid "cannot get tuner info (error %1)"
+msgstr "Tuner-Informationen können nicht gelesen werden (Fehler %1)"
+
+#: v4lradio.cpp:1514
+msgid "error updating radio audio info (%1): %2"
+msgstr "Fehler %2 beim Updaten der Audio-Informationen (%1)"
+
+#: v4lradio.cpp:1515
+msgid "write"
+msgstr "Schreiben"
+
+#: v4lradio.cpp:1515
+msgid "read"
+msgstr "Lesen"
+
+#: v4lradio-configuration-ui.ui:16
+#, no-c-format
+msgid "SetupDialogGeneral"
+msgstr "SetupDialogGeneral"
+
+#: v4lradio-configuration-ui.ui:37
+#, no-c-format
+msgid "Devices"
+msgstr "Geräte"
+
+#: v4lradio-configuration-ui.ui:68
+#, no-c-format
+msgid "Playback Mixer Device"
+msgstr "Wiedergabe Mixer"
+
+#: v4lradio-configuration-ui.ui:76
+#, no-c-format
+msgid "Playback Mixer Channel"
+msgstr "Wiedergabe Mixerkanal"
+
+#: v4lradio-configuration-ui.ui:169
+#, no-c-format
+msgid "Radio Device"
+msgstr "Radio Gerät"
+
+#: v4lradio-configuration-ui.ui:196
+#, no-c-format
+msgid "Capture Mixer Device"
+msgstr "Aufnahme Mixer"
+
+#: v4lradio-configuration-ui.ui:217
+#, no-c-format
+msgid "Capture Mixer Channel"
+msgstr "Aufnahme Mixerkanal"
+
+#: v4lradio-configuration-ui.ui:249
+#, no-c-format
+msgid "test"
+msgstr "test"
+
+#: v4lradio-configuration-ui.ui:269
+#, no-c-format
+msgid "unknown v4l device"
+msgstr "Unbekanntes V4L-Gerät"
+
+#: v4lradio-configuration-ui.ui:315
+#, no-c-format
+msgid "Use active pla&yback by capturing"
+msgstr "Aktive &Wiedergabe verwenden (Aufgenommenes abspielen)"
+
+#: v4lradio-configuration-ui.ui:318
+#, no-c-format
+msgid "Alt+Y"
+msgstr "Alt+Y"
+
+#: v4lradio-configuration-ui.ui:334
+#, no-c-format
+msgid "Mute Play&back Channel on Power Off"
+msgstr "Wiedergabekanal beim Abschalten des Radios stummschalten"
+
+#: v4lradio-configuration-ui.ui:337
+#, no-c-format
+msgid "Alt+B"
+msgstr "Alt+B"
+
+#: v4lradio-configuration-ui.ui:353
+#, no-c-format
+msgid "Set Playback Channel Volume to &Zero on Power Off"
+msgstr "Wiedergabelautstärke beim Abschalten des Radios auf 0 setzen"
+
+#: v4lradio-configuration-ui.ui:356
+#, no-c-format
+msgid "Alt+Z"
+msgstr "Alt+Z"
+
+#: v4lradio-configuration-ui.ui:394
+#, no-c-format
+msgid "to"
+msgstr "bis"
+
+#: v4lradio-configuration-ui.ui:413 v4lradio-configuration-ui.ui:443
+#: v4lradio-configuration-ui.ui:479
+#, no-c-format
+msgid " kHz"
+msgstr " kHz"
+
+#: v4lradio-configuration-ui.ui:460
+#, no-c-format
+msgid "minimum signal quality"
+msgstr "Mindest-Signalpegel"
+
+#: v4lradio-configuration-ui.ui:499
+#, no-c-format
+msgid "station scan step"
+msgstr "Sendersuchschrittweite"
+
+#: v4lradio-configuration-ui.ui:507
+#, no-c-format
+msgid "allowed frequency range"
+msgstr "erlaubter Frequenzbereich"
+
+#: v4lradio-configuration-ui.ui:566
+#, no-c-format
+msgid "V4L Mixer Controls"
+msgstr "V4L Mixersteuerung"
+
+#: v4lradio-configuration-ui.ui:594
+#, no-c-format
+msgid "volume"
+msgstr "Lautstärke"
+
+#: v4lradio-configuration-ui.ui:684
+#, no-c-format
+msgid "treble"
+msgstr "Höhen"
+
+#: v4lradio-configuration-ui.ui:774
+#, no-c-format
+msgid "bass"
+msgstr "Tiefen"
+
+#: v4lradio-configuration-ui.ui:861
+#, no-c-format
+msgid "balance"
+msgstr "Balance"
+
+#~ msgid "error setting %1: %2"
+#~ msgstr "Fehler %2 beim Setzen von %1"
+
+#~ msgid "error reading %1: %2"
+#~ msgstr "Fehler %2 beim Lesen von %1"
diff --git a/plugins/v4lradio/po/pt.po b/plugins/v4lradio/po/pt.po
new file mode 100644
index 0000000..be1e050
--- /dev/null
+++ b/plugins/v4lradio/po/pt.po
@@ -0,0 +1,321 @@
+# SOME DESCRIPTIVE TITLE.
+# Hugo Carvalho <hugokarvalho@hotmail.com>, 2020.
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2021-07-07 18:28+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Automatically generated\n"
+"Language-Team: none\n"
+"Language: pt\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).
+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 ""
+
+#: v4lradio-configuration.cpp:443
+msgid "any ( * )"
+msgstr ""
+
+#: v4lradio-configuration.cpp:445
+msgid "Radio Device Selection"
+msgstr ""
+
+#: v4lradio-configuration.cpp:448
+msgid "Select Radio Device"
+msgstr ""
+
+#: v4lradio.cpp:57
+msgid "Support for V4L(2) Radio Devices"
+msgstr ""
+
+#: v4lradio.cpp:62
+msgid "Video For Linux Plugin"
+msgstr ""
+
+#: v4lradio.cpp:660
+#, c-format
+msgid "invalid frequency %1"
+msgstr ""
+
+#: v4lradio.cpp:681 v4lradio.cpp:1359 v4lradio.cpp:1508
+#, c-format
+msgid "don't known how to handle V4L-version %1"
+msgstr ""
+
+#: v4lradio.cpp:687
+msgid "error setting frequency to %1 (%2)"
+msgstr ""
+
+#: v4lradio.cpp:1005
+msgid ""
+"Device %1 does exist but is not readable/writable. Please check device "
+"permissions."
+msgstr ""
+
+#: v4lradio.cpp:1015
+msgid "Could not find an accessible v4l(2) radio device."
+msgstr ""
+
+#: v4lradio.cpp:1078
+msgid "V4L Radio"
+msgstr ""
+
+#: v4lradio.cpp:1079
+msgid "V4L Radio Options"
+msgstr ""
+
+#: v4lradio.cpp:1089
+msgid ""
+"V4L/V4L2 Plugin for TDERadio.<P>Provides Support for V4L/V4L2 based Radio "
+"Cards<P>"
+msgstr ""
+
+#: v4lradio.cpp:1104
+msgid "V4L/V4L2"
+msgstr ""
+
+#: v4lradio.cpp:1105
+msgid "V4L/V4L2 Plugin"
+msgstr ""
+
+#: v4lradio.cpp:1136
+#, c-format
+msgid "Cannot open radio device %1"
+msgstr ""
+
+#: v4lradio.cpp:1187
+#, c-format
+msgid "cannot open %1"
+msgstr ""
+
+#: v4lradio.cpp:1211
+#, c-format
+msgid "audio caps = %1"
+msgstr ""
+
+#: v4lradio.cpp:1225
+msgid "error reading V4L1 caps"
+msgstr ""
+
+#: v4lradio.cpp:1234
+#, c-format
+msgid "V4L2 - Version: %1"
+msgstr ""
+
+#: v4lradio.cpp:1254
+msgid "V4L2: Querying mute control failed"
+msgstr ""
+
+#: v4lradio.cpp:1261
+msgid "V4L2: Querying volume control failed"
+msgstr ""
+
+#: v4lradio.cpp:1269
+msgid "V4L2: Querying treble control failed"
+msgstr ""
+
+#: v4lradio.cpp:1277
+msgid "V4L2: Querying bass control failed"
+msgstr ""
+
+#: v4lradio.cpp:1285
+msgid "V4L2: Querying balance control failed"
+msgstr ""
+
+#: v4lradio.cpp:1289
+msgid "V4LRadio::readV4LCaps: Reading V4L2 caps failed"
+msgstr ""
+
+#: v4lradio.cpp:1293
+msgid "V4L %1 detected"
+msgstr ""
+
+#: v4lradio.cpp:1295
+msgid "V4L not detected"
+msgstr ""
+
+#: v4lradio.cpp:1298
+msgid "Radio is mutable"
+msgstr ""
+
+#: v4lradio.cpp:1298
+msgid "Radio is not mutable"
+msgstr ""
+
+#: v4lradio.cpp:1299
+msgid "Radio has Volume Control"
+msgstr ""
+
+#: v4lradio.cpp:1299
+msgid "Radio has no Volume Control"
+msgstr ""
+
+#: v4lradio.cpp:1300
+msgid "Radio has Bass Control"
+msgstr ""
+
+#: v4lradio.cpp:1300
+msgid "Radio has no Bass Control"
+msgstr ""
+
+#: v4lradio.cpp:1301
+msgid "Radio has Treble Control"
+msgstr ""
+
+#: v4lradio.cpp:1301
+msgid "Radio has no Treble Control"
+msgstr ""
+
+#: v4lradio.cpp:1366
+msgid "cannot get tuner info (error %1)"
+msgstr ""
+
+#: v4lradio.cpp:1514
+msgid "error updating radio audio info (%1): %2"
+msgstr ""
+
+#: v4lradio.cpp:1515
+msgid "write"
+msgstr ""
+
+#: v4lradio.cpp:1515
+msgid "read"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:16
+#, no-c-format
+msgid "SetupDialogGeneral"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:37
+#, no-c-format
+msgid "Devices"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:68
+#, no-c-format
+msgid "Playback Mixer Device"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:76
+#, no-c-format
+msgid "Playback Mixer Channel"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:169
+#, no-c-format
+msgid "Radio Device"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:196
+#, no-c-format
+msgid "Capture Mixer Device"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:217
+#, no-c-format
+msgid "Capture Mixer Channel"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:249
+#, no-c-format
+msgid "test"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:269
+#, no-c-format
+msgid "unknown v4l device"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:315
+#, no-c-format
+msgid "Use active pla&yback by capturing"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:318
+#, no-c-format
+msgid "Alt+Y"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:334
+#, no-c-format
+msgid "Mute Play&back Channel on Power Off"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:337
+#, no-c-format
+msgid "Alt+B"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:353
+#, no-c-format
+msgid "Set Playback Channel Volume to &Zero on Power Off"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:356
+#, no-c-format
+msgid "Alt+Z"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:394
+#, no-c-format
+msgid "to"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:413 v4lradio-configuration-ui.ui:443
+#: v4lradio-configuration-ui.ui:479
+#, no-c-format
+msgid " kHz"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:460
+#, no-c-format
+msgid "minimum signal quality"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:499
+#, no-c-format
+msgid "station scan step"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:507
+#, no-c-format
+msgid "allowed frequency range"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:566
+#, no-c-format
+msgid "V4L Mixer Controls"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:594
+#, no-c-format
+msgid "volume"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:684
+#, no-c-format
+msgid "treble"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:774
+#, no-c-format
+msgid "bass"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:861
+#, no-c-format
+msgid "balance"
+msgstr ""
diff --git a/plugins/v4lradio/po/ru.po b/plugins/v4lradio/po/ru.po
new file mode 100644
index 0000000..a85cb77
--- /dev/null
+++ b/plugins/v4lradio/po/ru.po
@@ -0,0 +1,336 @@
+# translation of ru.po to
+# translation of tderadio-v4lradio.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: 2021-07-07 18:28+0000\n"
+"PO-Revision-Date: 2006-11-08 11:59+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"
+
+#: v4lradio-configuration.cpp:443
+msgid "any ( * )"
+msgstr "Все ( * )"
+
+#: v4lradio-configuration.cpp:445
+msgid "Radio Device Selection"
+msgstr "Выбор устройства радио"
+
+#: v4lradio-configuration.cpp:448
+msgid "Select Radio Device"
+msgstr "Выберите устройство радиоприёмника"
+
+#: v4lradio.cpp:57
+msgid "Support for V4L(2) Radio Devices"
+msgstr "Поддержка устройств V4l(2)"
+
+#: v4lradio.cpp:62
+msgid "Video For Linux Plugin"
+msgstr "Модуль \"Видео для linux\""
+
+#: v4lradio.cpp:660
+#, c-format
+msgid "invalid frequency %1"
+msgstr "Неправильная частота %1"
+
+#: v4lradio.cpp:681 v4lradio.cpp:1359 v4lradio.cpp:1508
+#, c-format
+msgid "don't known how to handle V4L-version %1"
+msgstr "Не знаю что делать с версией V4l \"%1\""
+
+#: v4lradio.cpp:687
+msgid "error setting frequency to %1 (%2)"
+msgstr "Ошибка установки частоты %1 (%2)"
+
+#: v4lradio.cpp:1005
+msgid ""
+"Device %1 does exist but is not readable/writable. Please check device "
+"permissions."
+msgstr ""
+"Устройство %1 недоступно для чтения/записи. Проверьте права на устройство, а "
+"также не использует ли его другая программа."
+
+#: v4lradio.cpp:1015
+msgid "Could not find an accessible v4l(2) radio device."
+msgstr "Не найти доступное устройство V4l(2)."
+
+#: v4lradio.cpp:1078
+msgid "V4L Radio"
+msgstr "Радио V4l"
+
+#: v4lradio.cpp:1079
+msgid "V4L Radio Options"
+msgstr "Параметры устройства V4l"
+
+#: v4lradio.cpp:1089
+msgid ""
+"V4L/V4L2 Plugin for TDERadio.<P>Provides Support for V4L/V4L2 based Radio "
+"Cards<P>"
+msgstr ""
+"Модуль V4l/V4l2 для TDERadio. <P> Предоставляет поддержку плат радио, "
+"совместимых с V4l/V4l2<P>"
+
+#: v4lradio.cpp:1104
+msgid "V4L/V4L2"
+msgstr "V4L/V4LV2"
+
+#: v4lradio.cpp:1105
+msgid "V4L/V4L2 Plugin"
+msgstr "Модуль V4L/V4L2"
+
+#: v4lradio.cpp:1136
+#, c-format
+msgid "Cannot open radio device %1"
+msgstr "Не могу открыть устройство радио: %1"
+
+#: v4lradio.cpp:1187
+#, c-format
+msgid "cannot open %1"
+msgstr "Не могу открыть %1"
+
+#: v4lradio.cpp:1211
+#, c-format
+msgid "audio caps = %1"
+msgstr "возможности звука = %1"
+
+#: v4lradio.cpp:1225
+msgid "error reading V4L1 caps"
+msgstr "Ошибка чтения возможностей V4l1"
+
+#: v4lradio.cpp:1234
+#, c-format
+msgid "V4L2 - Version: %1"
+msgstr "Версия V4l2: %1"
+
+#: v4lradio.cpp:1254
+msgid "V4L2: Querying mute control failed"
+msgstr "V4L2: Не могу обратиться к выключателю звука платы"
+
+#: v4lradio.cpp:1261
+msgid "V4L2: Querying volume control failed"
+msgstr "V4L2: Не могу обратиться к регулятору громкости"
+
+#: v4lradio.cpp:1269
+msgid "V4L2: Querying treble control failed"
+msgstr "V4L2: Не могу обратиться к регулятору верхних частот"
+
+#: v4lradio.cpp:1277
+msgid "V4L2: Querying bass control failed"
+msgstr "V4L2: Не могу обратиться к регулятору нижних частот"
+
+#: v4lradio.cpp:1285
+msgid "V4L2: Querying balance control failed"
+msgstr "V4L2: Не могу обратиться к регулятору стереобаланса"
+
+#: v4lradio.cpp:1289
+msgid "V4LRadio::readV4LCaps: Reading V4L2 caps failed"
+msgstr "V4LRadio::readV4LCaps:Не могу узнать возможности устройства"
+
+#: v4lradio.cpp:1293
+msgid "V4L %1 detected"
+msgstr "Найдено устройство V4L: %1"
+
+#: v4lradio.cpp:1295
+msgid "V4L not detected"
+msgstr "Устройств V4L не обнаружено"
+
+#: v4lradio.cpp:1298
+msgid "Radio is mutable"
+msgstr "Радио не поддерживает выключения звука"
+
+#: v4lradio.cpp:1298
+msgid "Radio is not mutable"
+msgstr "Радио поддерживает выключение звука"
+
+#: v4lradio.cpp:1299
+msgid "Radio has Volume Control"
+msgstr "Есть регулировка громкости"
+
+#: v4lradio.cpp:1299
+msgid "Radio has no Volume Control"
+msgstr "Регулировки громкости нет"
+
+#: v4lradio.cpp:1300
+msgid "Radio has Bass Control"
+msgstr "Есть регулировка НЧ"
+
+#: v4lradio.cpp:1300
+msgid "Radio has no Bass Control"
+msgstr "Регулировки НЧ нет"
+
+#: v4lradio.cpp:1301
+msgid "Radio has Treble Control"
+msgstr "Есть регулировка ВЧ"
+
+#: v4lradio.cpp:1301
+msgid "Radio has no Treble Control"
+msgstr "Регулировки ВЧ нет"
+
+#: v4lradio.cpp:1366
+msgid "cannot get tuner info (error %1)"
+msgstr "Не могу получить информацию о тюнере (код ошибки %1)"
+
+#: v4lradio.cpp:1514
+msgid "error updating radio audio info (%1): %2"
+msgstr "Ошибка %1: %2"
+
+#: v4lradio.cpp:1515
+msgid "write"
+msgstr "запись"
+
+#: v4lradio.cpp:1515
+msgid "read"
+msgstr "чтение"
+
+#: v4lradio-configuration-ui.ui:16
+#, no-c-format
+msgid "SetupDialogGeneral"
+msgstr "SetupDialogGeneral"
+
+#: v4lradio-configuration-ui.ui:37
+#, no-c-format
+msgid "Devices"
+msgstr "Устройства"
+
+#: v4lradio-configuration-ui.ui:68
+#, no-c-format
+msgid "Playback Mixer Device"
+msgstr "Устройство воспроизведения"
+
+#: v4lradio-configuration-ui.ui:76
+#, no-c-format
+msgid "Playback Mixer Channel"
+msgstr "Канал воспроизведения"
+
+#: v4lradio-configuration-ui.ui:169
+#, no-c-format
+msgid "Radio Device"
+msgstr "Устройство радио"
+
+#: v4lradio-configuration-ui.ui:196
+#, no-c-format
+msgid "Capture Mixer Device"
+msgstr "Устройство записи"
+
+#: v4lradio-configuration-ui.ui:217
+#, no-c-format
+msgid "Capture Mixer Channel"
+msgstr "Канал записи"
+
+#: v4lradio-configuration-ui.ui:249
+#, no-c-format
+msgid "test"
+msgstr "проверка"
+
+#: v4lradio-configuration-ui.ui:269
+#, no-c-format
+msgid "unknown v4l device"
+msgstr "неизвестно"
+
+#: v4lradio-configuration-ui.ui:315
+#, no-c-format
+msgid "Use active pla&yback by capturing"
+msgstr "Захватывать звук и затем проигрывать его"
+
+#: v4lradio-configuration-ui.ui:318
+#, no-c-format
+msgid "Alt+Y"
+msgstr "Alt+Y"
+
+#: v4lradio-configuration-ui.ui:334
+#, no-c-format
+msgid "Mute Play&back Channel on Power Off"
+msgstr "Выключать звук на канале воспроизведения при выходе"
+
+#: v4lradio-configuration-ui.ui:337
+#, no-c-format
+msgid "Alt+B"
+msgstr "Alt+B"
+
+#: v4lradio-configuration-ui.ui:353
+#, no-c-format
+msgid "Set Playback Channel Volume to &Zero on Power Off"
+msgstr "Устанавливать &нулевую громкость воспроизведения при выходе"
+
+#: v4lradio-configuration-ui.ui:356
+#, no-c-format
+msgid "Alt+Z"
+msgstr "Alt+Z"
+
+#: v4lradio-configuration-ui.ui:394
+#, no-c-format
+msgid "to"
+msgstr "до"
+
+#: v4lradio-configuration-ui.ui:413 v4lradio-configuration-ui.ui:443
+#: v4lradio-configuration-ui.ui:479
+#, no-c-format
+msgid " kHz"
+msgstr " кГц"
+
+#: v4lradio-configuration-ui.ui:460
+#, no-c-format
+msgid "minimum signal quality"
+msgstr "Минимальный уровень сигнала"
+
+#: v4lradio-configuration-ui.ui:499
+#, no-c-format
+msgid "station scan step"
+msgstr "Шаг изменения частоты при поиске"
+
+#: v4lradio-configuration-ui.ui:507
+#, no-c-format
+msgid "allowed frequency range"
+msgstr "Допустимый частотный диапазон:\tот"
+
+#: v4lradio-configuration-ui.ui:566
+#, no-c-format
+msgid "V4L Mixer Controls"
+msgstr "Аппаратные регуляторы V4l"
+
+#: v4lradio-configuration-ui.ui:594
+#, no-c-format
+msgid "volume"
+msgstr "Громкость"
+
+#: v4lradio-configuration-ui.ui:684
+#, no-c-format
+msgid "treble"
+msgstr "ВЧ"
+
+#: v4lradio-configuration-ui.ui:774
+#, no-c-format
+msgid "bass"
+msgstr "НЧ"
+
+#: v4lradio-configuration-ui.ui:861
+#, no-c-format
+msgid "balance"
+msgstr "Стереобаланс"
+
+#~ msgid "error setting %1: %2"
+#~ msgstr "Ошибка установки %1: %2"
+
+#~ msgid "error reading %1: %2"
+#~ msgstr "Ошибка чтения %1: %2"
diff --git a/plugins/v4lradio/po/tderadio-v4lradio.pot b/plugins/v4lradio/po/tderadio-v4lradio.pot
new file mode 100644
index 0000000..84a59f2
--- /dev/null
+++ b/plugins/v4lradio/po/tderadio-v4lradio.pot
@@ -0,0 +1,324 @@
+# SOME DESCRIPTIVE TITLE.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2021-07-07 18:28+0000\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 ""
+
+#: v4lradio-configuration.cpp:443
+msgid "any ( * )"
+msgstr ""
+
+#: v4lradio-configuration.cpp:445
+msgid "Radio Device Selection"
+msgstr ""
+
+#: v4lradio-configuration.cpp:448
+msgid "Select Radio Device"
+msgstr ""
+
+#: v4lradio.cpp:57
+msgid "Support for V4L(2) Radio Devices"
+msgstr ""
+
+#: v4lradio.cpp:62
+msgid "Video For Linux Plugin"
+msgstr ""
+
+#: v4lradio.cpp:660
+#, c-format
+msgid "invalid frequency %1"
+msgstr ""
+
+#: v4lradio.cpp:681 v4lradio.cpp:1359 v4lradio.cpp:1508
+#, c-format
+msgid "don't known how to handle V4L-version %1"
+msgstr ""
+
+#: v4lradio.cpp:687
+msgid "error setting frequency to %1 (%2)"
+msgstr ""
+
+#: v4lradio.cpp:1005
+msgid ""
+"Device %1 does exist but is not readable/writable. Please check device "
+"permissions."
+msgstr ""
+
+#: v4lradio.cpp:1015
+msgid "Could not find an accessible v4l(2) radio device."
+msgstr ""
+
+#: v4lradio.cpp:1078
+msgid "V4L Radio"
+msgstr ""
+
+#: v4lradio.cpp:1079
+msgid "V4L Radio Options"
+msgstr ""
+
+#: v4lradio.cpp:1089
+msgid ""
+"V4L/V4L2 Plugin for TDERadio.<P>Provides Support for V4L/V4L2 based Radio "
+"Cards<P>"
+msgstr ""
+
+#: v4lradio.cpp:1104
+msgid "V4L/V4L2"
+msgstr ""
+
+#: v4lradio.cpp:1105
+msgid "V4L/V4L2 Plugin"
+msgstr ""
+
+#: v4lradio.cpp:1136
+#, c-format
+msgid "Cannot open radio device %1"
+msgstr ""
+
+#: v4lradio.cpp:1187
+#, c-format
+msgid "cannot open %1"
+msgstr ""
+
+#: v4lradio.cpp:1211
+#, c-format
+msgid "audio caps = %1"
+msgstr ""
+
+#: v4lradio.cpp:1225
+msgid "error reading V4L1 caps"
+msgstr ""
+
+#: v4lradio.cpp:1234
+#, c-format
+msgid "V4L2 - Version: %1"
+msgstr ""
+
+#: v4lradio.cpp:1254
+msgid "V4L2: Querying mute control failed"
+msgstr ""
+
+#: v4lradio.cpp:1261
+msgid "V4L2: Querying volume control failed"
+msgstr ""
+
+#: v4lradio.cpp:1269
+msgid "V4L2: Querying treble control failed"
+msgstr ""
+
+#: v4lradio.cpp:1277
+msgid "V4L2: Querying bass control failed"
+msgstr ""
+
+#: v4lradio.cpp:1285
+msgid "V4L2: Querying balance control failed"
+msgstr ""
+
+#: v4lradio.cpp:1289
+msgid "V4LRadio::readV4LCaps: Reading V4L2 caps failed"
+msgstr ""
+
+#: v4lradio.cpp:1293
+msgid "V4L %1 detected"
+msgstr ""
+
+#: v4lradio.cpp:1295
+msgid "V4L not detected"
+msgstr ""
+
+#: v4lradio.cpp:1298
+msgid "Radio is mutable"
+msgstr ""
+
+#: v4lradio.cpp:1298
+msgid "Radio is not mutable"
+msgstr ""
+
+#: v4lradio.cpp:1299
+msgid "Radio has Volume Control"
+msgstr ""
+
+#: v4lradio.cpp:1299
+msgid "Radio has no Volume Control"
+msgstr ""
+
+#: v4lradio.cpp:1300
+msgid "Radio has Bass Control"
+msgstr ""
+
+#: v4lradio.cpp:1300
+msgid "Radio has no Bass Control"
+msgstr ""
+
+#: v4lradio.cpp:1301
+msgid "Radio has Treble Control"
+msgstr ""
+
+#: v4lradio.cpp:1301
+msgid "Radio has no Treble Control"
+msgstr ""
+
+#: v4lradio.cpp:1366
+msgid "cannot get tuner info (error %1)"
+msgstr ""
+
+#: v4lradio.cpp:1514
+msgid "error updating radio audio info (%1): %2"
+msgstr ""
+
+#: v4lradio.cpp:1515
+msgid "write"
+msgstr ""
+
+#: v4lradio.cpp:1515
+msgid "read"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:16
+#, no-c-format
+msgid "SetupDialogGeneral"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:37
+#, no-c-format
+msgid "Devices"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:68
+#, no-c-format
+msgid "Playback Mixer Device"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:76
+#, no-c-format
+msgid "Playback Mixer Channel"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:169
+#, no-c-format
+msgid "Radio Device"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:196
+#, no-c-format
+msgid "Capture Mixer Device"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:217
+#, no-c-format
+msgid "Capture Mixer Channel"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:249
+#, no-c-format
+msgid "test"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:269
+#, no-c-format
+msgid "unknown v4l device"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:315
+#, no-c-format
+msgid "Use active pla&yback by capturing"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:318
+#, no-c-format
+msgid "Alt+Y"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:334
+#, no-c-format
+msgid "Mute Play&back Channel on Power Off"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:337
+#, no-c-format
+msgid "Alt+B"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:353
+#, no-c-format
+msgid "Set Playback Channel Volume to &Zero on Power Off"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:356
+#, no-c-format
+msgid "Alt+Z"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:394
+#, no-c-format
+msgid "to"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:413 v4lradio-configuration-ui.ui:443
+#: v4lradio-configuration-ui.ui:479
+#, no-c-format
+msgid " kHz"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:460
+#, no-c-format
+msgid "minimum signal quality"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:499
+#, no-c-format
+msgid "station scan step"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:507
+#, no-c-format
+msgid "allowed frequency range"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:566
+#, no-c-format
+msgid "V4L Mixer Controls"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:594
+#, no-c-format
+msgid "volume"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:684
+#, no-c-format
+msgid "treble"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:774
+#, no-c-format
+msgid "bass"
+msgstr ""
+
+#: v4lradio-configuration-ui.ui:861
+#, no-c-format
+msgid "balance"
+msgstr ""
diff --git a/plugins/v4lradio/v4lcfg_interfaces.cpp b/plugins/v4lradio/v4lcfg_interfaces.cpp
new file mode 100644
index 0000000..9ef14aa
--- /dev/null
+++ b/plugins/v4lradio/v4lcfg_interfaces.cpp
@@ -0,0 +1,193 @@
+/***************************************************************************
+ v4lradio_interfaces.cpp - description
+ -------------------
+ begin : Sam Jun 21 2003
+ copyright : (C) 2003 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 <linux/soundcard.h>
+#include "v4lcfg_interfaces.h"
+
+///////////////////////////////////////////////////////////////////////
+
+V4LCaps::V4LCaps()
+ : version(0),
+ description(TQString()),
+ hasMute(false),
+ hasVolume(false),
+ minVolume(0),
+ maxVolume(65535),
+ hasTreble(false),
+ minTreble(0),
+ maxTreble(65535),
+ hasBass(false),
+ minBass(0),
+ maxBass(65535),
+ hasBalance(false),
+ minBalance(0),
+ maxBalance(65535)
+{
+}
+
+
+V4LCaps::V4LCaps(const V4LCaps &c)
+ : version(c.version),
+ description(c.description),
+ hasMute(c.hasMute),
+ hasVolume(c.hasVolume),
+ minVolume(c.minVolume),
+ maxVolume(c.maxVolume),
+ hasTreble(c.hasTreble),
+ minTreble(c.minTreble),
+ maxTreble(c.maxTreble),
+ hasBass(c.hasBass),
+ minBass(c.minBass),
+ maxBass(c.maxBass),
+ hasBalance(c.hasBalance),
+ minBalance(c.minBalance),
+ maxBalance(c.maxBalance)
+{
+}
+
+
+// IV4LCfg
+
+IF_IMPL_SENDER ( IV4LCfg::notifyRadioDeviceChanged(const TQString &s),
+ noticeRadioDeviceChanged(s)
+ )
+IF_IMPL_SENDER ( IV4LCfg::notifyPlaybackMixerChanged(const TQString &s, const TQString &Channel),
+ noticePlaybackMixerChanged(s, Channel)
+ )
+IF_IMPL_SENDER ( IV4LCfg::notifyCaptureMixerChanged(const TQString &s, const TQString &Channel),
+ noticeCaptureMixerChanged(s, Channel)
+ )
+IF_IMPL_SENDER ( IV4LCfg::notifyDeviceVolumeChanged(float v),
+ noticeDeviceVolumeChanged(v)
+ )
+IF_IMPL_SENDER ( IV4LCfg::notifyCapabilitiesChanged(const V4LCaps &c),
+ noticeCapabilitiesChanged(c)
+ )
+
+IF_IMPL_SENDER ( IV4LCfg::notifyActivePlaybackChanged(bool a),
+ noticeActivePlaybackChanged(a)
+ )
+
+IF_IMPL_SENDER ( IV4LCfg::notifyMuteOnPowerOffChanged(bool a),
+ noticeMuteOnPowerOffChanged(a)
+ )
+
+IF_IMPL_SENDER ( IV4LCfg::notifyVolumeZeroOnPowerOffChanged(bool a),
+ noticeVolumeZeroOnPowerOffChanged(a)
+ )
+// IV4LCfgClient
+
+IF_IMPL_SENDER ( IV4LCfgClient::sendRadioDevice (const TQString &s),
+ setRadioDevice(s)
+ )
+IF_IMPL_SENDER ( IV4LCfgClient::sendPlaybackMixer(const TQString &s, const TQString &ch),
+ setPlaybackMixer(s, ch)
+ )
+IF_IMPL_SENDER ( IV4LCfgClient::sendCaptureMixer(const TQString &s, const TQString &ch),
+ setCaptureMixer(s, ch)
+ )
+IF_IMPL_SENDER ( IV4LCfgClient::sendDeviceVolume(float v),
+ setDeviceVolume(v)
+ )
+
+IF_IMPL_SENDER ( IV4LCfgClient::sendActivePlayback(bool a),
+ setActivePlayback(a)
+ )
+
+IF_IMPL_SENDER ( IV4LCfgClient::sendMuteOnPowerOff(bool a),
+ setMuteOnPowerOff(a)
+ )
+
+IF_IMPL_SENDER ( IV4LCfgClient::sendVolumeZeroOnPowerOff(bool a),
+ setVolumeZeroOnPowerOff(a)
+ )
+
+static TQString defaultRDev("/dev/radio");
+// static TQString defaultMDev("/dev/mixer");
+
+IF_IMPL_QUERY ( const TQString &IV4LCfgClient::queryRadioDevice (),
+ getRadioDevice(),
+ defaultRDev
+ )
+IF_IMPL_QUERY ( const TQString &IV4LCfgClient::queryPlaybackMixerID (),
+ getPlaybackMixerID(),
+ TQString()
+ )
+IF_IMPL_QUERY ( const TQString &IV4LCfgClient::queryCaptureMixerID (),
+ getCaptureMixerID(),
+ TQString()
+ )
+
+static const TQString channel_line("Line");
+IF_IMPL_QUERY ( const TQString &IV4LCfgClient::queryPlaybackMixerChannel(),
+ getPlaybackMixerChannel(),
+ channel_line
+ )
+IF_IMPL_QUERY ( const TQString &IV4LCfgClient::queryCaptureMixerChannel(),
+ getCaptureMixerChannel(),
+ channel_line
+ )
+IF_IMPL_QUERY ( float IV4LCfgClient::queryDeviceVolume (),
+ getDeviceVolume(),
+ 0.0
+ )
+IF_IMPL_QUERY ( V4LCaps IV4LCfgClient::queryCapabilities(TQString dev),
+ getCapabilities(dev),
+ V4LCaps()
+ )
+
+IF_IMPL_QUERY ( bool IV4LCfgClient::queryActivePlayback(),
+ getActivePlayback(),
+ false
+ )
+
+IF_IMPL_QUERY ( bool IV4LCfgClient::queryMuteOnPowerOff(),
+ getMuteOnPowerOff(),
+ false
+ )
+
+IF_IMPL_QUERY ( bool IV4LCfgClient::queryVolumeZeroOnPowerOff(),
+ getVolumeZeroOnPowerOff(),
+ false
+ )
+
+void IV4LCfgClient::noticeConnectedI (cmplInterface *, bool /*pointer_valid*/)
+{
+ noticeRadioDeviceChanged(queryRadioDevice());
+ noticePlaybackMixerChanged(queryPlaybackMixerID(), queryPlaybackMixerChannel());
+ noticeCaptureMixerChanged (queryCaptureMixerID(), queryCaptureMixerChannel());
+ noticeDeviceVolumeChanged(queryDeviceVolume());
+ noticeCapabilitiesChanged(queryCapabilities());
+ noticeActivePlaybackChanged(queryActivePlayback());
+ noticeMuteOnPowerOffChanged(queryMuteOnPowerOff());
+ noticeVolumeZeroOnPowerOffChanged(queryVolumeZeroOnPowerOff());
+}
+
+
+void IV4LCfgClient::noticeDisconnectedI (cmplInterface *, bool /*pointer_valid*/)
+{
+ noticeRadioDeviceChanged(queryRadioDevice());
+ noticePlaybackMixerChanged(queryPlaybackMixerID(), queryPlaybackMixerChannel());
+ noticeCaptureMixerChanged (queryCaptureMixerID(), queryCaptureMixerChannel());
+ noticeDeviceVolumeChanged(queryDeviceVolume());
+ noticeCapabilitiesChanged(queryCapabilities());
+ noticeActivePlaybackChanged(queryActivePlayback());
+ noticeMuteOnPowerOffChanged(queryMuteOnPowerOff());
+ noticeVolumeZeroOnPowerOffChanged(queryVolumeZeroOnPowerOff());
+}
+
+
diff --git a/plugins/v4lradio/v4lcfg_interfaces.h b/plugins/v4lradio/v4lcfg_interfaces.h
new file mode 100644
index 0000000..d9c2a24
--- /dev/null
+++ b/plugins/v4lradio/v4lcfg_interfaces.h
@@ -0,0 +1,151 @@
+/***************************************************************************
+ v4lradio_interfaces.h - description
+ -------------------
+ begin : Sam Jun 21 2003
+ copyright : (C) 2003 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_V4LCFG_INTERFACES_H
+#define KRADIO_V4LCFG_INTERFACES_H
+
+#include "../../src/include/interfaces.h"
+#include "math.h"
+
+struct V4LCaps
+{
+ int version;
+ TQString description;
+
+ bool hasMute;
+
+ bool hasVolume;
+ int minVolume, maxVolume;
+ bool hasTreble;
+ int minTreble, maxTreble;
+ bool hasBass;
+ int minBass, maxBass;
+ bool hasBalance;
+ int minBalance, maxBalance;
+
+ V4LCaps();
+ V4LCaps(const V4LCaps &);
+
+ float volumeStep() const { return 1.0 / (float)(maxVolume - minVolume); }
+ float trebleStep() const { return 1.0 / (float)(maxTreble - minTreble); }
+ float bassStep() const { return 1.0 / (float)(maxBass - minBass); }
+ float balanceStep() const { return 1.0 / (float)(maxBalance - minBalance); }
+
+ void setVolume (int min, int max) { hasVolume = true; minVolume = min; maxVolume = max; }
+ void setTreble (int min, int max) { hasTreble = true; minTreble = min; maxTreble = max; }
+ void setBass (int min, int max) { hasBass = true; minBass = min; maxBass = max; }
+ void setBalance(int min, int max) { hasBalance = true; minBalance = min; maxBalance = max; }
+
+ void unsetVolume () { hasVolume = false; minVolume = 0; maxVolume = 65535; }
+ void unsetTreble () { hasTreble = false; minTreble = 0; maxTreble = 65535; }
+ void unsetBass () { hasBass = false; minBass = 0; maxBass = 65535; }
+ void unsetBalance() { hasBalance = false; minBalance = 0; maxBalance = 65535; }
+
+ int intGetVolume (float f) const { return (int)rint(minVolume + (maxVolume - minVolume ) * f); }
+ int intGetTreble (float f) const { return (int)rint(minTreble + (maxTreble - minTreble ) * f); }
+ int intGetBass (float f) const { return (int)rint(minBass + (maxBass - minBass ) * f); }
+ int intGetBalance(float f) const { return (int)rint(minBalance + (maxBalance - minBalance) / 2.0 * (1.0 + f)); }
+
+ float floatGetVolume (int i) const { return (float)(i - minVolume) * volumeStep(); }
+ float floatGetTreble (int i) const { return (float)(i - minTreble) * trebleStep(); }
+ float floatGetBass (int i) const { return (float)(i - minBass ) * bassStep(); }
+ float floatGetBalance(int i) const { return (float)(i - minBalance) * balanceStep() * 2.0 - 1.0; }
+};
+
+
+
+INTERFACE(IV4LCfg, IV4LCfgClient)
+{
+public:
+ IF_CON_DESTRUCTOR(IV4LCfg, -1)
+
+RECEIVERS:
+ IF_RECEIVER( setRadioDevice (const TQString &s) )
+ IF_RECEIVER( setPlaybackMixer(const TQString &soundStreamClientID, const TQString &ch) )
+ IF_RECEIVER( setCaptureMixer (const TQString &soundStreamClientID, const TQString &ch) )
+ IF_RECEIVER( setDeviceVolume(float v) )
+ IF_RECEIVER( setActivePlayback(bool a) )
+ IF_RECEIVER( setMuteOnPowerOff(bool m) )
+ IF_RECEIVER( setVolumeZeroOnPowerOff(bool m) )
+
+SENDERS:
+ IF_SENDER ( notifyRadioDeviceChanged (const TQString &s) )
+ IF_SENDER ( notifyPlaybackMixerChanged(const TQString &soundStreamClientID, const TQString &Channel) )
+ IF_SENDER ( notifyCaptureMixerChanged (const TQString &soundStreamClientID, const TQString &Channel) )
+ IF_SENDER ( notifyDeviceVolumeChanged (float v) )
+ IF_SENDER ( notifyCapabilitiesChanged (const V4LCaps &) )
+ IF_SENDER ( notifyActivePlaybackChanged (bool a) )
+ IF_SENDER ( notifyMuteOnPowerOffChanged (bool a) )
+ IF_SENDER ( notifyVolumeZeroOnPowerOffChanged (bool a) )
+
+ANSWERS:
+ IF_ANSWER ( const TQString &getRadioDevice () const )
+ IF_ANSWER ( const TQString &getPlaybackMixerID () const )
+ IF_ANSWER ( const TQString &getCaptureMixerID () const )
+ IF_ANSWER ( const TQString &getPlaybackMixerChannel() const )
+ IF_ANSWER ( const TQString &getCaptureMixerChannel() const )
+ IF_ANSWER ( float getDeviceVolume() const )
+ IF_ANSWER ( V4LCaps getCapabilities(TQString dev = TQString()) const )
+ IF_ANSWER ( bool getActivePlayback() const )
+ IF_ANSWER ( bool getMuteOnPowerOff() const )
+ IF_ANSWER ( bool getVolumeZeroOnPowerOff() const )
+};
+
+
+
+INTERFACE(IV4LCfgClient, IV4LCfg)
+{
+public:
+ IF_CON_DESTRUCTOR(IV4LCfgClient, 1)
+
+SENDERS:
+ IF_SENDER ( sendRadioDevice (const TQString &s) )
+ IF_SENDER ( sendPlaybackMixer(const TQString &soundStreamClientID, const TQString &ch) )
+ IF_SENDER ( sendCaptureMixer (const TQString &soundStreamClientID, const TQString &ch) )
+ IF_SENDER ( sendDeviceVolume(float v) )
+ IF_SENDER ( sendActivePlayback(bool a) )
+ IF_SENDER ( sendMuteOnPowerOff(bool a) )
+ IF_SENDER ( sendVolumeZeroOnPowerOff(bool a) )
+
+RECEIVERS:
+ IF_RECEIVER( noticeRadioDeviceChanged(const TQString &s) )
+ IF_RECEIVER( noticePlaybackMixerChanged(const TQString &soundStreamClientID, const TQString &Channel) )
+ IF_RECEIVER( noticeCaptureMixerChanged (const TQString &soundStreamClientID, const TQString &Channel) )
+ IF_RECEIVER( noticeDeviceVolumeChanged(float v) )
+ IF_RECEIVER( noticeCapabilitiesChanged(const V4LCaps &) )
+ IF_RECEIVER( noticeActivePlaybackChanged(bool a) )
+ IF_RECEIVER( noticeMuteOnPowerOffChanged(bool a) )
+ IF_RECEIVER( noticeVolumeZeroOnPowerOffChanged(bool a) )
+
+QUERIES:
+ IF_QUERY ( const TQString &queryRadioDevice () )
+ IF_QUERY ( const TQString &queryPlaybackMixerID () )
+ IF_QUERY ( const TQString &queryCaptureMixerID () )
+ IF_QUERY ( const TQString &queryPlaybackMixerChannel() )
+ IF_QUERY ( const TQString &queryCaptureMixerChannel() )
+ IF_QUERY ( float queryDeviceVolume() )
+ IF_QUERY ( V4LCaps queryCapabilities(TQString dev = TQString()) )
+ IF_QUERY ( bool queryActivePlayback() )
+ IF_QUERY ( bool queryMuteOnPowerOff() )
+ IF_QUERY ( bool queryVolumeZeroOnPowerOff() )
+
+RECEIVERS:
+ virtual void noticeConnectedI (cmplInterface *, bool /*pointer_valid*/);
+ virtual void noticeDisconnectedI (cmplInterface *, bool /*pointer_valid*/);
+};
+
+#endif
diff --git a/plugins/v4lradio/v4lradio-configuration-ui.ui b/plugins/v4lradio/v4lradio-configuration-ui.ui
new file mode 100644
index 0000000..63cdc59
--- /dev/null
+++ b/plugins/v4lradio/v4lradio-configuration-ui.ui
@@ -0,0 +1,956 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>V4LRadioConfigurationUI</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>V4LRadioConfigurationUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>512</width>
+ <height>357</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>SetupDialogGeneral</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>kTabWidget1</cstring>
+ </property>
+ <property name="currentPage">
+ <number>0</number>
+ </property>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Devices</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>spacer18_3_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>labelPlaybackMixerDevice</cstring>
+ </property>
+ <property name="text">
+ <string>Playback Mixer Device</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>labelPlaybackMixerChannel</cstring>
+ </property>
+ <property name="text">
+ <string>Playback Mixer Channel</string>
+ </property>
+ </widget>
+ <spacer row="2" column="2">
+ <property name="name">
+ <cstring>spacer18_3_4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="3" column="2">
+ <property name="name">
+ <cstring>spacer18_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="4" column="2">
+ <property name="name">
+ <cstring>spacer18_3_4_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="5" column="2">
+ <property name="name">
+ <cstring>spacer18_3_5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>40</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer18_3_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>152</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>labelRadioDevice</cstring>
+ </property>
+ <property name="text">
+ <string>Radio Device</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="0" column="2">
+ <property name="name">
+ <cstring>buttonSelectRadioDevice</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="iconSet">
+ <iconset>"document-open"</iconset>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="4" column="0">
+ <property name="name">
+ <cstring>labelCaptureMixerDevice</cstring>
+ </property>
+ <property name="text">
+ <string>Capture Mixer Device</string>
+ </property>
+ </widget>
+ <widget class="TQComboBox" row="5" column="1">
+ <property name="name">
+ <cstring>comboCaptureMixerChannel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="5" column="0">
+ <property name="name">
+ <cstring>labelCaptureMixerChannel</cstring>
+ </property>
+ <property name="text">
+ <string>Capture Mixer Channel</string>
+ </property>
+ </widget>
+ <widget class="TQComboBox" row="4" column="1">
+ <property name="name">
+ <cstring>comboCaptureMixerDevice</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQComboBox" row="3" column="1">
+ <property name="name">
+ <cstring>comboPlaybackMixerChannel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQComboBox" row="2" column="1">
+ <item>
+ <property name="text">
+ <string>test</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>comboPlaybackMixerDevice</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="1">
+ <property name="name">
+ <cstring>labelDescription</cstring>
+ </property>
+ <property name="text">
+ <string>unknown v4l device</string>
+ </property>
+ </widget>
+ <widget class="TQLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>editRadioDevice</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <spacer row="9" column="1">
+ <property name="name">
+ <cstring>spacer15</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>5</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQCheckBox" row="6" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>m_checkboxActivePlayback</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Use active pla&amp;yback by capturing</string>
+ </property>
+ <property name="accel">
+ <string>Alt+Y</string>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="7" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>m_checkboxMuteOnPowerOff</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Mute Play&amp;back Channel on Power Off</string>
+ </property>
+ <property name="accel">
+ <string>Alt+B</string>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="8" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>m_checkboxVolumeZeroOnPowerOff</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Set Playback Channel Volume to &amp;Zero on Power Off</string>
+ </property>
+ <property name="accel">
+ <string>Alt+Z</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Options</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="2">
+ <property name="name">
+ <cstring>layout37</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelFrequencyRange</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>to</string>
+ </property>
+ </widget>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>editMaxFrequency</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> kHz</string>
+ </property>
+ <property name="maxValue">
+ <number>300000</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="lineStep">
+ <number>1000</number>
+ </property>
+ <property name="value">
+ <number>300000</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>editScanStep</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> kHz</string>
+ </property>
+ <property name="maxValue">
+ <number>500</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>labelSignalMinQuality</cstring>
+ </property>
+ <property name="text">
+ <string>minimum signal quality</string>
+ </property>
+ </widget>
+ <widget class="TQSpinBox" row="0" column="1">
+ <property name="name">
+ <cstring>editMinFrequency</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> kHz</string>
+ </property>
+ <property name="maxValue">
+ <number>2999999</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="lineStep">
+ <number>1000</number>
+ </property>
+ <property name="value">
+ <number>0</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>labelScanStep</cstring>
+ </property>
+ <property name="text">
+ <string>station scan step</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>labelMinMaxFrequency</cstring>
+ </property>
+ <property name="text">
+ <string>allowed frequency range</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="2">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="TQSpinBox" row="2" column="1">
+ <property name="name">
+ <cstring>editSignalMinQuality</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="value">
+ <number>75</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="2">
+ <property name="name">
+ <cstring>textLabel1_4_2</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>spacer16</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>V4L Mixer Controls</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout35</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelDeviceVolume</cstring>
+ </property>
+ <property name="text">
+ <string>volume</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout34</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer42</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQSlider">
+ <property name="name">
+ <cstring>sliderDeviceVolume</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer43</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="KDoubleNumInput">
+ <property name="name">
+ <cstring>editDeviceVolume</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1</number>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout35_2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelTreble</cstring>
+ </property>
+ <property name="text">
+ <string>treble</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout34_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer42_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQSlider">
+ <property name="name">
+ <cstring>sliderTreble</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer43_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="KDoubleNumInput">
+ <property name="name">
+ <cstring>editTreble</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1</number>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget" row="0" column="2">
+ <property name="name">
+ <cstring>layout35_2_2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelBass</cstring>
+ </property>
+ <property name="text">
+ <string>bass</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>layout34_2_3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer42_2_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQSlider">
+ <property name="name">
+ <cstring>sliderBass</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer43_2_3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="KDoubleNumInput">
+ <property name="name">
+ <cstring>editBass</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1</number>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget" row="0" column="3">
+ <property name="name">
+ <cstring>layout51</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelBalance</cstring>
+ </property>
+ <property name="text">
+ <string>balance</string>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer40</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>33</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQSlider">
+ <property name="name">
+ <cstring>sliderBalance</cstring>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>65535</number>
+ </property>
+ <property name="pageStep">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>0</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer41</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>33</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KDoubleNumInput">
+ <property name="name">
+ <cstring>editBalance</cstring>
+ </property>
+ <property name="minValue">
+ <number>-1</number>
+ </property>
+ <property name="maxValue">
+ <number>1</number>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>editRadioDevice</tabstop>
+ <tabstop>buttonSelectRadioDevice</tabstop>
+ <tabstop>comboPlaybackMixerChannel</tabstop>
+ <tabstop>editMinFrequency</tabstop>
+ <tabstop>editMaxFrequency</tabstop>
+ <tabstop>editSignalMinQuality</tabstop>
+</tabstops>
+<pixmapfunction>SmallIconSet</pixmapfunction>
+<layoutdefaults spacing="6" margin="0"/>
+<includes>
+ <include location="global" impldecl="in implementation">kiconloader.h</include>
+ <include location="global" impldecl="in implementation">knuminput.h</include>
+ <include location="global" impldecl="in implementation">ktabwidget.h</include>
+</includes>
+</UI>
diff --git a/plugins/v4lradio/v4lradio-configuration.cpp b/plugins/v4lradio/v4lradio-configuration.cpp
new file mode 100644
index 0000000..ea71f9f
--- /dev/null
+++ b/plugins/v4lradio/v4lradio-configuration.cpp
@@ -0,0 +1,648 @@
+/***************************************************************************
+ v4lradio-configuration.cpp - description
+ -------------------
+ begin : Fre Jun 20 2003
+ copyright : (C) 2003 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 <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/soundcard.h>
+
+#include <tqspinbox.h>
+#include <tqlineedit.h>
+#include <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqfile.h>
+#include <tqpushbutton.h>
+#include <tqslider.h>
+#include <tqcheckbox.h>
+
+#include <tdefiledialog.h>
+#include <knuminput.h>
+#include <tdelocale.h>
+#include <ktabwidget.h>
+
+#include "../../src/include/utils.h"
+#include "../../src/include/gui_list_helper.h"
+#include "v4lradio-configuration.h"
+#include "v4lradio.h"
+
+V4LRadioConfiguration::V4LRadioConfiguration (TQWidget *parent, SoundStreamID ssid)
+ : V4LRadioConfigurationUI(parent),
+ m_SoundStreamID(ssid),
+ m_ignoreGUIChanges(false),
+ m_myControlChange(0),
+ m_orgTreble(-1),
+ m_orgBass(-1),
+ m_orgBalance(-2),
+ m_orgDeviceVolume(-1),
+ m_PlaybackMixerHelper(comboPlaybackMixerDevice, StringListHelper::SORT_BY_DESCR),
+ m_CaptureMixerHelper (comboCaptureMixerDevice, StringListHelper::SORT_BY_DESCR),
+ m_PlaybackChannelHelper(comboPlaybackMixerChannel),
+ m_CaptureChannelHelper (comboCaptureMixerChannel)
+{
+ TQObject::connect(buttonSelectRadioDevice, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(selectRadioDevice()));
+ editRadioDevice->installEventFilter(this);
+ TQObject::connect(editMinFrequency, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(guiMinFrequencyChanged(int)));
+ TQObject::connect(editMaxFrequency, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(guiMaxFrequencyChanged(int)));
+
+ TQObject::connect(editDeviceVolume, TQT_SIGNAL(valueChanged(double)),
+ this, TQT_SLOT(slotDeviceVolumeChanged(double)));
+ TQObject::connect(editTreble, TQT_SIGNAL(valueChanged(double)),
+ this, TQT_SLOT(slotTrebleChanged(double)));
+ TQObject::connect(editBass, TQT_SIGNAL(valueChanged(double)),
+ this, TQT_SLOT(slotBassChanged(double)));
+ TQObject::connect(editBalance, TQT_SIGNAL(valueChanged(double)),
+ this, TQT_SLOT(slotBalanceChanged(double)));
+
+ TQObject::connect(sliderDeviceVolume, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotDeviceVolumeChanged(int)));
+ TQObject::connect(sliderTreble, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotTrebleChanged(int)));
+ TQObject::connect(sliderBass, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotBassChanged(int)));
+ TQObject::connect(sliderBalance, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotBalanceChanged(int)));
+
+ TQObject::connect(comboPlaybackMixerDevice, TQT_SIGNAL(activated(int)),
+ this, TQT_SLOT(slotComboPlaybackMixerSelected(int)));
+ TQObject::connect(comboCaptureMixerDevice, TQT_SIGNAL(activated(int)),
+ this, TQT_SLOT(slotComboCaptureMixerSelected(int)));
+
+ sliderBalance->installEventFilter(this);
+}
+
+
+V4LRadioConfiguration::~V4LRadioConfiguration ()
+{
+}
+
+
+bool V4LRadioConfiguration::connectI (Interface *i)
+{
+ bool a = IV4LCfgClient::connectI(i);
+ bool b = IFrequencyRadioClient::connectI(i);
+ bool c = IRadioDeviceClient::connectI(i);
+ bool d = ISoundStreamClient::connectI(i);
+ return a || b || c || d;
+}
+
+
+bool V4LRadioConfiguration::disconnectI (Interface *i)
+{
+ bool a = IV4LCfgClient::disconnectI(i);
+ bool b = IFrequencyRadioClient::disconnectI(i);
+ bool c = IRadioDeviceClient::disconnectI(i);
+ bool d = ISoundStreamClient::disconnectI(i);
+ return a || b || c || d;
+}
+
+void V4LRadioConfiguration::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid)
+{
+ ISoundStreamClient::noticeConnectedI(s, pointer_valid);
+ if (s && pointer_valid) {
+ s->register4_notifyTrebleChanged(this);
+ s->register4_notifyBassChanged(this);
+ s->register4_notifyBalanceChanged(this);
+ s->register4_notifySignalMinQualityChanged(this);
+
+ s->register4_notifyPlaybackChannelsChanged(this);
+ s->register4_notifyCaptureChannelsChanged(this);
+ s->register4_notifySoundStreamCreated(this);
+ }
+}
+
+void V4LRadioConfiguration::noticeConnectedSoundClient(ISoundStreamClient::thisInterface *i, bool pointer_valid)
+{
+ if (i && pointer_valid && i->supportsPlayback()) {
+ const TQString &org_mid = queryPlaybackMixerID();
+ bool org_present = m_PlaybackMixerHelper.contains(org_mid);
+ const TQString &mid = org_present ? m_PlaybackMixerHelper.getCurrentItem() : org_mid;
+ const TQString &org_ch = queryPlaybackMixerChannel();
+ const TQString &ch = org_present ? m_PlaybackChannelHelper.getCurrentText() : org_ch;
+ noticePlaybackMixerChanged(mid, ch);
+ }
+ if (i && pointer_valid && i->supportsCapture()) {
+ const TQString &org_mid = queryCaptureMixerID();
+ bool org_present = m_CaptureMixerHelper.contains(org_mid);
+ const TQString &mid = org_present ? m_CaptureMixerHelper.getCurrentItem() : org_mid;
+ const TQString &org_ch = queryCaptureMixerChannel();
+ const TQString &ch = org_present ? m_CaptureChannelHelper.getCurrentText() : org_ch;
+ noticeCaptureMixerChanged(mid, ch);
+ }
+}
+
+
+void V4LRadioConfiguration::noticeDisconnectedSoundClient(ISoundStreamClient::thisInterface *i, bool pointer_valid)
+{
+ if (i && pointer_valid && i->supportsPlayback()) {
+ noticePlaybackMixerChanged(queryPlaybackMixerID(), queryPlaybackMixerChannel());
+ }
+ if (i && pointer_valid && i->supportsCapture()) {
+ noticeCaptureMixerChanged (queryCaptureMixerID(), queryCaptureMixerChannel());
+ }
+}
+
+// IV4LCfgClient
+
+bool V4LRadioConfiguration::noticeRadioDeviceChanged(const TQString &s)
+{
+ bool old = m_ignoreGUIChanges;
+ m_ignoreGUIChanges = true;
+
+ editRadioDevice->setText(s);
+
+ m_ignoreGUIChanges = old;
+ return true;
+}
+
+
+bool V4LRadioConfiguration::noticePlaybackMixerChanged(const TQString &_mixer_id, const TQString &Channel)
+{
+ TQString mixer_id = _mixer_id;
+ bool old = m_ignoreGUIChanges;
+ m_ignoreGUIChanges = true;
+
+ m_PlaybackMixerHelper.setData(getPlaybackClientDescriptions());
+ m_PlaybackMixerHelper.setCurrentItem(mixer_id);
+ mixer_id = m_PlaybackMixerHelper.getCurrentItem();
+
+ ISoundStreamClient *mixer = getSoundStreamClientWithID(mixer_id);
+ if (mixer) {
+ m_PlaybackChannelHelper.setData(mixer->getPlaybackChannels());
+ m_PlaybackChannelHelper.setCurrentText(m_PlaybackChannelHelper.contains(Channel) ? Channel : queryPlaybackMixerChannel());
+ }
+ labelPlaybackMixerChannel->setEnabled(mixer != NULL);
+ comboPlaybackMixerChannel->setEnabled(mixer != NULL);
+
+ m_ignoreGUIChanges = old;
+ return true;
+}
+
+
+bool V4LRadioConfiguration::noticeCaptureMixerChanged(const TQString &_mixer_id, const TQString &Channel)
+{
+ TQString mixer_id = _mixer_id;
+ bool old = m_ignoreGUIChanges;
+ m_ignoreGUIChanges = true;
+
+ m_CaptureMixerHelper.setData(getCaptureClientDescriptions());
+ m_CaptureMixerHelper.setCurrentItem(mixer_id);
+ mixer_id = m_CaptureMixerHelper.getCurrentItem();
+
+ ISoundStreamClient *mixer = getSoundStreamClientWithID(mixer_id);
+ if (mixer) {
+ m_CaptureChannelHelper.setData(mixer->getCaptureChannels());
+ m_CaptureChannelHelper.setCurrentText(m_CaptureChannelHelper.contains(Channel) ? Channel : queryCaptureMixerChannel());
+ }
+ labelCaptureMixerChannel->setEnabled(mixer != NULL);
+ comboCaptureMixerChannel->setEnabled(mixer != NULL);
+
+ m_ignoreGUIChanges = old;
+ return true;
+}
+
+
+bool V4LRadioConfiguration::noticeDeviceVolumeChanged(float v)
+{
+ bool old = m_ignoreGUIChanges;
+ m_ignoreGUIChanges = true;
+ v = v > 1 ? 1 : v;
+ v = v < 0 ? 0 : v;
+
+ if (!m_myControlChange)
+ m_orgDeviceVolume = v;
+
+ editDeviceVolume ->setValue(v);
+ sliderDeviceVolume->setValue(m_caps.maxVolume - m_caps.intGetVolume(v));
+ m_ignoreGUIChanges = old;
+ return true;
+}
+
+
+bool V4LRadioConfiguration::noticeCapabilitiesChanged(const V4LCaps &c)
+{
+ bool old = m_ignoreGUIChanges;
+ m_ignoreGUIChanges = true;
+
+ labelDeviceVolume ->setEnabled(c.hasVolume);
+ editDeviceVolume ->setEnabled(c.hasVolume);
+ editDeviceVolume ->setRange(0, 1, c.volumeStep(), false);
+ sliderDeviceVolume->setMinValue(0);
+ sliderDeviceVolume->setMaxValue(c.maxVolume - c.minVolume);
+ sliderDeviceVolume->setEnabled(c.hasVolume);
+
+ labelTreble ->setEnabled(c.hasTreble);
+ editTreble ->setEnabled(c.hasTreble);
+ editTreble ->setRange(0, 1, c.trebleStep(), false);
+ sliderTreble->setMinValue(0);
+ sliderTreble->setMaxValue(c.maxTreble - c.minTreble);
+ sliderTreble->setEnabled(c.hasTreble);
+
+ labelBass ->setEnabled(c.hasBass);
+ editBass ->setEnabled(c.hasBass);
+ editBass ->setRange(0, 1, c.bassStep(), false);
+ sliderBass->setMinValue(0);
+ sliderBass->setMaxValue(c.maxBass - c.minBass);
+ sliderBass->setEnabled(c.hasBass);
+
+ labelBalance ->setEnabled(c.hasBalance);
+ editBalance ->setEnabled(c.hasBalance);
+ editBalance ->setRange(-1, 1, c.balanceStep(), false);
+ sliderBalance->setMinValue(0);
+ sliderBalance->setMaxValue(c.maxBalance - c.minBalance);
+ sliderBalance->setEnabled(c.hasBalance);
+
+ m_caps = c;
+
+ float tmp = 0;
+ noticeDeviceVolumeChanged(queryDeviceVolume());
+
+ queryTreble(m_SoundStreamID, tmp);
+ noticeTrebleChanged(m_SoundStreamID, tmp);
+
+ queryBass(m_SoundStreamID, tmp);
+ noticeBassChanged(m_SoundStreamID, tmp);
+
+ queryBalance(m_SoundStreamID, tmp);
+ noticeBalanceChanged(m_SoundStreamID, tmp);
+
+ m_ignoreGUIChanges = old;
+ return true;
+}
+
+bool V4LRadioConfiguration::noticeActivePlaybackChanged(bool a)
+{
+ bool old = m_ignoreGUIChanges;
+ m_ignoreGUIChanges = true;
+ m_checkboxActivePlayback->setChecked(a);
+ m_ignoreGUIChanges = old;
+ return true;
+}
+
+bool V4LRadioConfiguration::noticeMuteOnPowerOffChanged(bool a)
+{
+ bool old = m_ignoreGUIChanges;
+ m_ignoreGUIChanges = true;
+ m_checkboxMuteOnPowerOff->setChecked(a);
+ m_ignoreGUIChanges = old;
+ return true;
+}
+
+bool V4LRadioConfiguration::noticeVolumeZeroOnPowerOffChanged(bool a)
+{
+ bool old = m_ignoreGUIChanges;
+ m_ignoreGUIChanges = true;
+ m_checkboxVolumeZeroOnPowerOff->setChecked(a);
+ m_ignoreGUIChanges = old;
+ return true;
+}
+
+// IRadioDeviceClient
+
+bool V4LRadioConfiguration::noticeDescriptionChanged (const TQString &s, const IRadioDevice */*sender*/)
+{
+ labelDescription->setText(s);
+ return true;
+}
+
+
+// IFrequencyRadioClient
+
+bool V4LRadioConfiguration::noticeFrequencyChanged(float /*f*/, const RadioStation */*s*/)
+{
+ return false; // we don't care
+}
+
+
+bool V4LRadioConfiguration::noticeMinMaxFrequencyChanged(float min, float max)
+{
+ editMinFrequency->setValue((int)rint(min*1000));
+ editMaxFrequency->setValue((int)rint(max*1000));
+ return true;
+}
+
+
+bool V4LRadioConfiguration::noticeDeviceMinMaxFrequencyChanged(float min, float max)
+{
+ editMinFrequency->setMinValue((int)rint(min*1000));
+ editMaxFrequency->setMaxValue((int)rint(max*1000));
+ return true;
+}
+
+
+bool V4LRadioConfiguration::noticeScanStepChanged(float s)
+{
+ editScanStep->setValue((int)rint(s * 1000));
+ return true;
+}
+
+
+// IRadioSoundClient
+
+bool V4LRadioConfiguration::noticeTrebleChanged(SoundStreamID id, float t)
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ bool old = m_ignoreGUIChanges;
+ m_ignoreGUIChanges = true;
+ t = t > 1 ? 1 : t;
+ t = t < 0 ? 0 : t;
+
+ if (!m_myControlChange)
+ m_orgTreble = t;
+
+ editTreble ->setValue (t);
+ sliderTreble->setValue(m_caps.maxTreble - m_caps.intGetTreble(t));
+ m_ignoreGUIChanges = old;
+ return true;
+}
+
+
+bool V4LRadioConfiguration::noticeBassChanged(SoundStreamID id, float b)
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ bool old = m_ignoreGUIChanges;
+ m_ignoreGUIChanges = true;
+ b = b > 1 ? 1 : b;
+ b = b < 0 ? 0 : b;
+
+ if (!m_myControlChange)
+ m_orgBass = b;
+
+ editBass ->setValue(b);
+ sliderBass->setValue(m_caps.maxBass - m_caps.intGetBass(b));
+ m_ignoreGUIChanges = old;
+ return true;
+}
+
+
+bool V4LRadioConfiguration::noticeBalanceChanged(SoundStreamID id, float b)
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ bool old = m_ignoreGUIChanges;
+ m_ignoreGUIChanges = true;
+ b = b > 1 ? 1 : b;
+ b = b < -1 ? -1 : b;
+
+ if (!m_myControlChange)
+ m_orgBalance = b;
+
+ editBalance ->setValue(b);
+ sliderBalance->setValue(m_caps.intGetBalance(b));
+ m_ignoreGUIChanges = old;
+ return true;
+}
+
+
+bool V4LRadioConfiguration::noticeSignalMinQualityChanged(SoundStreamID id, float q)
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ editSignalMinQuality->setValue((int)rint(q * 100));
+ return true;
+}
+
+
+bool V4LRadioConfiguration::noticeSoundStreamCreated(SoundStreamID id)
+{
+ if (id.HasSamePhysicalID(m_SoundStreamID)) {
+ m_SoundStreamID = id;
+ }
+ return true;
+}
+
+
+// GUI Slots
+
+
+void V4LRadioConfiguration::selectRadioDevice()
+{
+ KFileDialog fd("/dev/",
+ i18n("any ( * )").ascii(),
+ this,
+ i18n("Radio Device Selection").ascii(),
+ TRUE);
+ fd.setMode(KFile::File | KFile::ExistingOnly);
+ fd.setCaption (i18n("Select Radio Device"));
+
+ if (fd.exec() == TQDialog::Accepted) {
+ editRadioDevice->setText(fd.selectedFile());
+ }
+}
+
+
+bool V4LRadioConfiguration::eventFilter(TQObject *o, TQEvent *e)
+{
+ if (e->type() == TQEvent::FocusOut && TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(editRadioDevice)) {
+ slotEditRadioDeviceChanged();
+ }
+ if (e->type() == TQEvent::MouseButtonDblClick && TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(sliderBalance)) {
+ slotBalanceCenter();
+ }
+ return false;
+}
+
+
+void V4LRadioConfiguration::slotEditRadioDeviceChanged()
+{
+ if (m_ignoreGUIChanges) return;
+ const TQString &s = editRadioDevice->text();
+ if (s != queryRadioDevice() || !queryIsPowerOn()) {
+ V4LCaps c = queryCapabilities(s);
+ noticeDescriptionChanged(c.description);
+ } else {
+ noticeDescriptionChanged(queryDescription());
+ }
+}
+
+
+void V4LRadioConfiguration::slotComboPlaybackMixerSelected(int /*idx*/)
+{
+ if (m_ignoreGUIChanges) return;
+ TQString id = m_PlaybackMixerHelper.getCurrentItem();
+ noticePlaybackMixerChanged(id, queryPlaybackMixerChannel());
+}
+
+
+void V4LRadioConfiguration::slotComboCaptureMixerSelected(int /*idx*/)
+{
+ if (m_ignoreGUIChanges) return;
+ TQString id = m_CaptureMixerHelper.getCurrentItem();
+ noticeCaptureMixerChanged(id, queryCaptureMixerChannel());
+}
+
+
+void V4LRadioConfiguration::slotOK()
+{
+ sendMinFrequency(((float)editMinFrequency->value()) / 1000.0);
+ sendMaxFrequency(((float)editMaxFrequency->value()) / 1000.0);
+ sendSignalMinQuality(m_SoundStreamID, editSignalMinQuality->value() * 0.01);
+ sendRadioDevice(editRadioDevice->text());
+ sendScanStep(((float)editScanStep->value()) / 1000.0);
+
+ sendCaptureMixer (m_CaptureMixerHelper.getCurrentItem(),
+ m_CaptureChannelHelper.getCurrentText());
+ sendPlaybackMixer(m_PlaybackMixerHelper.getCurrentItem(),
+ m_PlaybackChannelHelper.getCurrentText());
+
+ sendActivePlayback(m_checkboxActivePlayback->isChecked());
+ sendMuteOnPowerOff(m_checkboxMuteOnPowerOff->isChecked());
+ sendVolumeZeroOnPowerOff(m_checkboxVolumeZeroOnPowerOff->isChecked());
+
+ queryTreble (m_SoundStreamID, m_orgTreble);
+ queryBass (m_SoundStreamID, m_orgBass);
+ queryBalance(m_SoundStreamID, m_orgBalance);
+ m_orgDeviceVolume = queryDeviceVolume();
+}
+
+
+void V4LRadioConfiguration::slotCancel()
+{
+ noticeRadioDeviceChanged(queryRadioDevice());
+ noticePlaybackMixerChanged(queryPlaybackMixerID(), queryPlaybackMixerChannel());
+ noticeCaptureMixerChanged (queryCaptureMixerID(), queryCaptureMixerChannel());
+ noticeMinMaxFrequencyChanged(queryMinFrequency(), queryMaxFrequency());
+ noticeActivePlaybackChanged(queryActivePlayback());
+ noticeMuteOnPowerOffChanged(queryMuteOnPowerOff());
+ noticeVolumeZeroOnPowerOffChanged(queryVolumeZeroOnPowerOff());
+
+ float q = 0;
+ querySignalMinQuality(m_SoundStreamID, q);
+ noticeSignalMinQualityChanged(m_SoundStreamID, q);
+ noticeScanStepChanged(queryScanStep());
+
+ sendTreble (m_SoundStreamID, m_orgTreble);
+ sendBass (m_SoundStreamID, m_orgBass);
+ sendBalance (m_SoundStreamID, m_orgBalance);
+ sendDeviceVolume(m_orgDeviceVolume);
+}
+
+
+void V4LRadioConfiguration::guiMinFrequencyChanged(int v)
+{
+ editMaxFrequency->setMinValue(v);
+}
+
+
+void V4LRadioConfiguration::guiMaxFrequencyChanged(int v)
+{
+ editMinFrequency->setMaxValue(v);
+}
+
+void V4LRadioConfiguration::slotDeviceVolumeChanged (double v) // for KDoubleNumInput, 0.0..1.0
+{
+ if (m_ignoreGUIChanges) return;
+ ++m_myControlChange;
+ sendDeviceVolume(v);
+ --m_myControlChange;
+}
+
+void V4LRadioConfiguration::slotTrebleChanged (double t) // for KDoubleNumInput, 0.0..1.0
+{
+ if (m_ignoreGUIChanges) return;
+ ++m_myControlChange;
+ sendTreble(m_SoundStreamID, t);
+ --m_myControlChange;
+}
+
+void V4LRadioConfiguration::slotBassChanged (double b) // for KDoubleNumInput, 0.0..1.0
+{
+ if (m_ignoreGUIChanges) return;
+ ++m_myControlChange;
+ sendBass(m_SoundStreamID, b);
+ --m_myControlChange;
+}
+
+void V4LRadioConfiguration::slotBalanceChanged(double b) // for KDoubleNumInput, -1.0..1.0
+{
+ if (m_ignoreGUIChanges) return;
+ ++m_myControlChange;
+ sendBalance(m_SoundStreamID, b);
+ --m_myControlChange;
+}
+
+
+void V4LRadioConfiguration::slotDeviceVolumeChanged (int v)
+{
+ if (m_ignoreGUIChanges) return;
+ ++m_myControlChange;
+ sendDeviceVolume(m_caps.floatGetVolume(m_caps.maxVolume - v));
+ --m_myControlChange;
+}
+
+void V4LRadioConfiguration::slotTrebleChanged (int t)
+{
+ if (m_ignoreGUIChanges) return;
+ ++m_myControlChange;
+ sendTreble(m_SoundStreamID, m_caps.floatGetTreble(m_caps.maxTreble - t));
+ --m_myControlChange;
+}
+
+void V4LRadioConfiguration::slotBassChanged (int b)
+{
+ if (m_ignoreGUIChanges) return;
+ ++m_myControlChange;
+ sendBass(m_SoundStreamID, m_caps.floatGetBass(m_caps.maxBass - b));
+ --m_myControlChange;
+}
+
+void V4LRadioConfiguration::slotBalanceChanged(int b)
+{
+ if (m_ignoreGUIChanges) return;
+ ++m_myControlChange;
+ sendBalance(m_SoundStreamID, m_caps.floatGetBalance(b));
+ --m_myControlChange;
+}
+
+
+void V4LRadioConfiguration::slotBalanceCenter()
+{
+ if (m_ignoreGUIChanges) return;
+ ++m_myControlChange;
+ sendBalance(m_SoundStreamID, 0);
+ --m_myControlChange;
+}
+
+
+bool V4LRadioConfiguration::noticePlaybackChannelsChanged(const TQString & client_id, const TQStringList &/*channels*/)
+{
+ if (m_PlaybackMixerHelper.getCurrentItem() == client_id) {
+ noticePlaybackMixerChanged(client_id, m_PlaybackChannelHelper.getCurrentText());
+ }
+ return true;
+}
+
+
+bool V4LRadioConfiguration::noticeCaptureChannelsChanged (const TQString & client_id, const TQStringList &/*channels*/)
+{
+ if (m_CaptureMixerHelper.getCurrentItem() == client_id) {
+ noticeCaptureMixerChanged(client_id, m_CaptureChannelHelper.getCurrentText());
+ }
+ return true;
+}
+
+
+
+#include "v4lradio-configuration.moc"
diff --git a/plugins/v4lradio/v4lradio-configuration.h b/plugins/v4lradio/v4lradio-configuration.h
new file mode 100644
index 0000000..7474a27
--- /dev/null
+++ b/plugins/v4lradio/v4lradio-configuration.h
@@ -0,0 +1,148 @@
+/***************************************************************************
+ v4lradio-configuration.h - description
+ -------------------
+ begin : Fre Jun 20 2003
+ copyright : (C) 2003 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_V4LRADIO_CONFIGURATION_H
+#define KRADIO_V4LRADIO_CONFIGURATION_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../../src/include/radiodevice_interfaces.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+#include "../../src/include/gui_list_helper.h"
+
+#include "v4lradio-configuration-ui.h"
+#include "v4lcfg_interfaces.h"
+
+class V4LRadio;
+class TQWidget;
+
+class V4LRadioConfiguration : public V4LRadioConfigurationUI,
+ public IV4LCfgClient,
+ public IFrequencyRadioClient,
+ public ISoundStreamClient,
+ public IRadioDeviceClient
+{
+Q_OBJECT
+
+public :
+ V4LRadioConfiguration (TQWidget *parent, SoundStreamID id);
+ ~V4LRadioConfiguration ();
+
+ bool connectI (Interface *i);
+ bool disconnectI (Interface *i);
+
+ void noticeConnectedSoundClient(ISoundStreamClient::thisInterface *i, bool pointer_valid);
+ void noticeDisconnectedSoundClient(ISoundStreamClient::thisInterface *i, bool pointer_valid);
+
+// IV4LCfgClient
+
+RECEIVERS:
+ bool noticeRadioDeviceChanged(const TQString &s);
+ bool noticePlaybackMixerChanged(const TQString &soundStreamClientID, const TQString &Channel);
+ bool noticeCaptureMixerChanged (const TQString &soundStreamClientID, const TQString &Channel);
+ bool noticeDeviceVolumeChanged(float v);
+ bool noticeCapabilitiesChanged(const V4LCaps &c);
+ bool noticeActivePlaybackChanged(bool a);
+ bool noticeMuteOnPowerOffChanged(bool a);
+ bool noticeVolumeZeroOnPowerOffChanged(bool a);
+
+// IRadioDeviceClient
+
+RECEIVERS:
+ bool noticePowerChanged (bool /*on*/, const IRadioDevice */*sender = NULL*/) { return false; }
+ bool noticeStationChanged (const RadioStation &, const IRadioDevice */*sender = NULL*/) { return false; }
+ bool noticeDescriptionChanged (const TQString &, const IRadioDevice *sender = NULL);
+
+ bool noticeCurrentSoundStreamIDChanged(SoundStreamID /*id*/, const IRadioDevice */*sender*/) { return false; }
+
+// IFrequencyRadioClient
+
+RECEIVERS:
+ bool noticeFrequencyChanged(float f, const RadioStation *s);
+ bool noticeMinMaxFrequencyChanged(float min, float max);
+ bool noticeDeviceMinMaxFrequencyChanged(float min, float max);
+ bool noticeScanStepChanged(float s);
+
+// ISoundStreamClient
+
+RECEIVERS:
+ void noticeConnectedI (ISoundStreamServer *s, bool pointer_valid);
+
+ bool noticeTrebleChanged(SoundStreamID id, float t);
+ bool noticeBassChanged(SoundStreamID id, float b);
+ bool noticeBalanceChanged(SoundStreamID id, float b);
+ bool noticeSignalMinQualityChanged(SoundStreamID id, float q);
+
+ bool noticePlaybackChannelsChanged(const TQString & /*client_id*/, const TQStringList &/*channels*/);
+ bool noticeCaptureChannelsChanged (const TQString & /*client_id*/, const TQStringList &/*channels*/);
+ bool noticeSoundStreamCreated(SoundStreamID /*id*/);
+
+
+protected:
+
+ bool eventFilter(TQObject *o, TQEvent *e);
+
+protected slots:
+
+ void selectRadioDevice();
+ void slotEditRadioDeviceChanged();
+ void slotComboPlaybackMixerSelected(int idx);
+ void slotComboCaptureMixerSelected(int idx);
+
+ void slotOK();
+ void slotCancel();
+
+ void guiMinFrequencyChanged(int v);
+ void guiMaxFrequencyChanged(int v);
+
+ void slotDeviceVolumeChanged (double v); // for KDoubleNumInput, 0.0..1.0
+ void slotTrebleChanged (double t); // for KDoubleNumInput, 0.0..1.0
+ void slotBassChanged (double b); // for KDoubleNumInput, 0.0..1.0
+ void slotBalanceChanged(double b); // for KDoubleNumInput, -1.0..1.0
+
+ void slotDeviceVolumeChanged (int v); // for slider, 0..65535
+ void slotTrebleChanged (int t); // for slider, 0..65535
+ void slotBassChanged (int b); // for slider, 0..65535
+ void slotBalanceChanged(int b); // for slider, 0..65535
+ void slotBalanceCenter ();
+
+protected:
+
+ SoundStreamID m_SoundStreamID;
+
+ bool m_ignoreGUIChanges;
+
+ int m_myControlChange;
+ float m_orgTreble,
+ m_orgBass,
+ m_orgBalance,
+ m_orgDeviceVolume;
+
+ V4LCaps m_caps;
+
+ typedef GUIListHelper<TQComboBox, TQString> StringListHelper;
+ typedef GUISimpleListHelper<TQComboBox> ChannelListHelper;
+
+ StringListHelper m_PlaybackMixerHelper,
+ m_CaptureMixerHelper;
+ ChannelListHelper m_PlaybackChannelHelper,
+ m_CaptureChannelHelper;
+};
+
+#endif
diff --git a/plugins/v4lradio/v4lradio.cpp b/plugins/v4lradio/v4lradio.cpp
new file mode 100644
index 0000000..97564ea
--- /dev/null
+++ b/plugins/v4lradio/v4lradio.cpp
@@ -0,0 +1,1622 @@
+/***************************************************************************
+ v4lradio.cpp - description
+ -------------------
+ begin : Don M�r 8 21:57:17 CET 2001
+ copyright : (C) 2002-2005 by Ernst 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. *
+ * *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#ifdef HAVE_V4L2
+#include "linux/videodev2.h"
+#endif
+#include "linux/videodev.h"
+#include <linux/soundcard.h>
+
+#include <string.h> // memcpy needed
+
+#include <tqlayout.h>
+#include <tqfile.h>
+#include <tqfileinfo.h>
+#include <tqvaluelist.h>
+
+#include <tdeconfig.h>
+#include <kiconloader.h>
+#include <kdialogbase.h>
+#include <tdeaboutdata.h>
+#include <tdelocale.h>
+
+#include "../../src/include/aboutwidget.h"
+#include "../../src/include/utils.h"
+#include "v4lradio.h"
+#include "v4lradio-configuration.h"
+
+#include "../../src/include/debug-profiler.h"
+
+struct _lrvol { unsigned char l, r; short dummy; };
+
+///////////////////////////////////////////////////////////////////////
+
+PLUGIN_LIBRARY_FUNCTIONS(V4LRadio, "tderadio-v4lradio", i18n("Support for V4L(2) Radio Devices"));
+
+///////////////////////////////////////////////////////////////////////
+
+V4LRadio::V4LRadio(const TQString &name)
+ : PluginBase(name, i18n("Video For Linux Plugin")),
+ m_treble(0.5),
+ m_bass(0.5),
+ m_balance(0),
+ m_deviceVolume(0.9),
+ m_muted(false),
+ m_signalQuality(0),
+ m_stereo(false),
+ m_minQuality(0.75),
+ m_minFrequency(87.0),
+ m_maxFrequency(108.0),
+ m_lastMinDevFrequency(87.0),
+ m_lastMaxDevFrequency(108.0),
+
+ m_defaultPlaybackVolume(0.5),
+
+ m_scanStep(0.05),
+
+ m_radioDev("/dev/radio0"),
+ m_radio_fd(-1),
+ m_useOldV4L2Calls(true),
+ m_pollTimer(this),
+
+ m_blockReadTuner(false),
+ m_blockReadAudio(false),
+
+ m_SoundStreamID(createNewSoundStream(false)),
+ m_PlaybackMixerID(TQString()),
+ m_CaptureMixerID(TQString()),
+ m_PlaybackMixerChannel(TQString()),
+ m_CaptureMixerChannel(TQString()),
+ m_ActivePlayback(false),
+ m_MuteOnPowerOff(false),
+ m_VolumeZeroOnPowerOff(false),
+ m_restorePowerOn(false)
+{
+ TQObject::connect (&m_pollTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(poll()));
+ m_pollTimer.start(333);
+
+ m_audio = new video_audio;
+ bzero(m_audio, sizeof(video_audio));
+ m_tuner = new video_tuner;
+ bzero(m_tuner, sizeof(video_tuner));
+#ifdef HAVE_V4L2
+ m_tuner2 = new v4l2_tuner;
+ bzero(m_tuner2, sizeof(v4l2_tuner));
+#endif
+ m_caps.version = 0;
+
+ m_seekHelper = new FrequencySeekHelper(*this);
+ m_seekHelper->connectI(this);
+}
+
+
+V4LRadio::~V4LRadio()
+{
+ setPower(false);
+
+ if (m_seekHelper)
+ delete m_seekHelper;
+
+ if (m_audio) delete m_audio;
+ if (m_tuner) delete m_tuner;
+#ifdef HAVE_V4L2
+ if (m_tuner2) delete m_tuner2;
+#endif
+}
+
+
+bool V4LRadio::connectI (Interface *i)
+{
+ bool a = IRadioDevice::connectI(i);
+ bool b = ISeekRadio::connectI(i);
+ bool c = IFrequencyRadio::connectI(i);
+ bool d = IV4LCfg::connectI(i);
+ bool e = PluginBase::connectI(i);
+ bool f = ISoundStreamClient::connectI(i);
+ return a || b || c || d || e || f;
+}
+
+
+bool V4LRadio::disconnectI (Interface *i)
+{
+ bool a = IRadioDevice::disconnectI(i);
+ bool b = ISeekRadio::disconnectI(i);
+ bool c = IFrequencyRadio::disconnectI(i);
+ bool d = IV4LCfg::disconnectI(i);
+ bool e = PluginBase::disconnectI(i);
+ bool f = ISoundStreamClient::disconnectI(i);
+ m_seekHelper->disconnectI(i);
+ return a || b || c || d || e || f;
+}
+
+
+void V4LRadio::noticeConnectedI (ISoundStreamServer *s, bool pointer_valid)
+{
+ ISoundStreamClient::noticeConnectedI(s, pointer_valid);
+ if (s && pointer_valid) {
+ m_seekHelper->connectI(s);
+
+ s->register4_queryPlaybackVolume(this);
+ s->register4_sendTreble(this);
+ s->register4_sendBass(this);
+ s->register4_sendBalance(this);
+ s->register4_sendMute(this);
+ s->register4_sendUnmute(this);
+ s->register4_sendSignalMinQuality(this);
+ s->register4_sendStereo(this);
+
+ s->register4_queryTreble(this);
+ s->register4_queryBass(this);
+ s->register4_queryBalance(this);
+ s->register4_querySignalQuality(this);
+ s->register4_querySignalMinQuality(this);
+ s->register4_queryHasGoodQuality(this);
+ s->register4_queryIsStereo(this);
+ s->register4_queryIsMuted(this);
+
+
+ s->register4_sendPlaybackVolume(this);
+ s->register4_sendCaptureVolume(this);
+
+ s->register4_sendStopCapture(this);
+
+ s->register4_querySoundStreamDescription(this);
+ s->register4_querySoundStreamRadioStation(this);
+ s->register4_queryEnumerateSoundStreams(this);
+
+ notifySoundStreamCreated(m_SoundStreamID);
+ }
+}
+
+void V4LRadio::noticeConnectedSoundClient(ISoundStreamClient::thisInterface *i, bool pointer_valid)
+{
+ if (i && pointer_valid && i->getSoundStreamClientID() == m_PlaybackMixerID) {
+ setPlaybackMixer(m_PlaybackMixerID, m_PlaybackMixerChannel);
+ }
+ if (i && pointer_valid && i->getSoundStreamClientID() == m_CaptureMixerID) {
+ setCaptureMixer(m_CaptureMixerID, m_CaptureMixerChannel);
+ }
+}
+
+// IRadioDevice methods
+
+bool V4LRadio::setPower (bool on)
+{
+ return on ? powerOn() : powerOff();
+}
+
+void V4LRadio::searchMixers(ISoundStreamClient **playback_mixer, ISoundStreamClient **capture_mixer)
+{
+ if (playback_mixer) {
+ *playback_mixer = getSoundStreamClientWithID(m_PlaybackMixerID);
+ if (!*playback_mixer) {
+ TQPtrList<ISoundStreamClient> playback_mixers = queryPlaybackMixers();
+ if (!playback_mixers.isEmpty())
+ *playback_mixer = playback_mixers.first();
+ }
+ }
+ if (capture_mixer) {
+ *capture_mixer = getSoundStreamClientWithID(m_CaptureMixerID);
+ if (!*capture_mixer) {
+ TQPtrList<ISoundStreamClient> capture_mixers = queryCaptureMixers();
+ if (!capture_mixers.isEmpty())
+ *capture_mixer = capture_mixers.first();
+ }
+ }
+}
+
+
+bool V4LRadio::powerOn ()
+{
+ if (isPowerOn())
+ return true;
+
+ radio_init();
+
+ if (isPowerOn()) {
+ ISoundStreamClient *playback_mixer = NULL,
+ *capture_mixer = NULL;
+
+ searchMixers(&playback_mixer, &capture_mixer);
+
+ if (playback_mixer)
+ playback_mixer->preparePlayback(m_SoundStreamID, m_PlaybackMixerChannel, m_ActivePlayback, false);
+ if (capture_mixer)
+ capture_mixer->prepareCapture(m_SoundStreamID, m_CaptureMixerChannel);
+
+ sendStartPlayback(m_SoundStreamID);
+ float tmp_vol = 0;
+ queryPlaybackVolume(m_SoundStreamID, tmp_vol);
+ if (tmp_vol < 0.005)
+ sendPlaybackVolume(m_SoundStreamID, m_defaultPlaybackVolume);
+
+ if (m_ActivePlayback) {
+ SoundFormat sf;
+ sendStartCaptureWithFormat(m_SoundStreamID, sf, sf);
+ }
+
+ unmute(m_SoundStreamID);
+ notifyPowerChanged(true);
+ }
+
+ return true;
+}
+
+
+bool V4LRadio::powerOff ()
+{
+ if (! isPowerOn())
+ return true;
+
+ queryPlaybackVolume(m_SoundStreamID, m_defaultPlaybackVolume);
+ if (m_MuteOnPowerOff)
+ sendMute(m_SoundStreamID, true);
+ if (m_VolumeZeroOnPowerOff)
+ sendPlaybackVolume(m_SoundStreamID, 0.0);
+ mute(m_SoundStreamID);
+ radio_done();
+
+ sendStopPlayback(m_SoundStreamID);
+ sendStopCapture(m_SoundStreamID);
+ closeSoundStream(m_SoundStreamID);
+ m_SoundStreamID = createNewSoundStream(m_SoundStreamID, false);
+ notifySoundStreamCreated(m_SoundStreamID);
+
+ if (isPowerOff()) {
+ notifyPowerChanged(false);
+ }
+
+ return true;
+}
+
+
+bool V4LRadio::activateStation(const RadioStation &rs)
+{
+ const FrequencyRadioStation *frs = dynamic_cast<const FrequencyRadioStation*>(&rs);
+ if (frs == NULL)
+ return false;
+
+ if (setFrequency(frs->frequency())) {
+ m_currentStation = *frs;
+
+ if (frs->initialVolume() > 0)
+ setPlaybackVolume(m_SoundStreamID, frs->initialVolume());
+
+ return true;
+ }
+
+ return false;
+}
+
+
+
+bool V4LRadio::isPowerOn() const
+{
+ return m_radio_fd >= 0;
+}
+
+
+bool V4LRadio::isPowerOff() const
+{
+ return m_radio_fd < 0;
+}
+
+
+SoundStreamID V4LRadio::getSoundStreamID() const
+{
+ return m_SoundStreamID;
+}
+
+
+const RadioStation &V4LRadio::getCurrentStation() const
+{
+ return m_currentStation;
+}
+
+
+const TQString &V4LRadio::getDescription() const
+{
+ return m_caps.description;
+}
+
+
+SoundStreamID V4LRadio::getCurrentSoundStreamID() const
+{
+ return m_SoundStreamID;
+}
+
+
+
+
+bool V4LRadio::setTreble (SoundStreamID id, float t)
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ if (t > 1.0) t = 1.0;
+ if (t < 0) t = 0.0;
+ if ((int)rint(m_treble*65535) != (int)rint(t*65535)) {
+ m_treble = t;
+ writeAudioInfo();
+ notifyTrebleChanged(id, t);
+ }
+ return true;
+}
+
+
+bool V4LRadio::setBass (SoundStreamID id, float b)
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ if (b > 1.0) b = 1.0;
+ if (b < 0) b = 0.0;
+ if ((int)rint(m_bass*65535) != (int)rint(b*65535)) {
+ m_bass = b;
+ writeAudioInfo();
+ notifyBassChanged(id, b);
+ }
+
+ return true;
+}
+
+
+bool V4LRadio::setBalance (SoundStreamID id, float b)
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ if (b > +1.0) b = +1.0;
+ if (b < -1.0) b = -1.0;
+ if ((int)rint(m_balance*32767) != (int)rint(b*32767)) {
+ m_balance = b;
+ writeAudioInfo();
+ notifyBalanceChanged(id, b);
+ }
+ return true;
+}
+
+
+bool V4LRadio::setDeviceVolume (float v)
+{
+ if (v > 1.0) v = 1.0;
+ if (v < 0) v = 0;
+ if ((int)rint(m_deviceVolume*65535) != (int)rint(v*65535)) {
+ m_deviceVolume = v;
+ writeAudioInfo();
+ notifyDeviceVolumeChanged(v);
+ }
+ return true;
+}
+
+
+bool V4LRadio::mute (SoundStreamID id, bool mute)
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ if (m_muted != mute) {
+ m_muted = mute;
+ bool r = writeAudioInfo();
+ if (r)
+ notifyMuted(id, m_muted);
+ return r;
+ }
+ return false;
+}
+
+
+bool V4LRadio::unmute (SoundStreamID id, bool unmute)
+{
+ return mute(id, !unmute);
+}
+
+
+bool V4LRadio::setSignalMinQuality (SoundStreamID id, float mq)
+{
+ if (id != m_SoundStreamID)
+ return false;
+ if (rint(mq*100) == rint(m_minQuality*100))
+ return true;
+
+ m_minQuality = mq;
+ notifySignalMinQualityChanged(id, m_minQuality);
+ return true;
+}
+
+
+bool V4LRadio::setStereo(SoundStreamID /*id*/, bool /*b*/)
+{
+ // FIXME if possible
+ return false; // we can't do that currently, not even switch stereo to mono
+}
+
+
+
+
+bool V4LRadio::getTreble (SoundStreamID id, float &t) const
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ readAudioInfo();
+ t = m_treble;
+ return true;
+}
+
+
+bool V4LRadio::getBass (SoundStreamID id, float &b) const
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ readAudioInfo();
+ b = m_bass;
+ return true;
+}
+
+
+bool V4LRadio::getBalance (SoundStreamID id, float &b) const
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ readAudioInfo();
+ b = m_balance;
+ return true;
+}
+
+
+float V4LRadio::getDeviceVolume () const
+{
+ readAudioInfo();
+ return m_deviceVolume;
+}
+
+
+
+bool V4LRadio::getSignalMinQuality(SoundStreamID id, float &q) const
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ q = m_minQuality;
+ return true;
+}
+
+
+bool V4LRadio::getSignalQuality(SoundStreamID id, float &q) const
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ readTunerInfo();
+ q = m_signalQuality;
+ return true;
+}
+
+
+bool V4LRadio::hasGoodQuality(SoundStreamID id, bool &good) const
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ float q = 0;
+ if (getSignalQuality(id, q))
+ good = q >= m_minQuality;
+ return true;
+}
+
+
+bool V4LRadio::isStereo(SoundStreamID id, bool &s) const
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ readAudioInfo();
+ s = m_stereo;
+ return true;
+}
+
+
+bool V4LRadio::isMuted(SoundStreamID id, bool &m) const
+{
+ if (id != m_SoundStreamID)
+ return false;
+
+ readAudioInfo();
+ m = m_muted;
+ return true;
+}
+
+
+// ISeekRadio
+
+bool V4LRadio::toBeginning()
+{
+ setFrequency(getMinFrequency());
+ return true;
+}
+
+bool V4LRadio::toEnd()
+{
+ setFrequency(getMaxFrequency());
+ return true;
+}
+
+bool V4LRadio::startSeekUp()
+{
+ return startSeek(true);
+}
+
+bool V4LRadio::startSeekDown()
+{
+ return startSeek(false);
+}
+
+bool V4LRadio::startSeek(bool up)
+{
+ if (isPowerOn() && m_seekHelper) {
+ m_seekHelper->start(m_SoundStreamID, up ? SeekHelper::up : SeekHelper::down);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool V4LRadio::stopSeek()
+{
+ if (m_seekHelper) m_seekHelper->stop();
+ return true;
+}
+
+bool V4LRadio::isSeekRunning() const
+{
+ if (m_seekHelper)
+ return m_seekHelper->isRunning();
+ else
+ return false;
+}
+
+
+bool V4LRadio::isSeekUpRunning() const
+{
+ if (m_seekHelper)
+ return m_seekHelper->isRunningUp();
+ else
+ return false;
+}
+
+
+bool V4LRadio::isSeekDownRunning() const
+{
+ if (m_seekHelper)
+ return m_seekHelper->isRunningDown();
+ else
+ return false;
+}
+
+float V4LRadio::getProgress () const
+{
+ float min = getMinFrequency();
+ float max = getMaxFrequency();
+
+ return (getFrequency() - min) / (max - min);
+}
+
+
+// IFrequencyRadio
+
+bool V4LRadio::setFrequency(float freq)
+{
+// if (isSeekRunning())
+// stopSeek();
+
+ if (m_currentStation.frequency() == freq) {
+ return true;
+ }
+
+ float minf = getMinFrequency();
+ float maxf = getMaxFrequency();
+
+ if (isPowerOn()) {
+
+ bool oldMute = false;
+ isMuted(m_SoundStreamID, oldMute);
+ if (!oldMute && !m_ActivePlayback)
+ mute(m_SoundStreamID);
+
+
+ if (!m_tunercache.valid) readTunerInfo();
+ float df = m_tunercache.deltaF;
+
+ unsigned long lfreq = (unsigned long) rint(freq / df);
+
+ if (freq > maxf || freq < minf) {
+ logError("V4LRadio::setFrequency: " +
+ i18n("invalid frequency %1").arg(TQString().setNum(freq)));
+ if (!oldMute && !m_ActivePlayback)
+ unmute(m_SoundStreamID);
+ return false;
+ }
+
+ int r = -1;
+ if (m_caps.version == 1) {
+ r = ioctl(m_radio_fd, VIDIOCSFREQ, &lfreq);
+ }
+#ifdef HAVE_V4L2
+ else if (m_caps.version == 2) {
+ v4l2_frequency tmp;
+ tmp.tuner = 0;
+ tmp.type = V4L2_TUNER_RADIO;
+ tmp.frequency = lfreq;
+ r = ioctl(m_radio_fd, VIDIOC_S_FREQUENCY, &tmp);
+ }
+#endif
+ else {
+ logError("V4LRadio::setFrequency: " +
+ i18n("don't known how to handle V4L-version %1")
+ .arg(m_caps.version));
+ }
+
+ if (r) {
+ logError("V4LRadio::setFrequency: " +
+ i18n("error setting frequency to %1 (%2)")
+ .arg(TQString().setNum(freq))
+ .arg(TQString().setNum(r)));
+ // unmute the old radio with the old radio station
+ if (!oldMute && !m_ActivePlayback)
+ unmute(m_SoundStreamID);
+ return false;
+ }
+
+ // unmute this radio device, because we now have the current
+ // radio station
+ if (!oldMute && !m_ActivePlayback)
+ unmute(m_SoundStreamID);
+ }
+
+ m_currentStation.setFrequency(freq);
+ notifyFrequencyChanged(freq, &m_currentStation);
+ notifyStationChanged(m_currentStation);
+ notifyProgress((freq - minf) / (maxf - minf));
+ notifySoundStreamChanged(m_SoundStreamID);
+ return true;
+}
+
+
+bool V4LRadio::setMinFrequency (float minF)
+{
+ float oldm = getMinFrequency();
+ m_minFrequency = minF;
+
+ float newm = getMinFrequency();
+ if (oldm != newm)
+ notifyMinMaxFrequencyChanged(newm, getMaxFrequency());
+
+ return true;
+}
+
+
+bool V4LRadio::setMaxFrequency (float maxF)
+{
+ float oldm = getMaxFrequency();
+ m_maxFrequency = maxF;
+
+ float newm = getMaxFrequency();
+ if (oldm != newm)
+ notifyMinMaxFrequencyChanged(getMinFrequency(), newm);
+
+ return true;
+}
+
+
+bool V4LRadio::setScanStep(float s)
+{
+ float old = m_scanStep;
+ m_scanStep = s;
+
+ if (old != s) notifyScanStepChanged(m_scanStep);
+ return true;
+}
+
+
+float V4LRadio::getFrequency() const
+{
+ return m_currentStation.frequency();
+}
+
+
+float V4LRadio::getMinFrequency() const
+{
+ return m_minFrequency ? m_minFrequency : getMinDeviceFrequency();
+}
+
+
+float V4LRadio::getMaxFrequency() const
+{
+ return m_maxFrequency ? m_maxFrequency : getMaxDeviceFrequency();
+}
+
+
+float V4LRadio::getMinDeviceFrequency() const
+{
+ if (!m_tunercache.valid)
+ readTunerInfo();
+
+ return m_tunercache.minF;
+}
+
+
+float V4LRadio::getMaxDeviceFrequency() const
+{
+ if (!m_tunercache.valid)
+ readTunerInfo();
+
+ return m_tunercache.maxF;
+}
+
+
+float V4LRadio::getScanStep() const
+{
+ return m_scanStep;
+}
+
+
+
+// IV4LCfg methods
+
+bool V4LRadio::setRadioDevice(const TQString &s)
+{
+ if (m_radioDev != s) {
+ bool p = isPowerOn();
+ powerOff();
+ m_radioDev = s;
+
+ m_caps = readV4LCaps(m_radioDev);
+ notifyRadioDeviceChanged(m_radioDev);
+ notifyDescriptionChanged(m_caps.description);
+ notifyCapabilitiesChanged(m_caps);
+ setPower(p);
+ }
+ return true;
+}
+
+
+bool V4LRadio::setPlaybackMixer(const TQString &soundStreamClientID, const TQString &ch)
+{
+ bool change = m_PlaybackMixerID != soundStreamClientID || m_PlaybackMixerChannel != ch;
+ m_PlaybackMixerID = soundStreamClientID;
+ m_PlaybackMixerChannel = ch;
+
+
+ if (isPowerOn()) {
+ queryPlaybackVolume(m_SoundStreamID, m_defaultPlaybackVolume);
+ sendStopPlayback(m_SoundStreamID);
+ sendReleasePlayback(m_SoundStreamID);
+ }
+
+ ISoundStreamClient *playback_mixer = NULL;
+ searchMixers(&playback_mixer, NULL);
+ if (playback_mixer)
+ playback_mixer->preparePlayback(m_SoundStreamID, m_PlaybackMixerChannel, m_ActivePlayback, false);
+
+ if (isPowerOn()) {
+ sendStartPlayback(m_SoundStreamID);
+ sendPlaybackVolume(m_SoundStreamID, m_defaultPlaybackVolume);
+ if (m_ActivePlayback) {
+ SoundFormat sf;
+ sendStartCaptureWithFormat(m_SoundStreamID, sf, sf);
+ }
+ }
+
+ if (change)
+ notifyPlaybackMixerChanged(soundStreamClientID, ch);
+
+ return true;
+}
+
+
+bool V4LRadio::setCaptureMixer(const TQString &soundStreamClientID, const TQString &ch)
+{
+ bool change = m_PlaybackMixerID != soundStreamClientID || m_PlaybackMixerChannel != ch;
+ m_CaptureMixerID = soundStreamClientID;
+ m_CaptureMixerChannel = ch;
+
+ bool r = false;
+ SoundFormat sf;
+ queryIsCaptureRunning(m_SoundStreamID, r, sf);
+
+ float v = 0;
+ if (isPowerOn() && r) {
+ queryCaptureVolume(m_SoundStreamID, v);
+ sendStopCapture(m_SoundStreamID);
+ sendReleaseCapture(m_SoundStreamID);
+ }
+
+ ISoundStreamClient *capture_mixer = NULL;
+ searchMixers(NULL, &capture_mixer);
+ if (capture_mixer)
+ capture_mixer->prepareCapture(m_SoundStreamID, m_CaptureMixerChannel);
+
+ if (isPowerOn() && r) {
+ sendStartCaptureWithFormat(m_SoundStreamID, sf, sf);
+ sendCaptureVolume(m_SoundStreamID, v);
+ }
+
+ if (change)
+ notifyCaptureMixerChanged(soundStreamClientID, ch);
+
+ return true;
+}
+
+
+V4LCaps V4LRadio::getCapabilities(TQString dev) const
+{
+ if (dev.isNull()) {
+ return m_caps;
+ } else {
+ return readV4LCaps(dev);
+ }
+}
+
+
+bool V4LRadio::setActivePlayback(bool a)
+{
+ if (a == m_ActivePlayback)
+ return true;
+
+
+ if (isPowerOn()) {
+ queryPlaybackVolume(m_SoundStreamID, m_defaultPlaybackVolume);
+ sendStopPlayback(m_SoundStreamID);
+ sendReleasePlayback(m_SoundStreamID);
+ if (m_ActivePlayback) {
+ sendStopCapture(m_SoundStreamID);
+ }
+ }
+
+ m_ActivePlayback = a;
+
+ ISoundStreamClient *playback_mixer = NULL;
+ searchMixers(&playback_mixer, NULL);
+ if (playback_mixer)
+ playback_mixer->preparePlayback(m_SoundStreamID, m_PlaybackMixerChannel, m_ActivePlayback, false);
+
+ if (isPowerOn()) {
+ sendStartPlayback(m_SoundStreamID);
+ sendPlaybackVolume(m_SoundStreamID, m_defaultPlaybackVolume);
+ if (m_ActivePlayback) {
+ SoundFormat sf;
+ sendStartCaptureWithFormat(m_SoundStreamID, sf, sf);
+ }
+ }
+
+ // FIXME: restart playback/capture
+ notifyActivePlaybackChanged(m_ActivePlayback);
+
+ return true;
+}
+
+bool V4LRadio::setMuteOnPowerOff(bool a)
+{
+ if (a != m_MuteOnPowerOff) {
+ m_MuteOnPowerOff = a;
+ notifyMuteOnPowerOffChanged(m_MuteOnPowerOff);
+ }
+ return true;
+}
+
+bool V4LRadio::setVolumeZeroOnPowerOff(bool a)
+{
+ if (a != m_VolumeZeroOnPowerOff) {
+ m_VolumeZeroOnPowerOff = a;
+ notifyVolumeZeroOnPowerOffChanged(m_VolumeZeroOnPowerOff);
+ }
+ return true;
+}
+
+// PluginBase methods
+
+void V4LRadio::saveState (TDEConfig *config) const
+{
+ config->setGroup(TQString("v4lradio-") + name());
+
+ config->writeEntry("RadioDev", m_radioDev);
+
+ config->writeEntry("PlaybackMixerID", m_PlaybackMixerID);
+ config->writeEntry("PlaybackMixerChannel", m_PlaybackMixerChannel);
+ config->writeEntry("CaptureMixerID", m_CaptureMixerID);
+ config->writeEntry("CaptureMixerChannel", m_CaptureMixerChannel);
+
+ config->writeEntry("fMinOverride", m_minFrequency);
+ config->writeEntry("fMaxOverride", m_maxFrequency);
+ config->writeEntry("fLastDevMin", m_lastMinDevFrequency);
+ config->writeEntry("fLastDevMax", m_lastMaxDevFrequency);
+
+ config->writeEntry("defaultPlaybackVolume", m_defaultPlaybackVolume);
+
+ config->writeEntry("signalMinQuality", m_minQuality);
+
+ config->writeEntry("scanStep", m_scanStep);
+
+ config->writeEntry("Frequency", m_currentStation.frequency());
+ config->writeEntry("Treble", m_treble);
+ config->writeEntry("Bass", m_bass);
+ config->writeEntry("Balance", m_balance);
+ config->writeEntry("DeviceVolume", m_deviceVolume);
+
+ config->writeEntry("PowerOn", isPowerOn());
+ config->writeEntry("UseOldV4L2Calls", m_useOldV4L2Calls);
+
+ config->writeEntry("ActivePlayback", m_ActivePlayback);
+ config->writeEntry("MuteOnPowerOff", m_MuteOnPowerOff);
+ config->writeEntry("VolumeZeroOnPowerOff", m_VolumeZeroOnPowerOff);
+}
+
+
+void V4LRadio::restoreState (TDEConfig *config)
+{
+ BlockProfiler p("V4LRadio::restoreState");
+
+ config->setGroup(TQString("v4lradio-") + name());
+
+ TQString base_devname = "/dev/radio";
+
+ TQStringList testlist (base_devname );
+ for (int i = 0; i < 9; ++i)
+ testlist.append(base_devname + TQString::number(i));
+
+ TQString found_devname(TQString::null);
+ for (TQValueListConstIterator<TQString> it = testlist.begin(); it != testlist.end(); ++it) {
+ TQFile f(*it);
+ if (f.exists()) {
+ TQFileInfo info(f);
+ if (info.isReadable() && info.isWritable()) {
+ found_devname = *it;
+ break;
+ }
+ else {
+ if (found_devname.isNull())
+ found_devname = *it;
+ logWarning(i18n("Device %1 does exist but is not readable/writable. Please check device permissions.").arg(*it));
+ }
+ }
+ }
+
+ TQString default_devname = found_devname.isNull() ? base_devname : found_devname;
+
+ TQString devname = config->readEntry ("RadioDev", default_devname);
+
+ if (found_devname.isNull() && devname == default_devname) {
+ logError(i18n("Could not find an accessible v4l(2) radio device."));
+ }
+
+ setRadioDevice(devname);
+
+ TQString PlaybackMixerID = config->readEntry ("PlaybackMixerID", TQString());
+ TQString PlaybackMixerChannel = config->readEntry ("PlaybackMixerChannel", "Line");
+
+ TQString CaptureMixerID = config->readEntry ("CaptureMixerID", TQString());
+ TQString CaptureMixerChannel = config->readEntry ("CaptureMixerChannel", "Line");
+
+ m_ActivePlayback = config->readBoolEntry("ActivePlayback", false);
+ m_MuteOnPowerOff = config->readBoolEntry("MuteOnPowerOff", false);
+ m_VolumeZeroOnPowerOff = config->readBoolEntry("VolumeZeroOnPowerOff", false);
+
+ m_lastMinDevFrequency = config->readDoubleNumEntry ("fLastDevMin", 65.0);
+ m_lastMaxDevFrequency = config->readDoubleNumEntry ("fLastDevMax", 108.0);
+ m_minFrequency = config->readDoubleNumEntry ("fMinOverride", m_lastMinDevFrequency);
+ m_maxFrequency = config->readDoubleNumEntry ("fMaxOverride", m_lastMaxDevFrequency);
+
+ m_minQuality = config->readDoubleNumEntry ("signalMinQuality", 0.75);
+ m_scanStep = config->readDoubleNumEntry ("scanStep", 0.05);
+ m_defaultPlaybackVolume = config->readDoubleNumEntry ("defaultPlaybackVolume", 0.5);
+
+ setPlaybackMixer(PlaybackMixerID, PlaybackMixerChannel);
+ setCaptureMixer (CaptureMixerID, CaptureMixerChannel);
+ notifyDeviceMinMaxFrequencyChanged(m_lastMinDevFrequency, m_lastMaxDevFrequency);
+ notifyMinMaxFrequencyChanged(m_minFrequency, m_maxFrequency);
+ notifySignalMinQualityChanged(m_SoundStreamID, m_minQuality);
+ notifyScanStepChanged(m_scanStep);
+ notifyActivePlaybackChanged(m_ActivePlayback);
+ notifyMuteOnPowerOffChanged(m_MuteOnPowerOff);
+ notifyVolumeZeroOnPowerOffChanged(m_VolumeZeroOnPowerOff);
+
+ BlockProfiler p2("V4LRadio::restoreState2");
+
+ setFrequency(config->readDoubleNumEntry("Frequency", 88));
+ m_restorePowerOn = config->readBoolEntry ("PowerOn", false);
+
+ BlockProfiler p3("V4LRadio::restoreState3");
+
+ setTreble (m_SoundStreamID, config->readDoubleNumEntry("Treble", 0.5));
+ setBass (m_SoundStreamID, config->readDoubleNumEntry("Bass", 0.5));
+ setBalance (m_SoundStreamID, config->readDoubleNumEntry("Balance", 0.0));
+ setDeviceVolume( config->readDoubleNumEntry("DeviceVolume", 0.9));
+
+ m_useOldV4L2Calls = config->readBoolEntry("UseOldV4L2Calls", true);
+
+ if (isPowerOff())
+ notifyPlaybackVolumeChanged(m_SoundStreamID, m_defaultPlaybackVolume);
+}
+
+void V4LRadio::startPlugin()
+{
+ PluginBase::startPlugin();
+ setPower(m_restorePowerOn);
+}
+
+ConfigPageInfo V4LRadio::createConfigurationPage()
+{
+ V4LRadioConfiguration *v4lconf = new V4LRadioConfiguration(NULL, m_SoundStreamID);
+ connectI(v4lconf);
+ return ConfigPageInfo (v4lconf,
+ i18n("V4L Radio"),
+ i18n("V4L Radio Options"),
+ "applications-utilities");
+}
+
+
+AboutPageInfo V4LRadio::createAboutPage()
+{
+ TDEAboutData aboutData("tderadio",
+ NULL,
+ NULL,
+ I18N_NOOP("V4L/V4L2 Plugin for TDERadio."
+ "<P>"
+ "Provides Support for V4L/V4L2 based Radio Cards"
+ "<P>"),
+ 0,
+ //TDEAboutData::License_GPL,
+ "(c) 2002-2005 Martin Witte, Klas Kalass",
+ 0,
+ "http://sourceforge.net/projects/tderadio",
+ 0);
+ aboutData.addAuthor("Martin Witte", "", "witte@kawo1.rwth-aachen.de");
+ aboutData.addAuthor("Klas Kalass", "", "klas.kalass@gmx.de");
+
+ return AboutPageInfo(
+ new TDERadioAboutWidget(aboutData, TDERadioAboutWidget::AbtTabbed),
+ i18n("V4L/V4L2"),
+ i18n("V4L/V4L2 Plugin"),
+ "applications-utilities"
+ );
+}
+
+////////////////////////////////////////
+// anything else
+
+void V4LRadio::radio_init()
+{
+ if (isSeekRunning())
+ stopSeek();
+
+ m_caps = readV4LCaps(m_radioDev);
+ notifyCapabilitiesChanged(m_caps);
+ notifyDescriptionChanged(m_caps.description);
+
+/* m_mixer_fd = open(m_mixerDev, O_RDONLY);
+ if (m_mixer_fd < 0) {
+ radio_done();
+
+ logError("V4LRadio::radio_init: " +
+ i18n("Cannot open mixer device %1").arg(m_mixerDev));
+ return;
+ }
+*/
+ m_radio_fd = open(m_radioDev.ascii(), O_RDONLY);
+ if (m_radio_fd < 0) {
+ radio_done();
+
+ logError("V4LRadio::radio_init: " +
+ i18n("Cannot open radio device %1").arg(m_radioDev));
+ return;
+ }
+
+ readTunerInfo();
+ writeAudioInfo(); // set tuner-audio config as used last time
+ readAudioInfo(); // reread tuner-audio and read-only flags (e.g. stereo)
+
+ // restore frequency
+ float old = getFrequency();
+ m_currentStation.setFrequency(0);
+ setFrequency(old);
+
+ // read volume level from mixer
+ // FIXME: do we still need this
+/* float v = 0;
+ getVolume(m_SoundStreamID, v)
+ setVolume (m_SoundStreamID, v);*/
+}
+
+
+void V4LRadio::radio_done()
+{
+ if (isSeekRunning())
+ stopSeek();
+
+ if (m_radio_fd >= 0) close (m_radio_fd);
+// if (m_mixer_fd >= 0) close (m_mixer_fd);
+
+ m_radio_fd = -1;
+// m_mixer_fd = -1;
+}
+
+
+
+
+
+#define CAPS_NAME_LEN 127
+V4LCaps V4LRadio::readV4LCaps(const TQString &device) const
+{
+ char buffer[CAPS_NAME_LEN+1];
+ int r;
+ int fd;
+
+ V4LCaps c;
+ c.description = device;
+
+ fd = open(device.ascii(), O_RDONLY);
+
+ if (fd < 0) {
+ logError("V4LRadio::readV4LCaps: " +
+ i18n("cannot open %1").arg(device));
+ return c;
+ }
+
+ video_capability caps;
+ r = ioctl(fd, VIDIOCGCAP, &caps);
+ if (r == 0) {
+ c.version = 1;
+
+ size_t l = sizeof(caps.name);
+ l = l < CAPS_NAME_LEN ? l : CAPS_NAME_LEN;
+ memcpy(buffer, caps.name, l);
+ buffer[l] = 0;
+ c.description = buffer;
+
+ c.hasMute = false;
+ c.unsetVolume();
+ c.unsetTreble();
+ c.unsetBass();
+ c.unsetBalance();
+
+ video_audio audiocaps;
+ if (0 == ioctl(fd, VIDIOCGAUDIO, &audiocaps)) {
+ logDebug("V4LRadio::readV4LCaps: " +
+ i18n("audio caps = %1").arg(TQString().setNum(audiocaps.flags)));
+ if ((audiocaps.flags & VIDEO_AUDIO_MUTABLE) != 0)
+ c.hasMute = true;
+ if ((audiocaps.flags & VIDEO_AUDIO_VOLUME) != 0)
+ c.setVolume (0, 65535);
+ if ((audiocaps.flags & VIDEO_AUDIO_TREBLE) != 0)
+ c.setTreble (0, 65535);
+ if ((audiocaps.flags & VIDEO_AUDIO_BASS) != 0)
+ c.setBass (0, 65535);
+ // at least my driver has support for balance, but the bit is not set ...
+ c.setBalance(0, 65535);
+ }
+ } else {
+ logError("V4LRadio::readV4LCaps: " +
+ i18n("error reading V4L1 caps"));
+ }
+
+#ifdef HAVE_V4L2
+ v4l2_capability caps2;
+ r = ioctl(fd, VIDIOC_QUERYCAP, &caps2);
+ if (r == 0) {
+ c.version = 2;
+
+ logDebug(i18n("V4L2 - Version: %1").arg(TQString().sprintf("%08X", caps2.version)));
+
+ size_t l = sizeof(caps.name);
+ l = l < CAPS_NAME_LEN ? l : CAPS_NAME_LEN;
+ memcpy(buffer, caps.name, l);
+ buffer[l] = 0;
+ // c.description = buffer;
+
+ v4l2_queryctrl ctrl;
+
+ c.hasMute = false;
+ c.unsetVolume();
+ c.unsetTreble();
+ c.unsetBass();
+ c.unsetBalance();
+
+ ctrl.id = V4L2_CID_AUDIO_MUTE;
+ if (0 == ioctl(fd, VIDIOC_QUERYCTRL, &ctrl))
+ c.hasMute = !(ctrl.flags & V4L2_CTRL_FLAG_DISABLED);
+ else
+ logError(i18n("V4L2: Querying mute control failed"));
+
+ ctrl.id = V4L2_CID_AUDIO_VOLUME;
+ if (0 == ioctl(fd, VIDIOC_QUERYCTRL, &ctrl)) {
+ if (!(ctrl.flags & V4L2_CTRL_FLAG_DISABLED))
+ c.setVolume(ctrl.minimum, ctrl.maximum);
+ } else {
+ logError(i18n("V4L2: Querying volume control failed"));
+ }
+
+ ctrl.id = V4L2_CID_AUDIO_TREBLE;
+ if (0 == ioctl(fd, VIDIOC_QUERYCTRL, &ctrl)) {
+ if (!(ctrl.flags & V4L2_CTRL_FLAG_DISABLED))
+ c.setTreble(ctrl.minimum, ctrl.maximum);
+ } else {
+ logError(i18n("V4L2: Querying treble control failed"));
+ }
+
+ ctrl.id = V4L2_CID_AUDIO_BASS;
+ if (0 == ioctl(fd, VIDIOC_QUERYCTRL, &ctrl)) {
+ if (!(ctrl.flags & V4L2_CTRL_FLAG_DISABLED))
+ c.setBass(ctrl.minimum, c.maxBass = ctrl.maximum);
+ } else {
+ logError(i18n("V4L2: Querying bass control failed"));
+ }
+
+ ctrl.id = V4L2_CID_AUDIO_BALANCE;
+ if (0 == ioctl(fd, VIDIOC_QUERYCTRL, &ctrl)) {
+ if (!(ctrl.flags & V4L2_CTRL_FLAG_DISABLED))
+ c.setBalance(ctrl.minimum, ctrl.maximum);
+ } else {
+ logError(i18n("V4L2: Querying balance control failed"));
+ }
+
+ } else {
+ logWarning(i18n("V4LRadio::readV4LCaps: Reading V4L2 caps failed"));
+ }
+#endif
+ if (c.version > 0) {
+ logInfo(i18n("V4L %1 detected").arg(c.version));
+ } else {
+ logError(i18n("V4L not detected"));
+ }
+
+ logInfo(c.hasMute ? i18n("Radio is mutable") : i18n("Radio is not mutable"));
+ logInfo(c.hasVolume ? i18n("Radio has Volume Control") : i18n("Radio has no Volume Control"));
+ logInfo(c.hasBass ? i18n("Radio has Bass Control") : i18n("Radio has no Bass Control"));
+ logInfo(c.hasTreble ? i18n("Radio has Treble Control") : i18n("Radio has no Treble Control"));
+
+ close(fd);
+ return c;
+}
+
+
+bool V4LRadio::readTunerInfo() const
+{
+ if (m_blockReadTuner) return true;
+
+ float oldq = m_signalQuality;
+ float oldminf = m_tunercache.minF;
+ float oldmaxf = m_tunercache.maxF;
+
+ if (!m_tunercache.valid) {
+ m_tunercache.minF = m_lastMinDevFrequency;
+ m_tunercache.maxF = m_lastMaxDevFrequency;
+ m_tunercache.deltaF = 1.0/16.0;
+ m_tunercache.valid = true;
+ }
+
+ int r = 0;
+ if (isPowerOn()) {
+
+ // v4l1
+ if (m_caps.version == 1) {
+
+ r = ioctl(m_radio_fd, VIDIOCGTUNER, m_tuner);
+
+ if (r == 0) {
+ if ((m_tuner->flags & VIDEO_TUNER_LOW) != 0)
+ m_tunercache.deltaF = 1.0 / 16000.0;
+ m_tunercache.minF = float(m_tuner->rangelow) * m_tunercache.deltaF;
+ m_tunercache.maxF = float(m_tuner->rangehigh) * m_tunercache.deltaF;
+ m_tunercache.valid = true;
+ m_signalQuality = float(m_tuner->signal) / 32767.0;
+
+ }
+ }
+#ifdef HAVE_V4L2
+ // v4l2
+ else if (m_caps.version == 2) {
+
+ r = ioctl(m_radio_fd, VIDIOC_G_TUNER, m_tuner2);
+
+ if (r == 0) {
+ if ((m_tuner2->capability & V4L2_TUNER_CAP_LOW) != 0)
+ m_tunercache.deltaF = 1.0 / 16000.0;
+ m_tunercache.minF = float(m_tuner2->rangelow) * m_tunercache.deltaF;
+ m_tunercache.maxF = float(m_tuner2->rangehigh) * m_tunercache.deltaF;
+ m_tunercache.valid = true;
+ m_signalQuality = float(m_tuner2->signal) / 32767.0;
+ }
+ }
+#endif
+ else {
+ logError("V4LRadio::readTunerInfo: " +
+ i18n("don't known how to handle V4L-version %1")
+ .arg(TQString().setNum(m_caps.version)));
+ }
+
+ if (r != 0) {
+ m_signalQuality = 0;
+ logError("V4LRadio::readTunerInfo: " +
+ i18n("cannot get tuner info (error %1)").arg(TQString().setNum(r)));
+ }
+ } else {
+ m_signalQuality = 0;
+ }
+
+ // prevent loops, if noticeXYZ-method is reading my state
+ m_blockReadTuner = true;
+
+ if (oldminf != m_tunercache.minF || oldmaxf != m_tunercache.maxF)
+ notifyDeviceMinMaxFrequencyChanged(m_tunercache.minF, m_tunercache.maxF);
+ m_lastMinDevFrequency = m_tunercache.minF;
+ m_lastMaxDevFrequency = m_tunercache.maxF;
+
+ if ( ! m_minFrequency && (oldminf != m_tunercache.minF)
+ || ! m_maxFrequency && (oldmaxf != m_tunercache.maxF))
+ notifyMinMaxFrequencyChanged(getMinFrequency(), getMaxFrequency());
+
+
+ if (m_signalQuality != oldq)
+ notifySignalQualityChanged(m_SoundStreamID, m_signalQuality);
+ if ( (m_signalQuality >= m_minQuality) != (oldq >= m_minQuality))
+ notifySignalQualityBoolChanged(m_SoundStreamID, m_signalQuality > m_minQuality);
+
+ m_blockReadTuner = false;
+
+ return true;
+}
+
+
+
+#define V4L2_S_CTRL(what,val) \
+ { ctl.value = (val); \
+ ctl.id = (what); \
+ /* Problem: Current V4L2 development has changed the IOCTL-IDs for VIDIOC_S_CTRL */ \
+ /* => we must du "try and error" to figure out what version we should use */ \
+ r = ioctl (m_radio_fd, m_useOldV4L2Calls ? VIDIOC_S_CTRL_OLD : VIDIOC_S_CTRL, &ctl); \
+ /* in case this did not work, try the other version of the call */ \
+ if (r) { \
+ r = ioctl (m_radio_fd, !m_useOldV4L2Calls ? VIDIOC_S_CTRL_OLD : VIDIOC_S_CTRL, &ctl); \
+ if (!r) m_useOldV4L2Calls = !m_useOldV4L2Calls; \
+ } \
+ x = x ? x : r; \
+ if (r) \
+ logError(i18n("error setting %1: %2").arg(#what).arg(TQString().setNum(r))); \
+ }
+
+#define V4L2_G_CTRL(what) \
+ { ctl.id = (what); \
+ r = ioctl (m_radio_fd, VIDIOC_G_CTRL, &ctl); \
+ x = x ? x : r; \
+ if (r) \
+ logError(i18n("error reading %1: %2").arg(#what).arg(TQString().setNum(r))); \
+ }
+
+
+bool V4LRadio::updateAudioInfo(bool write) const
+{
+ if (m_blockReadAudio && !write)
+ return true;
+
+ bool oldStereo = m_stereo;
+ bool oldMute = m_muted;
+ int iOldDeviceVolume = m_caps.intGetVolume (m_deviceVolume);
+ int iOldTreble = m_caps.intGetTreble (m_treble);
+ int iOldBass = m_caps.intGetBass (m_bass);
+ int iOldBalance = m_caps.intGetBalance(m_balance);
+
+ if (isPowerOn()) {
+ int r = 0;
+ if (m_caps.version == 1) {
+ m_audio->audio = 0;
+ if (m_muted) m_audio->flags |= VIDEO_AUDIO_MUTE;
+ else m_audio->flags &= ~VIDEO_AUDIO_MUTE;
+
+ m_audio->volume = m_caps.intGetVolume (m_deviceVolume);
+ m_audio->treble = m_caps.intGetTreble (m_treble);
+ m_audio->bass = m_caps.intGetBass (m_bass);
+ m_audio->balance = m_caps.intGetBalance(m_balance);
+
+ r = ioctl(m_radio_fd, write ? VIDIOCSAUDIO : VIDIOCGAUDIO, m_audio);
+
+ m_stereo = (r == 0) && ((m_audio->mode & VIDEO_SOUND_STEREO) != 0);
+
+ m_muted = m_caps.hasMute &&
+ ((r != 0) || ((m_audio->flags & VIDEO_AUDIO_MUTE) != 0));
+
+ /* Some drivers seem to set volumes to zero if they are muted.
+ Thus we do not reload them if radio is muted */
+ if (!m_muted && !write) {
+ m_deviceVolume = m_caps.hasVolume && !r ? m_caps.floatGetVolume (m_audio->volume) : 1;
+ m_treble = m_caps.hasTreble && !r ? m_caps.floatGetTreble (m_audio->treble) : 1;
+ m_bass = m_caps.hasBass && !r ? m_caps.floatGetBass (m_audio->bass) : 1;
+ m_balance = m_caps.hasBalance && !r ? m_caps.floatGetBalance(m_audio->balance) : 0;
+ }
+ }
+#ifdef HAVE_V4L2
+ else if (m_caps.version == 2) {
+ v4l2_control ctl;
+ int x = 0; // x stores first ioctl error
+ if (write) {
+ if (m_caps.hasMute)
+ V4L2_S_CTRL(V4L2_CID_AUDIO_MUTE, m_muted);
+ if (m_caps.hasTreble)
+ V4L2_S_CTRL(V4L2_CID_AUDIO_TREBLE, m_caps.intGetTreble(m_treble));
+ if (m_caps.hasBass)
+ V4L2_S_CTRL(V4L2_CID_AUDIO_BASS, m_caps.intGetBass(m_bass));
+ if (m_caps.hasBalance)
+ V4L2_S_CTRL(V4L2_CID_AUDIO_BALANCE, m_caps.intGetBalance(m_balance));
+ if (m_caps.hasVolume)
+ V4L2_S_CTRL(V4L2_CID_AUDIO_VOLUME, m_caps.intGetVolume(m_deviceVolume));
+ } else {
+ if (m_caps.hasMute)
+ V4L2_G_CTRL(V4L2_CID_AUDIO_MUTE);
+ m_muted = m_caps.hasMute && ((r != 0) || ctl.value);
+
+ /* Some drivers seem to set volumes to zero if they are muted.
+ Thus we do not reload them if radio is muted */
+ if (!m_muted) {
+ if (m_caps.hasVolume)
+ V4L2_G_CTRL(V4L2_CID_AUDIO_VOLUME);
+ m_deviceVolume = m_caps.hasVolume && !r ? m_caps.floatGetVolume (ctl.value) : 1;
+ if (m_caps.hasTreble)
+ V4L2_G_CTRL(V4L2_CID_AUDIO_TREBLE);
+ m_treble = m_caps.hasTreble && !r ? m_caps.floatGetTreble (ctl.value) : 1;
+ if (m_caps.hasBass)
+ V4L2_G_CTRL(V4L2_CID_AUDIO_BASS);
+ m_bass = m_caps.hasBass && !r ? m_caps.floatGetBass (ctl.value) : 1;
+ if (m_caps.hasBalance)
+ V4L2_G_CTRL(V4L2_CID_AUDIO_BALANCE);
+ m_balance = m_caps.hasBalance&& !r ? m_caps.floatGetBalance(ctl.value) : 0;
+ }
+
+ r = ioctl (m_radio_fd, VIDIOC_G_TUNER, m_tuner2);
+ m_stereo = (r == 0) && ((m_tuner2->rxsubchans & V4L2_TUNER_SUB_STEREO) != 0);
+ x = x ? x : r;
+ }
+ r = x; // store first error back to r, used below for error message
+ }
+#endif
+ else {
+ logError("V4LRadio::updateAudioInfo: " +
+ i18n("don't known how to handle V4L-version %1")
+ .arg(TQString().setNum(m_caps.version)));
+ }
+
+ if (r) {
+ logError("V4LRadio::updateAudioInfo: " +
+ i18n("error updating radio audio info (%1): %2")
+ .arg(write ? i18n("write") : i18n("read"))
+ .arg(TQString().setNum(r)));
+ return false;
+ }
+ }
+
+ // prevent loops, if noticeXYZ-method is reading my state
+ bool oldBlock = m_blockReadAudio;
+ m_blockReadAudio = true;
+
+ // send notifications
+
+ if (oldStereo != m_stereo)
+ notifyStereoChanged(m_SoundStreamID, m_stereo);
+ if (oldMute != m_muted)
+ notifyMuted(m_SoundStreamID, m_muted);
+ if (iOldDeviceVolume != m_caps.intGetVolume(m_deviceVolume))
+ notifyDeviceVolumeChanged(m_deviceVolume);
+ if (iOldTreble != m_caps.intGetTreble(m_treble))
+ notifyTrebleChanged(m_SoundStreamID, m_treble);
+ if (iOldBass != m_caps.intGetBass(m_bass))
+ notifyBassChanged(m_SoundStreamID, m_bass);
+ if (iOldBalance != m_caps.intGetBalance(m_balance))
+ notifyBalanceChanged(m_SoundStreamID, m_balance);
+
+ m_blockReadAudio = oldBlock;
+
+ return isPowerOn();
+}
+
+
+
+
+void V4LRadio::poll()
+{
+ readTunerInfo();
+ readAudioInfo();
+}
+
+
+bool V4LRadio::setPlaybackVolume(SoundStreamID id, float volume)
+{
+ if (isPowerOff() && id == m_SoundStreamID) {
+ m_defaultPlaybackVolume = min(max(volume, 0.0), 1.0);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool V4LRadio::getPlaybackVolume(SoundStreamID id, float &volume) const
+{
+ if (isPowerOff() && id == m_SoundStreamID) {
+ volume = m_defaultPlaybackVolume;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+
+bool V4LRadio::getSoundStreamDescription(SoundStreamID id, TQString &descr) const
+{
+ if (id == m_SoundStreamID) {
+ descr = name() + " - " + m_currentStation.name();
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+bool V4LRadio::getSoundStreamRadioStation(SoundStreamID id, const RadioStation *&rs) const
+{
+ if (id == m_SoundStreamID) {
+ rs = &m_currentStation;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+bool V4LRadio::enumerateSoundStreams(TQMap<TQString, SoundStreamID> &list) const
+{
+ if (m_SoundStreamID.isValid()) {
+ TQString tmp = TQString();
+ getSoundStreamDescription(m_SoundStreamID, tmp);
+ list[tmp] = m_SoundStreamID;
+ return true;
+ }
+ return false;
+}
+
+
+// bool V4LRadio::stopCapture(SoundStreamID id)
+// {
+// if (id.isValid() && id == m_SoundStreamID && m_ActivePlayback) {
+// sendStopPlayback(id);
+// return true;
+// }
+// return false;
+// }
+
+#include "v4lradio.moc"
diff --git a/plugins/v4lradio/v4lradio.h b/plugins/v4lradio/v4lradio.h
new file mode 100644
index 0000000..c8d7a58
--- /dev/null
+++ b/plugins/v4lradio/v4lradio.h
@@ -0,0 +1,266 @@
+/***************************************************************************
+ v4lradio.h - description
+ -------------------
+ begin : Jan 2002
+ copyright : (C) 2002-2005 Ernst Martin Witte, Klas Kalass
+ email : witte@kawo1.rwth-aachen.de, klas@kde.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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_V4LRADIO_H
+#define KRADIO_V4LRADIO_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <tqtimer.h>
+
+#include "../../src/include/radiodevice_interfaces.h"
+#include "../../src/include/plugins.h"
+#include "../../src/include/frequencyradiostation.h"
+#include "../../src/include/frequencyseekhelper.h"
+#include "../../src/include/soundstreamclient_interfaces.h"
+#include "v4lcfg_interfaces.h"
+
+
+struct video_tuner;
+struct video_audio;
+#ifdef HAVE_V4L2
+struct v4l2_tuner;
+#endif
+
+class V4LRadio : public TQObject,
+ public PluginBase,
+ public IRadioDevice,
+// public IRadioSound,
+ public ISeekRadio,
+ public IFrequencyRadio,
+ public ISoundStreamClient,
+ public IV4LCfg
+{
+Q_OBJECT
+
+public:
+ V4LRadio (const TQString &name);
+ virtual ~V4LRadio ();
+
+ virtual bool connectI (Interface *);
+ virtual bool disconnectI (Interface *);
+
+ virtual TQString pluginClassName() const { return "V4LRadio"; }
+
+ virtual const TQString &name() const { return PluginBase::name(); }
+ virtual TQString &name() { return PluginBase::name(); }
+
+ // PluginBase
+
+public:
+ virtual void saveState (TDEConfig *) const;
+ virtual void restoreState (TDEConfig *);
+ virtual void startPlugin();
+
+ virtual ConfigPageInfo createConfigurationPage();
+ virtual AboutPageInfo createAboutPage();
+
+ // IRadioDevice methods
+
+RECEIVERS:
+ virtual bool setPower(bool p);
+ virtual bool powerOn();
+ virtual bool powerOff();
+ virtual bool activateStation(const RadioStation &rs);
+
+ANSWERS:
+ virtual bool isPowerOn() const;
+ virtual bool isPowerOff() const;
+ virtual SoundStreamID getSoundStreamID() const;
+ virtual const RadioStation & getCurrentStation() const;
+ virtual const TQString & getDescription() const;
+ virtual SoundStreamID getCurrentSoundStreamID() const;
+
+
+ // ISeekRadio
+
+RECEIVERS:
+ virtual bool toBeginning();
+ virtual bool toEnd();
+ virtual bool startSeek (bool up);
+ virtual bool startSeekUp();
+ virtual bool startSeekDown();
+ virtual bool stopSeek();
+
+ANSWERS:
+ virtual bool isSeekRunning() const;
+ virtual bool isSeekUpRunning() const;
+ virtual bool isSeekDownRunning() const;
+ virtual float getProgress () const;
+
+
+ // IFrequencyRadio
+
+RECEIVERS:
+ virtual bool setFrequency(float f);
+ virtual bool setMinFrequency(float mf);
+ virtual bool setMaxFrequency(float mf);
+ virtual bool setScanStep(float s);
+
+ANSWERS:
+ virtual float getFrequency() const;
+ virtual float getMinFrequency() const;
+ virtual float getMinDeviceFrequency() const;
+ virtual float getMaxFrequency() const;
+ virtual float getMaxDeviceFrequency() const;
+ virtual float getScanStep() const;
+
+
+ // ISoundStreamClient: mixer functions
+
+
+RECEIVERS:
+ void noticeConnectedI (ISoundStreamServer *s, bool pointer_valid);
+ void noticeConnectedSoundClient(ISoundStreamClient::thisInterface *i, bool pointer_valid);
+
+ bool setTreble (SoundStreamID, float v);
+ bool setBass (SoundStreamID, float v);
+ bool setBalance (SoundStreamID, float v);
+ bool mute (SoundStreamID, bool mute = true);
+ bool unmute (SoundStreamID, bool unmute = true);
+ bool setSignalMinQuality(SoundStreamID, float q);
+ bool setStereo(SoundStreamID, bool s);
+
+ bool getTreble(SoundStreamID, float &v) const;
+ bool getBass (SoundStreamID, float &v) const;
+ bool getBalance (SoundStreamID, float &b) const;
+ bool getSignalQuality(SoundStreamID, float &q) const;
+ bool getSignalMinQuality(SoundStreamID, float &q) const;
+ bool hasGoodQuality(SoundStreamID, bool &) const;
+ bool isStereo(SoundStreamID, bool &s) const;
+ bool isMuted(SoundStreamID, bool &m) const;
+
+ // ISoundStreamClient: generic stream handling (broadcasts)
+
+RECEIVERS:
+
+ bool getSoundStreamDescription(SoundStreamID id, TQString &descr) const;
+ bool getSoundStreamRadioStation(SoundStreamID id, const RadioStation *&rs) const;
+ bool enumerateSoundStreams(TQMap<TQString, SoundStreamID> &list) const;
+
+// bool stopCapture(SoundStreamID id); // if active playback also call stopPlayback
+
+
+ // IV4LCfg
+RECEIVERS:
+ bool setRadioDevice (const TQString &s);
+ bool setPlaybackMixer(const TQString &soundStreamClientID, const TQString &ch);
+ bool setCaptureMixer (const TQString &soundStreamClientID, const TQString &ch);
+ bool setDeviceVolume (float v);
+ bool setActivePlayback(bool a);
+ bool setMuteOnPowerOff(bool a);
+ bool setVolumeZeroOnPowerOff(bool a);
+
+ // if the radio is powered off, we will handle the volume by changing m_defaultPlaybackVolume
+ bool setPlaybackVolume(SoundStreamID id, float volume);
+ bool getPlaybackVolume(SoundStreamID id, float &volume) const;
+
+ANSWERS:
+ const TQString &getRadioDevice () const { return m_radioDev; }
+ const TQString &getPlaybackMixerID () const { return m_PlaybackMixerID; }
+ const TQString &getCaptureMixerID () const { return m_CaptureMixerID; }
+ const TQString &getPlaybackMixerChannel() const { return m_PlaybackMixerChannel; }
+ const TQString &getCaptureMixerChannel () const { return m_CaptureMixerChannel; }
+ float getDeviceVolume () const;
+ V4LCaps getCapabilities(TQString dev = TQString()) const;
+
+ bool getActivePlayback() const { return m_ActivePlayback; }
+ bool getMuteOnPowerOff() const { return m_MuteOnPowerOff; }
+ bool getVolumeZeroOnPowerOff() const { return m_VolumeZeroOnPowerOff; }
+
+ // anything else
+
+protected slots:
+ void poll();
+
+protected:
+ V4LCaps readV4LCaps(const TQString &device) const;
+ void radio_init();
+ void radio_done();
+
+ bool readTunerInfo() const;
+ bool updateAudioInfo(bool write) const;
+ bool readAudioInfo() const { return updateAudioInfo(false); }
+ bool writeAudioInfo() const { return updateAudioInfo(true); }
+
+ void searchMixers(ISoundStreamClient **playback_mixer, ISoundStreamClient **capture_mixer);
+
+protected:
+
+ FrequencyRadioStation m_currentStation;
+ mutable float m_treble;
+ mutable float m_bass;
+ mutable float m_balance;
+ mutable float m_deviceVolume;
+ mutable bool m_muted;
+ mutable float m_signalQuality;
+ mutable bool m_stereo;
+
+ float m_minQuality;
+ float m_minFrequency;
+ float m_maxFrequency;
+ mutable float m_lastMinDevFrequency;
+ mutable float m_lastMaxDevFrequency;
+
+ float m_defaultPlaybackVolume;
+
+ FrequencySeekHelper *m_seekHelper;
+ float m_scanStep;
+
+ V4LCaps m_caps;
+ TQString m_radioDev;
+ int m_radio_fd;
+
+ mutable bool m_useOldV4L2Calls;
+
+
+ mutable struct video_audio *m_audio;
+ mutable struct video_tuner *m_tuner;
+#ifdef HAVE_V4L2
+ mutable struct v4l2_tuner *m_tuner2;
+#endif
+
+ TQTimer m_pollTimer;
+
+ struct TunerCache {
+ bool valid;
+ float deltaF;
+ float minF, maxF;
+ TunerCache() { valid = false; deltaF = minF = maxF = 0; }
+ };
+ mutable struct TunerCache m_tunercache;
+
+
+ mutable bool m_blockReadTuner,
+ m_blockReadAudio;
+
+ SoundStreamID m_SoundStreamID;
+ TQString m_PlaybackMixerID;
+ TQString m_CaptureMixerID;
+ TQString m_PlaybackMixerChannel;
+ TQString m_CaptureMixerChannel;
+
+ bool m_ActivePlayback;
+ bool m_MuteOnPowerOff;
+ bool m_VolumeZeroOnPowerOff;
+
+ bool m_restorePowerOn;
+};
+
+#endif