diff options
author | Michele Calgaro <[email protected]> | 2022-05-30 19:40:31 +0900 |
---|---|---|
committer | Michele Calgaro <[email protected]> | 2022-05-31 01:17:58 +0900 |
commit | d95a4fea540b371fa86493d069fdbd54f33c5b40 (patch) | |
tree | 079b038ab559439eb7ded40a07bd79fd92926b3b /plugins/streaming | |
parent | e54890e0480e5adee69f5220a7c6dd072bbd75ea (diff) | |
download | tderadio-d95a4fea540b371fa86493d069fdbd54f33c5b40.tar.gz tderadio-d95a4fea540b371fa86493d069fdbd54f33c5b40.zip |
Standardize folder structure.
Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'plugins/streaming')
19 files changed, 3126 insertions, 0 deletions
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 Binary files differnew file mode 100644 index 0000000..320a633 --- /dev/null +++ b/plugins/streaming/icons/hi16-action-tderadio_streaming.png diff --git a/plugins/streaming/icons/hi22-action-tderadio_streaming.png b/plugins/streaming/icons/hi22-action-tderadio_streaming.png Binary files differnew file mode 100644 index 0000000..e582ea8 --- /dev/null +++ b/plugins/streaming/icons/hi22-action-tderadio_streaming.png diff --git a/plugins/streaming/icons/hi32-action-tderadio_streaming.png b/plugins/streaming/icons/hi32-action-tderadio_streaming.png Binary files differnew file mode 100644 index 0000000..0767a6a --- /dev/null +++ b/plugins/streaming/icons/hi32-action-tderadio_streaming.png diff --git a/plugins/streaming/icons/hi48-action-tderadio_streaming.png b/plugins/streaming/icons/hi48-action-tderadio_streaming.png Binary files differnew file mode 100644 index 0000000..6ace14e --- /dev/null +++ b/plugins/streaming/icons/hi48-action-tderadio_streaming.png diff --git a/plugins/streaming/icons/hi64-action-tderadio_streaming.png b/plugins/streaming/icons/hi64-action-tderadio_streaming.png Binary files differnew file mode 100644 index 0000000..a9fc990 --- /dev/null +++ b/plugins/streaming/icons/hi64-action-tderadio_streaming.png 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 <[email protected]>, 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 <[email protected]>\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. +# Алексей Кузнецов <[email protected]>, 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: Алексей Кузнецов <[email protected]>\n" +"Language-Team: <[email protected]>\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 <[email protected]>\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 : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <tqcheckbox.h> + +#include <kurlrequester.h> +#include <knuminput.h> +#include <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 : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef KRADIO_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 : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "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 : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _KRADIO_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 : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "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 : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _KRADIO_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 |