diff options
Diffstat (limited to 'kradio3/plugins/streaming')
17 files changed, 2967 insertions, 0 deletions
diff --git a/kradio3/plugins/streaming/Makefile.am b/kradio3/plugins/streaming/Makefile.am new file mode 100644 index 0000000..0e5ed11 --- /dev/null +++ b/kradio3/plugins/streaming/Makefile.am @@ -0,0 +1,18 @@ +SUBDIRS = po icons . + +INCLUDES = $(all_includes) +METASOURCES = AUTO + +libkradio_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/kradio-streaming.pot + +messages: rc.cpp + $(EXTRACTRC) *.rc *.ui >> rc.cpp + $(XGETTEXT) rc.cpp *.h *.cpp -o po/kradio-streaming.pot diff --git a/kradio3/plugins/streaming/icons/Makefile.am b/kradio3/plugins/streaming/icons/Makefile.am new file mode 100644 index 0000000..b3f2583 --- /dev/null +++ b/kradio3/plugins/streaming/icons/Makefile.am @@ -0,0 +1,2 @@ +icons_ICON = AUTO +iconsdir = $(kde_datadir)/kradio/icons diff --git a/kradio3/plugins/streaming/icons/hi16-action-kradio_streaming.png b/kradio3/plugins/streaming/icons/hi16-action-kradio_streaming.png Binary files differnew file mode 100644 index 0000000..af7de60 --- /dev/null +++ b/kradio3/plugins/streaming/icons/hi16-action-kradio_streaming.png diff --git a/kradio3/plugins/streaming/icons/hi22-action-kradio_streaming.png b/kradio3/plugins/streaming/icons/hi22-action-kradio_streaming.png Binary files differnew file mode 100644 index 0000000..c737464 --- /dev/null +++ b/kradio3/plugins/streaming/icons/hi22-action-kradio_streaming.png diff --git a/kradio3/plugins/streaming/icons/hi32-action-kradio_streaming.png b/kradio3/plugins/streaming/icons/hi32-action-kradio_streaming.png Binary files differnew file mode 100644 index 0000000..d3ce851 --- /dev/null +++ b/kradio3/plugins/streaming/icons/hi32-action-kradio_streaming.png diff --git a/kradio3/plugins/streaming/icons/hi48-action-kradio_streaming.png b/kradio3/plugins/streaming/icons/hi48-action-kradio_streaming.png Binary files differnew file mode 100644 index 0000000..2e1ff2a --- /dev/null +++ b/kradio3/plugins/streaming/icons/hi48-action-kradio_streaming.png diff --git a/kradio3/plugins/streaming/icons/hi64-action-kradio_streaming.png b/kradio3/plugins/streaming/icons/hi64-action-kradio_streaming.png Binary files differnew file mode 100644 index 0000000..465cda6 --- /dev/null +++ b/kradio3/plugins/streaming/icons/hi64-action-kradio_streaming.png diff --git a/kradio3/plugins/streaming/po/Makefile.am b/kradio3/plugins/streaming/po/Makefile.am new file mode 100644 index 0000000..e1b5685 --- /dev/null +++ b/kradio3/plugins/streaming/po/Makefile.am @@ -0,0 +1,2 @@ +PACKAGE = kradio-streaming +POFILES = AUTO diff --git a/kradio3/plugins/streaming/po/de.po b/kradio3/plugins/streaming/po/de.po new file mode 100644 index 0000000..aaa1e2e --- /dev/null +++ b/kradio3/plugins/streaming/po/de.po @@ -0,0 +1,226 @@ +# translation of de.po to +# translation of kradio-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: 2006-11-12 18:41+0100\n" +"PO-Revision-Date: 2006-11-12 18:24+0100\n" +"Last-Translator: Ernst Martin Witte <[email protected]>\n" +"Language-Team: <[email protected]>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.11.4\n" + +#. i18n: file streaming-configuration-ui.ui line 16 +#: rc.cpp:3 rc.cpp:95 streaming-configuration-ui.cpp:253 +#, no-c-format +msgid "StreamingConfigurationUI" +msgstr "StreamingConfigurationUI" + +#. i18n: file streaming-configuration-ui.ui line 33 +#. i18n: file streaming-configuration-ui.ui line 74 +#. i18n: file streaming-configuration-ui.ui line 33 +#. i18n: file streaming-configuration-ui.ui line 74 +#: rc.cpp:6 rc.cpp:12 rc.cpp:98 rc.cpp:104 streaming-configuration-ui.cpp:43 +#: streaming-configuration-ui.cpp:52 streaming-configuration-ui.cpp:254 +#: streaming-configuration-ui.cpp:256 +#, no-c-format +msgid "No." +msgstr "Nr." + +#. i18n: file streaming-configuration-ui.ui line 44 +#. i18n: file streaming-configuration-ui.ui line 85 +#. i18n: file streaming-configuration-ui.ui line 44 +#. i18n: file streaming-configuration-ui.ui line 85 +#: rc.cpp:9 rc.cpp:15 rc.cpp:101 rc.cpp:107 streaming-configuration-ui.cpp:44 +#: streaming-configuration-ui.cpp:53 streaming-configuration-ui.cpp:255 +#: streaming-configuration-ui.cpp:257 +#, no-c-format +msgid "URL" +msgstr "URL" + +#. i18n: file streaming-configuration-ui.ui line 114 +#: rc.cpp:18 rc.cpp:110 streaming-configuration-ui.cpp:258 +#, no-c-format +msgid "Capture URLs" +msgstr "Aufnahme-URL" + +#. i18n: file streaming-configuration-ui.ui line 122 +#: rc.cpp:21 rc.cpp:113 streaming-configuration-ui.cpp:259 +#, no-c-format +msgid "Playback URLs" +msgstr "Wiedergabe-URL" + +#. i18n: file streaming-configuration-ui.ui line 434 +#: rc.cpp:32 rc.cpp:124 streaming-configuration-ui.cpp:268 +#, no-c-format +msgid "URL Properties" +msgstr "URL-Eigenschaften" + +#. i18n: file streaming-configuration-ui.ui line 446 +#: rc.cpp:35 rc.cpp:127 streaming-configuration-ui.cpp:270 +#, no-c-format +msgid "Stereo" +msgstr "Stereo" + +#. i18n: file streaming-configuration-ui.ui line 451 +#: rc.cpp:38 rc.cpp:130 streaming-configuration-ui.cpp:271 +#, no-c-format +msgid "Mono" +msgstr "Mono" + +#. i18n: file streaming-configuration-ui.ui line 471 +#: rc.cpp:41 rc.cpp:133 streaming-configuration-ui.cpp:272 +#, no-c-format +msgid "Sample Bits" +msgstr "Quantisierungs-Bits" + +#. i18n: file streaming-configuration-ui.ui line 479 +#: rc.cpp:44 rc.cpp:136 streaming-configuration-ui.cpp:273 +#, no-c-format +msgid "Channels" +msgstr "Kanäle" + +#. i18n: file streaming-configuration-ui.ui line 487 +#: rc.cpp:47 rc.cpp:139 streaming-configuration-ui.cpp:274 +#, no-c-format +msgid "Endianess" +msgstr "Byte-Reihenfolge" + +#. i18n: file streaming-configuration-ui.ui line 493 +#: rc.cpp:50 rc.cpp:142 streaming-configuration-ui.cpp:276 +#, no-c-format +msgid "Little Endian" +msgstr "Little Endian" + +#. i18n: file streaming-configuration-ui.ui line 498 +#: rc.cpp:53 rc.cpp:145 streaming-configuration-ui.cpp:277 +#, no-c-format +msgid "Big Endian" +msgstr "Big Endian" + +#. i18n: file streaming-configuration-ui.ui line 516 +#: rc.cpp:56 rc.cpp:148 streaming-configuration-ui.cpp:279 +#, no-c-format +msgid "48000" +msgstr "48000" + +#. i18n: file streaming-configuration-ui.ui line 521 +#: rc.cpp:59 rc.cpp:151 streaming-configuration-ui.cpp:280 +#, no-c-format +msgid "44100" +msgstr "44100" + +#. i18n: file streaming-configuration-ui.ui line 526 +#: rc.cpp:62 rc.cpp:154 streaming-configuration-ui.cpp:281 +#, no-c-format +msgid "22050" +msgstr "22050" + +#. i18n: file streaming-configuration-ui.ui line 531 +#: rc.cpp:65 rc.cpp:157 streaming-configuration-ui.cpp:282 +#, no-c-format +msgid "11025" +msgstr "11025" + +#. i18n: file streaming-configuration-ui.ui line 549 +#: rc.cpp:68 rc.cpp:160 streaming-configuration-ui.cpp:284 +#, no-c-format +msgid "16" +msgstr "16" + +#. i18n: file streaming-configuration-ui.ui line 554 +#: rc.cpp:71 rc.cpp:163 streaming-configuration-ui.cpp:285 +#, no-c-format +msgid "8" +msgstr "8" + +#. i18n: file streaming-configuration-ui.ui line 572 +#: rc.cpp:74 rc.cpp:166 streaming-configuration-ui.cpp:287 +#, no-c-format +msgid "Raw" +msgstr "Rohdaten" + +#. i18n: file streaming-configuration-ui.ui line 592 +#: rc.cpp:77 rc.cpp:169 streaming-configuration-ui.cpp:288 +#, no-c-format +msgid "kB" +msgstr "kB" + +#. i18n: file streaming-configuration-ui.ui line 609 +#: rc.cpp:80 rc.cpp:172 streaming-configuration-ui.cpp:289 +#, no-c-format +msgid "Buffer Size" +msgstr "Puffergröße" + +#. i18n: file streaming-configuration-ui.ui line 617 +#: rc.cpp:83 rc.cpp:175 streaming-configuration-ui.cpp:290 +#, no-c-format +msgid "Format" +msgstr "Format" + +#. i18n: file streaming-configuration-ui.ui line 625 +#: rc.cpp:86 rc.cpp:178 streaming-configuration-ui.cpp:291 +#, no-c-format +msgid "Sample Rate" +msgstr "Abtastrate" + +#. i18n: file streaming-configuration-ui.ui line 631 +#: rc.cpp:89 rc.cpp:181 streaming-configuration-ui.cpp:293 +#, no-c-format +msgid "Signed" +msgstr "Vorzeichenbehaftet" + +#. i18n: file streaming-configuration-ui.ui line 636 +#: rc.cpp:92 rc.cpp:184 streaming-configuration-ui.cpp:294 +#, no-c-format +msgid "Unsigned" +msgstr "Vorzeichenlos" + +#: 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 "KRadio Streaming Plugin" +msgstr "KRadio 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 +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" diff --git a/kradio3/plugins/streaming/po/ru.po b/kradio3/plugins/streaming/po/ru.po new file mode 100644 index 0000000..c46978a --- /dev/null +++ b/kradio3/plugins/streaming/po/ru.po @@ -0,0 +1,228 @@ +# translation of ru.po to +# translation of kradio-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: 2006-11-12 18:20+0100\n" +"PO-Revision-Date: 2006-11-08 12:25+0300\n" +"Last-Translator: Алексей Кузнецов <[email protected]>\n" +"Language-Team: <[email protected]>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.10\n" + +#. i18n: file streaming-configuration-ui.ui line 16 +#: rc.cpp:3 rc.cpp:95 streaming-configuration-ui.cpp:253 +#, no-c-format +msgid "StreamingConfigurationUI" +msgstr "StreamingConfigurationUI" + +#. i18n: file streaming-configuration-ui.ui line 33 +#. i18n: file streaming-configuration-ui.ui line 74 +#. i18n: file streaming-configuration-ui.ui line 33 +#. i18n: file streaming-configuration-ui.ui line 74 +#: rc.cpp:6 rc.cpp:12 rc.cpp:98 rc.cpp:104 streaming-configuration-ui.cpp:43 +#: streaming-configuration-ui.cpp:52 streaming-configuration-ui.cpp:254 +#: streaming-configuration-ui.cpp:256 +#, no-c-format +msgid "No." +msgstr "No " + +#. i18n: file streaming-configuration-ui.ui line 44 +#. i18n: file streaming-configuration-ui.ui line 85 +#. i18n: file streaming-configuration-ui.ui line 44 +#. i18n: file streaming-configuration-ui.ui line 85 +#: rc.cpp:9 rc.cpp:15 rc.cpp:101 rc.cpp:107 streaming-configuration-ui.cpp:44 +#: streaming-configuration-ui.cpp:53 streaming-configuration-ui.cpp:255 +#: streaming-configuration-ui.cpp:257 +#, no-c-format +msgid "URL" +msgstr "Адрес" + +#. i18n: file streaming-configuration-ui.ui line 114 +#: rc.cpp:18 rc.cpp:110 streaming-configuration-ui.cpp:258 +#, no-c-format +msgid "Capture URLs" +msgstr "Адреса для записи" + +#. i18n: file streaming-configuration-ui.ui line 122 +#: rc.cpp:21 rc.cpp:113 streaming-configuration-ui.cpp:259 +#, no-c-format +msgid "Playback URLs" +msgstr "Адреса для воспроизведения" + +#. i18n: file streaming-configuration-ui.ui line 434 +#: rc.cpp:32 rc.cpp:124 streaming-configuration-ui.cpp:268 +#, no-c-format +msgid "URL Properties" +msgstr "Параметры для URL" + +#. i18n: file streaming-configuration-ui.ui line 446 +#: rc.cpp:35 rc.cpp:127 streaming-configuration-ui.cpp:270 +#, no-c-format +msgid "Stereo" +msgstr "2 (Стерео)" + +#. i18n: file streaming-configuration-ui.ui line 451 +#: rc.cpp:38 rc.cpp:130 streaming-configuration-ui.cpp:271 +#, no-c-format +msgid "Mono" +msgstr "1 (Моно)" + +#. i18n: file streaming-configuration-ui.ui line 471 +#: rc.cpp:41 rc.cpp:133 streaming-configuration-ui.cpp:272 +#, no-c-format +msgid "Sample Bits" +msgstr "Бит на элемент выборки" + +#. i18n: file streaming-configuration-ui.ui line 479 +#: rc.cpp:44 rc.cpp:136 streaming-configuration-ui.cpp:273 +#, no-c-format +msgid "Channels" +msgstr "Число каналов" + +#. i18n: file streaming-configuration-ui.ui line 487 +#: rc.cpp:47 rc.cpp:139 streaming-configuration-ui.cpp:274 +#, no-c-format +msgid "Endianess" +msgstr "Порядок байтов" + +#. i18n: file streaming-configuration-ui.ui line 493 +#: rc.cpp:50 rc.cpp:142 streaming-configuration-ui.cpp:276 +#, no-c-format +msgid "Little Endian" +msgstr "Little Endian" + +#. i18n: file streaming-configuration-ui.ui line 498 +#: rc.cpp:53 rc.cpp:145 streaming-configuration-ui.cpp:277 +#, no-c-format +msgid "Big Endian" +msgstr "Big Endian" + +#. i18n: file streaming-configuration-ui.ui line 516 +#: rc.cpp:56 rc.cpp:148 streaming-configuration-ui.cpp:279 +#, no-c-format +msgid "48000" +msgstr "48000" + +#. i18n: file streaming-configuration-ui.ui line 521 +#: rc.cpp:59 rc.cpp:151 streaming-configuration-ui.cpp:280 +#, no-c-format +msgid "44100" +msgstr "44100" + +#. i18n: file streaming-configuration-ui.ui line 526 +#: rc.cpp:62 rc.cpp:154 streaming-configuration-ui.cpp:281 +#, no-c-format +msgid "22050" +msgstr "22050" + +#. i18n: file streaming-configuration-ui.ui line 531 +#: rc.cpp:65 rc.cpp:157 streaming-configuration-ui.cpp:282 +#, no-c-format +msgid "11025" +msgstr "11025" + +#. i18n: file streaming-configuration-ui.ui line 549 +#: rc.cpp:68 rc.cpp:160 streaming-configuration-ui.cpp:284 +#, no-c-format +msgid "16" +msgstr "16" + +#. i18n: file streaming-configuration-ui.ui line 554 +#: rc.cpp:71 rc.cpp:163 streaming-configuration-ui.cpp:285 +#, no-c-format +msgid "8" +msgstr "8" + +#. i18n: file streaming-configuration-ui.ui line 572 +#: rc.cpp:74 rc.cpp:166 streaming-configuration-ui.cpp:287 +#, no-c-format +msgid "Raw" +msgstr "Raw" + +#. i18n: file streaming-configuration-ui.ui line 592 +#: rc.cpp:77 rc.cpp:169 streaming-configuration-ui.cpp:288 +#, no-c-format +msgid "kB" +msgstr "kB" + +#. i18n: file streaming-configuration-ui.ui line 609 +#: rc.cpp:80 rc.cpp:172 streaming-configuration-ui.cpp:289 +#, no-c-format +msgid "Buffer Size" +msgstr "Размер буфера" + +#. i18n: file streaming-configuration-ui.ui line 617 +#: rc.cpp:83 rc.cpp:175 streaming-configuration-ui.cpp:290 +#, no-c-format +msgid "Format" +msgstr "Формат" + +#. i18n: file streaming-configuration-ui.ui line 625 +#: rc.cpp:86 rc.cpp:178 streaming-configuration-ui.cpp:291 +#, no-c-format +msgid "Sample Rate" +msgstr "Частота дискретизации" + +#. i18n: file streaming-configuration-ui.ui line 631 +#: rc.cpp:89 rc.cpp:181 streaming-configuration-ui.cpp:293 +#, no-c-format +msgid "Signed" +msgstr "Со знаком" + +#. i18n: file streaming-configuration-ui.ui line 636 +#: rc.cpp:92 rc.cpp:184 streaming-configuration-ui.cpp:294 +#, no-c-format +msgid "Unsigned" +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 "KRadio Streaming Plugin" +msgstr "Модуль сетевого вещания для KRadio" + +#: 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 +msgid "Streaming Device %1" +msgstr "Устройство вещания %1" + +#: streaming.cpp:432 streaming.cpp:437 +msgid "Streaming Device %1, %2: %3" +msgstr "Устройство вещания %1, %2: %3" diff --git a/kradio3/plugins/streaming/streaming-configuration-ui.ui b/kradio3/plugins/streaming/streaming-configuration-ui.ui new file mode 100644 index 0000000..001d4ae --- /dev/null +++ b/kradio3/plugins/streaming/streaming-configuration-ui.ui @@ -0,0 +1,777 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>StreamingConfigurationUI</class> +<widget class="QWidget"> + <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="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout48</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KListView" 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="KListView" 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="QLabel" row="0" column="2"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>Capture URLs</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Playback URLs</string> + </property> + </widget> + <widget class="QLayoutWidget" row="1" column="3"> + <property name="name"> + <cstring>layout38_2</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <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="QPushButton"> + <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>"editdelete"</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="QPushButton"> + <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="QPushButton"> + <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="QLayoutWidget" row="1" column="1"> + <property name="name"> + <cstring>layout38</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <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="QPushButton"> + <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>"editdelete"</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="QPushButton"> + <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="QPushButton"> + <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="QGroupBox" 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="QLabel" row="3" column="0"> + <property name="name"> + <cstring>lableBits</cstring> + </property> + <property name="text"> + <string>Sample Bits</string> + </property> + </widget> + <widget class="QLabel" row="5" column="0"> + <property name="name"> + <cstring>lableChannels</cstring> + </property> + <property name="text"> + <string>Channels</string> + </property> + </widget> + <widget class="QLabel" 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="QLabel" row="0" column="0"> + <property name="name"> + <cstring>labelRate_2</cstring> + </property> + <property name="text"> + <string>Buffer Size</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>labelRate_2_2</cstring> + </property> + <property name="text"> + <string>Format</string> + </property> + </widget> + <widget class="QLabel" 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> +<includes> + <include location="global" impldecl="in implementation">kiconloader.h</include> +</includes> +<pixmapfunction>SmallIconSet</pixmapfunction> +<layoutdefaults spacing="6" margin="0"/> +<includehints> + <includehint>klistview.h</includehint> + <includehint>klistview.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>kcombobox.h</includehint> +</includehints> +</UI> diff --git a/kradio3/plugins/streaming/streaming-configuration.cpp b/kradio3/plugins/streaming/streaming-configuration.cpp new file mode 100644 index 0000000..ea1801d --- /dev/null +++ b/kradio3/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 <qcheckbox.h> + +#include <kurlrequester.h> +#include <knuminput.h> +#include <klistview.h> +#include <kcombobox.h> +#include <knuminput.h> + +#include <klocale.h> + +#include "streaming-configuration.h" +#include "streaming.h" + +StreamingConfiguration::StreamingConfiguration (QWidget *parent, StreamingDevice *streamer) + : StreamingConfigurationUI(parent), + m_ignore_updates(false), + m_dirty(true), + m_StreamingDevice(streamer) +{ + connect(m_pbNewPlaybackURL, SIGNAL(clicked()), this, SLOT(slotNewPlaybackChannel())); + connect(m_pbDeletePlaybackURL, SIGNAL(clicked()), this, SLOT(slotDeletePlaybackChannel())); + connect(m_pbUpPlaybackURL, SIGNAL(clicked()), this, SLOT(slotUpPlaybackChannel())); + connect(m_pbDownPlaybackURL, SIGNAL(clicked()), this, SLOT(slotDownPlaybackChannel())); + connect(m_ListPlaybackURLs, SIGNAL(selectionChanged()), this, SLOT(slotPlaybackSelectionChanged())); + connect(m_ListPlaybackURLs, SIGNAL(itemRenamed(QListViewItem *)), this, SLOT(slotSetDirty())); + + connect(m_pbNewCaptureURL, SIGNAL(clicked()), this, SLOT(slotNewCaptureChannel())); + connect(m_pbDeleteCaptureURL, SIGNAL(clicked()), this, SLOT(slotDeleteCaptureChannel())); + connect(m_pbUpCaptureURL, SIGNAL(clicked()), this, SLOT(slotUpCaptureChannel())); + connect(m_pbDownCaptureURL, SIGNAL(clicked()), this, SLOT(slotDownCaptureChannel())); + connect(m_ListCaptureURLs, SIGNAL(selectionChanged()), this, SLOT(slotCaptureSelectionChanged())); + connect(m_ListCaptureURLs, SIGNAL(itemRenamed(QListViewItem *)), this, SLOT(slotSetDirty())); + + connect(m_cbBits, SIGNAL(activated(int)), this, SLOT(slotUpdateSoundFormat())); + connect(m_cbChannels, SIGNAL(activated(int)), this, SLOT(slotUpdateSoundFormat())); + connect(m_cbEndianess, SIGNAL(activated(int)), this, SLOT(slotUpdateSoundFormat())); + connect(m_cbFormat, SIGNAL(activated(int)), this, SLOT(slotUpdateSoundFormat())); + connect(m_cbRate, SIGNAL(activated(int)), this, SLOT(slotUpdateSoundFormat())); + connect(m_cbSign, SIGNAL(activated(int)), this, SLOT(slotUpdateSoundFormat())); + connect(m_sbBufferSize, SIGNAL(valueChanged(int)), this, 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); + + QListViewItem *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 QStringList &playbackChannels = m_StreamingDevice->getPlaybackChannels(); + const QStringList &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; + QString url; + m_StreamingDevice->getPlaybackStreamOptions(playbackChannels[i], url, sf, buffer_size); + m_PlaybackSoundFormats.append(sf); + m_PlaybackBufferSizes.append(buffer_size); + + QListViewItem *item = new QListViewItem(m_ListPlaybackURLs, m_ListPlaybackURLs->lastChild()); + item->setText(0, QString::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; + QString url; + m_StreamingDevice->getCaptureStreamOptions(captureChannels[i], url, sf, buffer_size); + m_CaptureSoundFormats.append(sf); + m_CaptureBufferSizes.append(buffer_size); + + QListViewItem *item = new QListViewItem(m_ListCaptureURLs, m_ListCaptureURLs->lastChild()); + item->setText(0, QString::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(); + QListViewItem *item = new QListViewItem(m_ListPlaybackURLs, m_ListPlaybackURLs->lastChild()); + item->setText(0, QString::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(); + QListViewItem *item = m_ListPlaybackURLs->selectedItem(); + if (item) { + int idx = 0; + QListViewItem *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, QString::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(); + QListViewItem *prev = NULL; + QListViewItem *i = m_ListPlaybackURLs->firstChild(); + QListViewItem *item = m_ListPlaybackURLs->selectedItem(); + int idx = 0; + for (; i && i != item; i = i->nextSibling(), ++idx) { + prev = i; + } + if (prev && item) { + QString 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(); + QListViewItem *item = m_ListPlaybackURLs->selectedItem(); + QListViewItem *next = item ? item->nextSibling() : NULL; + QListViewItem *i = m_ListPlaybackURLs->firstChild(); + int idx = 0; + for (; i && i != item; i = i->nextSibling()) { + ++idx; + } + if (next && item) { + QString 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(); + QListViewItem *item = new QListViewItem(m_ListCaptureURLs, m_ListCaptureURLs->lastChild()); + item->setText(0, QString::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(); + QListViewItem *item = m_ListCaptureURLs->selectedItem(); + if (item) { + int idx = 0; + QListViewItem *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, QString::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(); + QListViewItem *prev = NULL; + QListViewItem *i = m_ListCaptureURLs->firstChild(); + QListViewItem *item = m_ListCaptureURLs->selectedItem(); + int idx = 0; + for (; i && i != item; i = i->nextSibling(), ++idx) { + prev = i; + } + if (prev && item) { + QString 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(); + QListViewItem *item = m_ListCaptureURLs->selectedItem(); + QListViewItem *next = item ? item->nextSibling() : NULL; + QListViewItem *i = m_ListCaptureURLs->firstChild(); + int idx = 0; + for (; i && i != item; i = i->nextSibling()) { + ++idx; + } + if (next && item) { + QString 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() +{ + QListViewItem *item = m_ListPlaybackURLs->selectedItem(); + bool up_possible = false; + bool down_possible = false; + if (item) { + int idx = 0; + QListViewItem *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); + } + QListViewItem *playback_item = m_ListPlaybackURLs->selectedItem(); + QListViewItem *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() +{ + QListViewItem *item = m_ListCaptureURLs->selectedItem(); + bool up_possible = false; + bool down_possible = false; + if (item) { + int idx = 0; + QListViewItem *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); + } + QListViewItem *playback_item = m_ListPlaybackURLs->selectedItem(); + QListViewItem *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(); + QListViewItem *playback_item = m_ListPlaybackURLs->selectedItem(); + QListViewItem *capture_item = m_ListCaptureURLs->selectedItem(); + if (playback_item) { + int idx = 0; + QListViewItem *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; + QListViewItem *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/kradio3/plugins/streaming/streaming-configuration.h b/kradio3/plugins/streaming/streaming-configuration.h new file mode 100644 index 0000000..f40a0cb --- /dev/null +++ b/kradio3/plugins/streaming/streaming-configuration.h @@ -0,0 +1,97 @@ +/*************************************************************************** + 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 (QWidget *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 ; + + + QValueList<SoundFormat> m_PlaybackSoundFormats, m_CaptureSoundFormats; + QValueList<int> m_PlaybackBufferSizes, m_CaptureBufferSizes; + + bool m_ignore_updates; + bool m_dirty; + StreamingDevice *m_StreamingDevice; + +}; + +#endif diff --git a/kradio3/plugins/streaming/streaming-job.cpp b/kradio3/plugins/streaming/streaming-job.cpp new file mode 100644 index 0000000..0c3736a --- /dev/null +++ b/kradio3/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 <kio/job.h> + + +StreamingJob::StreamingJob() + : QObject(), + m_URL(QString::null), + m_SoundFormat(), + m_BufferSize(65536), + m_Buffer(m_BufferSize), + m_OpenCounter(0), + m_StreamPos(0), + m_StartTime(0), + m_SkipCount(0), + m_KIO_Job(NULL), + m_capturing(false) +{ +} + +StreamingJob::StreamingJob(const QString &_URL, const SoundFormat &_SoundFormat, size_t _bufferSize) + : QObject(), + 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_KIO_Job(NULL), + m_capturing(false) +{ +} + +StreamingJob::StreamingJob(const StreamingJob &c) + : QObject(), + 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_KIO_Job(NULL), + m_capturing(c.m_capturing) +{ +} + +StreamingJob::~StreamingJob() +{ +} + + +void StreamingJob::setURL(const QString &url) +{ + if (m_URL != url) { + m_URL = url; + delete m_KIO_Job; + m_KIO_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_KIO_Job = KIO::put(m_URL, -1, true, false, false); + if (!m_KIO_Job) + return false; + m_KIO_Job->setAsyncDataEnabled(true); + connect (m_KIO_Job, SIGNAL(dataReq(KIO::Job *job, QByteArray &data)), + this, SLOT(slotWriteData (KIO::Job *job, QByteArray &data))); + connect (m_KIO_Job, SIGNAL(result(KIO::Job *)), + this, SLOT(slotIOJobResult(KIO::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_KIO_Job->error()) { + emit logStreamError(m_URL, m_KIO_Job->errorString()); + } + return m_KIO_Job->error() == 0; + } + else { + return true; + } +} + +bool StreamingJob::stopPlayback() +{ + if (m_OpenCounter) { + if (!--m_OpenCounter) { + delete m_KIO_Job; + m_KIO_Job = NULL; + } + } + return true; +} + + +bool StreamingJob::startGetJob() +{ + m_KIO_Job = KIO::get(m_URL, false, false); + if (!m_KIO_Job) + return false; + m_KIO_Job->setAsyncDataEnabled(true); + connect (m_KIO_Job, SIGNAL(data(KIO::Job *, const QByteArray &)), + this, SLOT(slotReadData(KIO::Job *, const QByteArray &))); + connect (m_KIO_Job, SIGNAL(result(KIO::Job *)), + this, SLOT(slotIOJobResult(KIO::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_KIO_Job->error()) { + emit logStreamError(m_URL, m_KIO_Job->errorString()); + } + return m_KIO_Job->error() == 0; + } + ++m_OpenCounter; + real_format = m_SoundFormat; + return true; +} + + +bool StreamingJob::stopCapture() +{ + if (m_OpenCounter) { + if (!--m_OpenCounter) { + delete m_KIO_Job; + m_KIO_Job = NULL; + } + } + return true; +} + + +void StreamingJob::slotReadData (KIO::Job */*job*/, const QByteArray &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_KIO_Job->suspend(); + } +} + + +void StreamingJob::slotWriteData (KIO::Job */*job*/, QByteArray &) +{ + size_t size = m_Buffer.getFillSize(); + if (size) { + char *buf = new char [size]; + size = m_Buffer.takeData(buf, size); + QByteArray data; + data.assign(buf, size); + m_KIO_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_KIO_Job->resume(); + } +} + +void StreamingJob::slotIOJobResult (KIO::Job *job) +{ + if (job && job->error()) { + emit logStreamError(m_URL, job->errorString()); + } +} + +#include "streaming-job.moc" + diff --git a/kradio3/plugins/streaming/streaming-job.h b/kradio3/plugins/streaming/streaming-job.h new file mode 100644 index 0000000..b88c32a --- /dev/null +++ b/kradio3/plugins/streaming/streaming-job.h @@ -0,0 +1,100 @@ +/*************************************************************************** + 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 <qobject.h> + +#include <kio/jobclasses.h> + +class StreamingJob : public QObject +{ +Q_OBJECT +public: + StreamingJob(); + StreamingJob(const QString &_URL, const SoundFormat &_SoundFormat, size_t _bufferSize); + StreamingJob(const StreamingJob &c); + + virtual ~StreamingJob(); + + const QString &getURL() const { return m_URL; } + const SoundFormat &getSoundFormat() const { return m_SoundFormat; } + int getBufferSize() const { return m_BufferSize; } + + void setURL(const QString &); + 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 (KIO::Job *job, const QByteArray &data); + void slotWriteData (KIO::Job *job, QByteArray &data); + void slotIOJobResult (KIO::Job *job); + +signals: + + void logStreamError(const KURL &url, const QString &s); + void logStreamWarning(const KURL &url, const QString &s); + +protected: + + bool startGetJob(); + bool startPutJob(); + + + QString m_URL; + SoundFormat m_SoundFormat; + + size_t m_BufferSize; + RingBuffer m_Buffer; + + unsigned m_OpenCounter; + Q_UINT64 m_StreamPos; + time_t m_StartTime; + + size_t m_SkipCount; + + KIO::TransferJob *m_KIO_Job; + bool m_capturing; +}; + + + +#endif diff --git a/kradio3/plugins/streaming/streaming.cpp b/kradio3/plugins/streaming/streaming.cpp new file mode 100644 index 0000000..5f5431c --- /dev/null +++ b/kradio3/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 <klocale.h> +#include <kaboutdata.h> +#include <kurl.h> +#include <klocale.h> + +#include "streaming-job.h" +#include "streaming-configuration.h" + +/////////////////////////////////////////////////////////////////////// +//// plugin library functions + +PLUGIN_LIBRARY_FUNCTIONS(StreamingDevice, "kradio-streaming", i18n("Streaming Support")); + +///////////////////////////////////////////////////////////////////////////// + + + + +StreamingDevice::StreamingDevice(const QString &name) + : QObject(NULL, NULL), + PluginBase(name, i18n("KRadio 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 (KConfig *c) const +{ + c->setGroup(QString("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) { + QString 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-" + QString::number(i), c); + c->writeEntry("playback-channel-" + QString::number(i) + "-url", url.url()); + c->writeEntry("playback-channel-" + QString::number(i) + "-buffer-size", buffer_size); + } + + c->writeEntry("capture-channels", m_CaptureChannelList.size()); + for (unsigned int i = 0; i < m_CaptureChannelList.size(); ++i) { + QString 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-" + QString::number(i), c); + c->writeEntry("capture-channel-" + QString::number(i) + "-url", url.url()); + c->writeEntry("capture-channel-" + QString::number(i) + "-buffer-size", buffer_size); + } +} + +void StreamingDevice::restoreState (KConfig *c) +{ + c->setGroup(QString("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-" + QString::number(i), c); + QString url = c->readEntry("playback-channel-" + QString::number(i) + "-url", QString::null); + size_t buffer_size = c->readNum64Entry("playback-channel-" + QString::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-" + QString::number(i), c); + QString url = c->readEntry("capture-channel-" + QString::number(i) + "-url", QString::null); + size_t buffer_size = c->readNum64Entry("capture-channel-" + QString::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); + QObject::connect(this, SIGNAL(sigUpdateConfig()), conf, SLOT(slotUpdateConfig())); + return ConfigPageInfo (conf, + i18n("Streaming"), + i18n("Streaming Device Options"), + "kradio_streaming"); +} + + +AboutPageInfo StreamingDevice::createAboutPage() +{ + return AboutPageInfo(); +} + + + +bool StreamingDevice::preparePlayback(SoundStreamID id, const QString &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 QString &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 QStringList &StreamingDevice::getPlaybackChannels() const +{ + return m_PlaybackChannelList; +} + + +const QStringList &StreamingDevice::getCaptureChannels() const +{ + return m_CaptureChannelList; +} + + +QString StreamingDevice::getSoundStreamClientDescription() const +{ + return i18n("Streaming Device %1").arg(PluginBase::name()); +} + + +void StreamingDevice::logStreamError(const KURL &url, const QString &s) +{ + logError(i18n("Streaming Device %1, %2: %3").arg(name()).arg(url.url()).arg(s)); +} + +void StreamingDevice::logStreamWarning(const KURL &url, const QString &s) +{ + logWarning(i18n("Streaming Device %1, %2: %3").arg(name()).arg(url.url()).arg(s)); +} + + +bool StreamingDevice::getPlaybackStreamOptions(const QString &channel, QString &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 QString &channel, QString &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 QString &url, const SoundFormat &sf, size_t buffer_size, bool notification_enabled) +{ + StreamingJob *x = new StreamingJob(url, sf, buffer_size); + connect(x, SIGNAL(logStreamError(const KURL &, const QString &)), + this, SLOT (logStreamError(const KURL &, const QString &))); + + m_PlaybackChannelList.append(url); + m_PlaybackChannels.insert(url, x); + if (notification_enabled) { + notifyPlaybackChannelsChanged(m_SoundStreamClientID, m_PlaybackChannelList); + } +} + + +void StreamingDevice::addCaptureStream (const QString &url, const SoundFormat &sf, size_t buffer_size, bool notification_enabled) +{ + StreamingJob *x = new StreamingJob(url, sf, buffer_size); + connect(x, SIGNAL(logStreamError(const KURL &, const QString &)), + this, SLOT (logStreamError(const KURL &, const QString &))); + + m_CaptureChannelList.append(url); + m_CaptureChannels.insert(url, x); + if (notification_enabled) { + notifyCaptureChannelsChanged(m_SoundStreamClientID, m_CaptureChannelList); + } +} + + +#include "streaming.moc" diff --git a/kradio3/plugins/streaming/streaming.h b/kradio3/plugins/streaming/streaming.h new file mode 100644 index 0000000..430ab7b --- /dev/null +++ b/kradio3/plugins/streaming/streaming.h @@ -0,0 +1,145 @@ +/*************************************************************************** + 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 <qobject.h> +#include <qdict.h> + +class StreamingJob; + +class StreamingDevice : public QObject, + public PluginBase, + public ISoundStreamClient +{ +Q_OBJECT + +public: + StreamingDevice (const QString &name); + virtual ~StreamingDevice (); + + virtual bool connectI(Interface *i); + virtual bool disconnectI(Interface *i); + + bool getPlaybackStreamOptions(const QString &channel, QString &url, SoundFormat &sf, size_t &buffer_size) const; + bool getCaptureStreamOptions (const QString &channel, QString &url, SoundFormat &sf, size_t &buffer_size) const; + + void resetPlaybackStreams(bool notification_enabled = true); + void resetCaptureStreams(bool notification_enabled = true); + void addPlaybackStream(const QString &url, const SoundFormat &sf, size_t buffer_size, bool notification_enabled = true); + void addCaptureStream (const QString &url, const SoundFormat &sf, size_t buffer_size, bool notification_enabled = true); + + // PluginBase + +public: + virtual void saveState (KConfig *) const; + virtual void restoreState (KConfig *); + + virtual QString pluginClassName() const { return "StreamingDevice"; } + + virtual const QString &name() const { return PluginBase::name(); } + virtual QString &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 QString &channel, bool active_mode, bool start_immediately); + bool prepareCapture(SoundStreamID id, const QString &channel); + bool releasePlayback(SoundStreamID id); + bool releaseCapture(SoundStreamID id); + +ANSWERS: + bool supportsPlayback() const; + bool supportsCapture() const; + + QString getSoundStreamClientDescription() const; + + // ISoundStreamClient: mixer access + +protected: + +ANSWERS: + const QStringList &getPlaybackChannels() const; + const QStringList &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 QString &s); + void logStreamWarning(const KURL &url, const QString &s); + +signals: + + void sigUpdateConfig(); + +protected: + + QStringList m_PlaybackChannelList, + m_CaptureChannelList; + + QDict<StreamingJob> + m_PlaybackChannels, + m_CaptureChannels; + + QMap<SoundStreamID, QString> + m_AllPlaybackStreams, + m_AllCaptureStreams, + m_EnabledPlaybackStreams, + m_EnabledCaptureStreams; +}; + + + +#endif |