summaryrefslogtreecommitdiffstats
path: root/plugins/timeshifter
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/timeshifter')
-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
20 files changed, 1409 insertions, 0 deletions
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