diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2017-01-03 18:39:36 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2017-01-03 18:39:36 +0000 |
| commit | 7696ef13c13aea0da9acada8abb149967aaf8a90 (patch) | |
| tree | cd700a27da47071bc605fe2cc88992d940de2307 /src/plugins | |
| parent | 28dda78e5036bae2bd317decf950ba9f6caea780 (diff) | |
| download | qmmp-7696ef13c13aea0da9acada8abb149967aaf8a90.tar.gz qmmp-7696ef13c13aea0da9acada8abb149967aaf8a90.tar.bz2 qmmp-7696ef13c13aea0da9acada8abb149967aaf8a90.zip | |
icecast plugin: added resampler and settings dialog
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@6930 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/plugins')
| -rw-r--r-- | src/plugins/Output/shout/settingsdialog.cpp | 64 | ||||
| -rw-r--r-- | src/plugins/Output/shout/settingsdialog.h | 45 | ||||
| -rw-r--r-- | src/plugins/Output/shout/settingsdialog.ui | 196 | ||||
| -rw-r--r-- | src/plugins/Output/shout/shoutclient.cpp | 24 | ||||
| -rw-r--r-- | src/plugins/Output/shout/shoutoutput.cpp | 60 | ||||
| -rw-r--r-- | src/plugins/Output/shout/shoutoutput.h | 5 |
6 files changed, 376 insertions, 18 deletions
diff --git a/src/plugins/Output/shout/settingsdialog.cpp b/src/plugins/Output/shout/settingsdialog.cpp new file mode 100644 index 000000000..0e72144ea --- /dev/null +++ b/src/plugins/Output/shout/settingsdialog.cpp @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (C) 2017 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * 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. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include <QSettings> +#include <qmmp/qmmp.h> +#include "settingsdialog.h" +#include "ui_settingsdialog.h" + +SettingsDialog::SettingsDialog(QWidget *parent) : + QDialog(parent), + m_ui(new Ui::SettingsDialog) +{ + m_ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, true); + QSettings settings(Qmmp::configFile(), QSettings::IniFormat); + settings.beginGroup("Shout"); + m_ui->hostLineEdit->setText(settings.value("host", "127.0.0.1").toString()); + m_ui->portSpinBox->setValue(settings.value("port", 8000).toInt()); + m_ui->mountPointLineEdit->setText(settings.value("mount", "qmmp.out").toString()); + m_ui->userLineEdit->setText(settings.value("user", "source").toString()); + m_ui->passwLineEdit->setText(settings.value("passw", "hackme").toString()); + m_ui->publicCheckBox->setChecked(settings.value("public", false).toBool()); + m_ui->qualitySpinBox->setValue(settings.value("vorbis_quality", 0.8).toDouble()); + m_ui->srateSpinBox->setValue(settings.value("sample_rate", 44100).toInt()); + settings.endGroup(); +} + +SettingsDialog::~SettingsDialog() +{ + delete m_ui; +} + +void SettingsDialog::accept() +{ + QSettings settings(Qmmp::configFile(), QSettings::IniFormat); + settings.beginGroup("Shout"); + settings.setValue("host", m_ui->hostLineEdit->text()); + settings.setValue("port", m_ui->portSpinBox->value()); + settings.setValue("mount", m_ui->mountPointLineEdit->text()); + settings.setValue("user", m_ui->userLineEdit->text()); + settings.setValue("passw", m_ui->passwLineEdit->text()); + settings.setValue("public", m_ui->publicCheckBox->isChecked()); + settings.setValue("vorbis_quality", m_ui->qualitySpinBox->value()); + settings.setValue("sample_rate", m_ui->srateSpinBox->value()); + settings.endGroup(); + QDialog::accept(); +} diff --git a/src/plugins/Output/shout/settingsdialog.h b/src/plugins/Output/shout/settingsdialog.h new file mode 100644 index 000000000..0b05b5520 --- /dev/null +++ b/src/plugins/Output/shout/settingsdialog.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2017 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * 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. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef SETTINGSDIALOG_H +#define SETTINGSDIALOG_H + +#include <QDialog> + +namespace Ui { +class SettingsDialog; +} + +class SettingsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SettingsDialog(QWidget *parent = 0); + ~SettingsDialog(); + +public slots: + void accept(); + +private: + Ui::SettingsDialog *m_ui; +}; + +#endif // SETTINGSDIALOG_H diff --git a/src/plugins/Output/shout/settingsdialog.ui b/src/plugins/Output/shout/settingsdialog.ui new file mode 100644 index 000000000..e1e20048f --- /dev/null +++ b/src/plugins/Output/shout/settingsdialog.ui @@ -0,0 +1,196 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SettingsDialog</class> + <widget class="QDialog" name="SettingsDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>450</width> + <height>302</height> + </rect> + </property> + <property name="windowTitle"> + <string>Connection Settings</string> + </property> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::AllNonFixedFieldsGrow</enum> + </property> + <property name="leftMargin"> + <number>6</number> + </property> + <property name="rightMargin"> + <number>6</number> + </property> + <property name="bottomMargin"> + <number>6</number> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Host:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="hostLineEdit"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Port:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="portSpinBox"> + <property name="maximum"> + <number>65535</number> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Mount point:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="mountPointLineEdit"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>User:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLineEdit" name="userLineEdit"/> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Password:</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLineEdit" name="passwLineEdit"/> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_6"> + <property name="text"> + <string>Quality:</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QDoubleSpinBox" name="qualitySpinBox"> + <property name="minimum"> + <double>0.200000000000000</double> + </property> + <property name="maximum"> + <double>1.000000000000000</double> + </property> + <property name="singleStep"> + <double>0.010000000000000</double> + </property> + </widget> + </item> + <item row="7" column="0"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>Sample rate:</string> + </property> + </widget> + </item> + <item row="9" column="0" colspan="2"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="8" column="0"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item row="5" column="0" colspan="2"> + <widget class="QCheckBox" name="publicCheckBox"> + <property name="text"> + <string>Public</string> + </property> + </widget> + </item> + <item row="7" column="1"> + <widget class="QSpinBox" name="srateSpinBox"> + <property name="suffix"> + <string>Hz</string> + </property> + <property name="minimum"> + <number>8000</number> + </property> + <property name="maximum"> + <number>96000</number> + </property> + <property name="singleStep"> + <number>100</number> + </property> + <property name="value"> + <number>44100</number> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>SettingsDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>SettingsDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/plugins/Output/shout/shoutclient.cpp b/src/plugins/Output/shout/shoutclient.cpp index 45c5d5614..cf4efbf92 100644 --- a/src/plugins/Output/shout/shoutclient.cpp +++ b/src/plugins/Output/shout/shoutclient.cpp @@ -19,6 +19,8 @@ ***************************************************************************/ #include <QTimer> +#include <QSettings> +#include <qmmp/qmmp.h> #include "shoutclient.h" ShoutClient::ShoutClient(QObject *parent) : @@ -42,19 +44,25 @@ ShoutClient::~ShoutClient() void ShoutClient::readSettings() { - shout_set_host(m_shout_conn, "127.0.0.1"); - shout_set_port(m_shout_conn, 8000); - shout_set_password(m_shout_conn, "hackme"); - shout_set_mount(m_shout_conn, "/qmmp.out"); + QSettings settings(Qmmp::configFile(), QSettings::IniFormat); + settings.beginGroup("Shout"); + shout_set_host(m_shout_conn, settings.value("host", "127.0.0.1").toString().toLatin1().constData()); + shout_set_port(m_shout_conn, settings.value("port", 8000).toInt()); + shout_set_password(m_shout_conn, settings.value("passw", "hackme").toString().toLatin1().constData()); + shout_set_mount(m_shout_conn, QString("/%1").arg(settings.value("mount", "qmmp.out").toString()). + toLatin1().constData()); shout_set_name(m_shout_conn, "qmmp"); - shout_set_user(m_shout_conn, "source"); - shout_set_public(m_shout_conn, 0); + shout_set_user(m_shout_conn, settings.value("user", "source").toString().toLatin1().constData()); + shout_set_public(m_shout_conn, settings.value("public", false).toBool() ? 1 : 0); shout_set_format(m_shout_conn, SHOUT_FORMAT_OGG); shout_set_protocol(m_shout_conn, SHOUT_PROTOCOL_HTTP); shout_set_agent(m_shout_conn, "qmmp"); shout_set_audio_info(m_shout_conn, SHOUT_AI_CHANNELS, "2"); - shout_set_audio_info(m_shout_conn, SHOUT_AI_QUALITY, "0.4"); - shout_set_audio_info(m_shout_conn, SHOUT_AI_SAMPLERATE, "44100"); + shout_set_audio_info(m_shout_conn, SHOUT_AI_QUALITY, + QString::number(settings.value("vorbis_quality", 0.8).toDouble(), 'f').toLatin1().constData()); + shout_set_audio_info(m_shout_conn, SHOUT_AI_SAMPLERATE, + QString::number(settings.value("sample_rate", 44100).toInt()).toLatin1().constData()); + settings.endGroup(); } bool ShoutClient::open() diff --git a/src/plugins/Output/shout/shoutoutput.cpp b/src/plugins/Output/shout/shoutoutput.cpp index bb0fd2bfc..d27bd81c7 100644 --- a/src/plugins/Output/shout/shoutoutput.cpp +++ b/src/plugins/Output/shout/shoutoutput.cpp @@ -19,13 +19,18 @@ ***************************************************************************/ #include <QFile> -#include <unistd.h> +#include <QSettings> +#include <qmmp/qmmp.h> #include "shoutoutput.h" ShoutOutput::ShoutOutput(ShoutClient *m) { m_client = m; - + m_soxr = 0; + m_ratio = 0; + m_soxr_buf = 0; + m_soxr_buf_frames = 0; + qsrand(time(NULL)); } ShoutOutput::~ShoutOutput() @@ -36,20 +41,33 @@ ShoutOutput::~ShoutOutput() vorbis_dsp_clear(&m_vd); vorbis_comment_clear(&m_vc); vorbis_info_clear(&m_vi); + if(m_soxr) + { + soxr_delete(m_soxr); + m_soxr = 0; + } } bool ShoutOutput::initialize(quint32 freq, ChannelMap map, Qmmp::AudioFormat) { + QSettings settings(Qmmp::configFile(), QSettings::IniFormat); + float quality = settings.value("Shout/vorbis_quality", 0.8).toFloat(); + quint32 outFreq = settings.value("Shout/sample_rate", 44100).toInt(); + + if(freq != outFreq) + { + m_soxr = soxr_create(freq, outFreq, map.size(), 0, 0, 0, 0); + m_ratio = (double)outFreq/freq; + } + vorbis_info_init(&m_vi); - vorbis_encode_init_vbr(&m_vi,2,freq,.4); + vorbis_encode_init_vbr(&m_vi,2,outFreq, quality); vorbis_comment_init(&m_vc); - //vorbis_comment_add_tag(&m_vc,"TITLE","encoder_example.c"); vorbis_analysis_init(&m_vd, &m_vi); vorbis_block_init(&m_vd,&m_vb); - qsrand(time(NULL)); ogg_stream_init(&m_os,qrand()); configure(freq, map, Qmmp::PCM_FLOAT); @@ -65,19 +83,42 @@ qint64 ShoutOutput::writeAudio(unsigned char *data, qint64 maxSize) { int chan = channels(); int frames = maxSize / chan / sizeof(float); + float *input_data = 0; + + if(m_soxr) + { + size_t required_frames = double(frames) * m_ratio * 2 + 2; + if(required_frames > m_soxr_buf_frames) + { + m_soxr_buf_frames = required_frames; + m_soxr_buf = (float *)realloc(m_soxr_buf, m_soxr_buf_frames * sizeof(float) * chan); + } + + size_t done = 0; + soxr_process(m_soxr, data, frames, 0, m_soxr_buf, m_soxr_buf_frames, &done); + input_data = m_soxr_buf; + if(done == 0) //soxr requires more data + return maxSize; + frames = done; + } + else + { + input_data = (float *)data; + } + float **buffer = vorbis_analysis_buffer(&m_vd, frames); if(chan == 1) { - memcpy(buffer[0], data, frames * sizeof(float)); - memcpy(buffer[1], data, frames * sizeof(float)); + memcpy(buffer[0], input_data, frames * sizeof(float)); + memcpy(buffer[1], input_data, frames * sizeof(float)); } else { for(int i = 0; i < frames; i++) { - buffer[0][i] = *reinterpret_cast<float *>(data + (i * chan) * sizeof(float)); - buffer[1][i] = *reinterpret_cast<float *>(data + (i * chan + 1) * sizeof(float)); + buffer[0][i] = input_data[i * chan]; + buffer[1][i] = input_data[i * chan + 1]; } } @@ -131,7 +172,6 @@ qint64 ShoutOutput::writeAudio(unsigned char *data, qint64 maxSize) if(!m_client->open()) return -1; - qsrand(time(NULL)); ogg_stream_reset(&m_os); ogg_stream_init(&m_os,qrand()); diff --git a/src/plugins/Output/shout/shoutoutput.h b/src/plugins/Output/shout/shoutoutput.h index 69f06a443..4d09a1a4a 100644 --- a/src/plugins/Output/shout/shoutoutput.h +++ b/src/plugins/Output/shout/shoutoutput.h @@ -22,6 +22,7 @@ #define SHOUTOUTPUT_H #include <vorbis/vorbisenc.h> +#include <soxr.h> #include <qmmp/output.h> #include "shoutclient.h" @@ -48,6 +49,10 @@ private: vorbis_comment m_vc; //struct that stores all the user comments vorbis_dsp_state m_vd; //central working state for the packet->PCM decoder vorbis_block m_vb; //local working space for packet->PCM decode + soxr_t m_soxr; + float *m_soxr_buf; + size_t m_soxr_buf_frames; + double m_ratio; }; #endif // SHOUTOUTPUT_H |
