- Streaming Settings Page
- Activate Streaming - Set Port - Set Bitrate
This commit is contained in:
parent
ea2de21921
commit
d2e9cb510f
|
@ -361,6 +361,7 @@ set(SOURCES
|
|||
ui/settingsdialog.cpp
|
||||
ui/settingspage.cpp
|
||||
ui/standarditemiconloader.cpp
|
||||
ui/streamingsettingspage.cpp
|
||||
ui/systemtrayicon.cpp
|
||||
ui/trackselectiondialog.cpp
|
||||
ui/windows7thumbbar.cpp
|
||||
|
@ -642,6 +643,7 @@ set(HEADERS
|
|||
ui/settingsdialog.h
|
||||
ui/settingspage.h
|
||||
ui/standarditemiconloader.h
|
||||
ui/streamingsettingspage.h
|
||||
ui/systemtrayicon.h
|
||||
ui/trackselectiondialog.h
|
||||
ui/windows7thumbbar.h
|
||||
|
@ -763,6 +765,7 @@ set(UI
|
|||
ui/organiseerrordialog.ui
|
||||
ui/playbacksettingspage.ui
|
||||
ui/settingsdialog.ui
|
||||
ui/streamingsettingspage.ui
|
||||
ui/trackselectiondialog.ui
|
||||
|
||||
widgets/equalizerslider.ui
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "podcasts/podcastbackend.h"
|
||||
#include "podcasts/podcastdownloader.h"
|
||||
#include "podcasts/podcastupdater.h"
|
||||
#include "streaming/streamserver.h"
|
||||
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
#include "internet/lastfmservice.h"
|
||||
|
@ -74,7 +75,8 @@ Application::Application(QObject* parent)
|
|||
moodbar_controller_(nullptr),
|
||||
network_remote_(nullptr),
|
||||
network_remote_helper_(nullptr),
|
||||
scrobbler_(nullptr) {
|
||||
scrobbler_(nullptr),
|
||||
stream_server_(nullptr) {
|
||||
tag_reader_client_ = new TagReaderClient(this);
|
||||
MoveToNewThread(tag_reader_client_);
|
||||
tag_reader_client_->Start();
|
||||
|
@ -114,6 +116,10 @@ Application::Application(QObject* parent)
|
|||
network_remote_ = new NetworkRemote(this);
|
||||
MoveToNewThread(network_remote_);
|
||||
|
||||
// StreamServer
|
||||
stream_server_ = new StreamServer(player_);
|
||||
stream_server_->Listen();
|
||||
|
||||
// This must be before libraray_->Init();
|
||||
// In the constructor the helper waits for the signal
|
||||
// PlaylistManagerInitialized
|
||||
|
|
|
@ -45,6 +45,7 @@ class PlaylistManager;
|
|||
class PodcastBackend;
|
||||
class PodcastUpdater;
|
||||
class Scrobbler;
|
||||
class StreamServer;
|
||||
class TagReaderClient;
|
||||
class TaskManager;
|
||||
|
||||
|
@ -88,6 +89,7 @@ class Application : public QObject {
|
|||
return network_remote_helper_;
|
||||
}
|
||||
Scrobbler* scrobbler() const { return scrobbler_; }
|
||||
StreamServer* stream_server() const { return stream_server_; }
|
||||
|
||||
LibraryBackend* library_backend() const;
|
||||
LibraryModel* library_model() const;
|
||||
|
@ -131,6 +133,7 @@ signals:
|
|||
NetworkRemote* network_remote_;
|
||||
NetworkRemoteHelper* network_remote_helper_;
|
||||
Scrobbler* scrobbler_;
|
||||
StreamServer* stream_server_;
|
||||
|
||||
QList<QObject*> objects_in_threads_;
|
||||
QList<QThread*> threads_;
|
||||
|
|
|
@ -114,8 +114,6 @@ Q_IMPORT_PLUGIN(qsqlite)
|
|||
|
||||
namespace {
|
||||
|
||||
#include "streaming/streamserver.h"
|
||||
|
||||
void LoadTranslation(const QString& prefix, const QString& path,
|
||||
const QString& language) {
|
||||
#if QT_VERSION < 0x040700
|
||||
|
@ -496,9 +494,6 @@ int main(int argc, char* argv[]) {
|
|||
SLOT(CommandlineOptionsReceived(QByteArray)));
|
||||
w.CommandlineOptionsReceived(options);
|
||||
|
||||
StreamServer stream_server(app.player());;
|
||||
stream_server.Listen();
|
||||
|
||||
int ret = a.exec();
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "streamserver.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QSettings>
|
||||
#include <QTcpSocket>
|
||||
#include <QTcpServer>
|
||||
|
||||
|
@ -13,18 +14,34 @@
|
|||
|
||||
#include <gst/gst.h>
|
||||
|
||||
const char* StreamServer::kSettingsGroup = "Streaming";
|
||||
const quint16 StreamServer::kDefaultServerPort = 8080;
|
||||
|
||||
StreamServer::StreamServer(Player* player, QObject* parent)
|
||||
: QObject(parent),
|
||||
player_(player),
|
||||
server_(new QTcpServer(this)) {
|
||||
GstEngine::InitialiseGstreamer();
|
||||
//GstEngine::InitialiseGstreamer();
|
||||
gst_init(nullptr, nullptr);
|
||||
}
|
||||
|
||||
void StreamServer::Listen(quint16 port) {
|
||||
server_->listen(QHostAddress::LocalHost, port);
|
||||
void StreamServer::Listen() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
|
||||
// Streaming activated?
|
||||
if (!s.value("use_streaming", false).toBool()) {
|
||||
return;
|
||||
}
|
||||
|
||||
server_->listen(QHostAddress::LocalHost, s.value("port", kDefaultServerPort).toInt());
|
||||
connect(server_, SIGNAL(newConnection()), SLOT(AcceptConnection()));
|
||||
}
|
||||
|
||||
void StreamServer::StopListening() {
|
||||
server_->close();
|
||||
}
|
||||
|
||||
void StreamServer::AcceptConnection() {
|
||||
QTcpSocket* socket = server_->nextPendingConnection();
|
||||
QByteArray buffer;
|
||||
|
@ -60,7 +77,7 @@ static GstBusSyncReply BusCallbackSync(GstBus*, GstMessage* msg, gpointer data)
|
|||
GST_OBJECT_NAME(msg->src), err->message);
|
||||
g_error_free(err);
|
||||
g_free(dbg_info);
|
||||
socket->deleteLater();
|
||||
socket->close();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -77,7 +94,6 @@ void StreamServer::ReadyRead(QTcpSocket* socket, QByteArray buffer) {
|
|||
if (socket->atEnd() || buffer.endsWith("\r\n\r\n")) {
|
||||
QByteArray response = ParseRequest(buffer);
|
||||
qLog(Debug) << response;
|
||||
|
||||
socket->write("HTTP/1.0 200 OK\r\n");
|
||||
socket->write("Content-type: application/ogg\r\n");
|
||||
socket->write("Connection: close\r\n");
|
||||
|
@ -86,9 +102,9 @@ void StreamServer::ReadyRead(QTcpSocket* socket, QByteArray buffer) {
|
|||
|
||||
QUrl url(QString::fromUtf8(response), QUrl::StrictMode);
|
||||
UrlHandler* handler = player_->HandlerForUrl(url);
|
||||
connect(handler, SIGNAL(AsyncLoadComplete(const UrlHandler::LoadResult&)),
|
||||
SLOT(AsyncLoadComplete(const UrlHandler::LoadResult&)), Qt::UniqueConnection);
|
||||
if (handler) {
|
||||
connect(handler, SIGNAL(AsyncLoadComplete(const UrlHandler::LoadResult&)),
|
||||
SLOT(AsyncLoadComplete(const UrlHandler::LoadResult&)), Qt::UniqueConnection);
|
||||
UrlHandler::LoadResult result = handler->StartLoading(url);
|
||||
if (result.type_ == UrlHandler::LoadResult::TrackAvailable) {
|
||||
SendStream(result.media_url_, socket);
|
||||
|
@ -118,6 +134,7 @@ void StreamServer::SendStream(const QUrl& url, QTcpSocket* socket) {
|
|||
decodebin, audioconvert, audioresample, vorbisenc, oggmux, fdsink,
|
||||
NULL);
|
||||
|
||||
g_object_set(vorbisenc, "bitrate", getBitrate(), NULL);
|
||||
g_object_set(decodebin, "uri", url.toString().toUtf8().constData(), NULL);
|
||||
g_object_set(fdsink, "fd", socket->socketDescriptor(), NULL);
|
||||
|
||||
|
@ -143,3 +160,9 @@ void StreamServer::AsyncLoadComplete(const UrlHandler::LoadResult& result) {
|
|||
QTcpSocket* socket = sockets_.take(result.original_url_);
|
||||
SendStream(result.media_url_, socket);
|
||||
}
|
||||
|
||||
int StreamServer::getBitrate() {
|
||||
QSettings s;
|
||||
s.beginGroup(kSettingsGroup);
|
||||
return s.value("bitrate", 128).toInt() * 1000;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef STREAMSERVER_H
|
||||
#define STREAMSERVER_h
|
||||
#define STREAMSERVER_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QObject>
|
||||
|
@ -15,8 +15,12 @@ class QTcpSocket;
|
|||
class StreamServer : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
StreamServer(Player* player, QObject* parent = 0);
|
||||
void Listen(quint16 port = 8080);
|
||||
static const char* kSettingsGroup;
|
||||
static const quint16 kDefaultServerPort;
|
||||
|
||||
StreamServer(Player* player, QObject* parent = nullptr);
|
||||
void Listen();
|
||||
void StopListening();
|
||||
|
||||
private slots:
|
||||
void AcceptConnection();
|
||||
|
@ -26,6 +30,7 @@ class StreamServer : public QObject {
|
|||
private:
|
||||
QByteArray ParseRequest(const QByteArray& data);
|
||||
void SendStream(const QUrl& url, QTcpSocket* socket);
|
||||
int getBitrate();
|
||||
|
||||
Player* player_;
|
||||
QTcpServer* server_;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "notificationssettingspage.h"
|
||||
#include "mainwindow.h"
|
||||
#include "settingsdialog.h"
|
||||
#include "streamingsettingspage.h"
|
||||
#include "core/application.h"
|
||||
#include "core/backgroundstreams.h"
|
||||
#include "core/logging.h"
|
||||
|
@ -137,10 +138,14 @@ SettingsDialog::SettingsDialog(Application* app, BackgroundStreams* streams,
|
|||
AddPage(Page_Library, new LibrarySettingsPage(this), general);
|
||||
AddPage(Page_Proxy, new NetworkProxySettingsPage(this), general);
|
||||
AddPage(Page_Transcoding, new TranscoderSettingsPage(this), general);
|
||||
AddPage(Page_NetworkRemote, new NetworkRemoteSettingsPage(this), general);
|
||||
|
||||
QTreeWidgetItem* network = AddCategory(tr("Interfaces"));
|
||||
|
||||
AddPage(Page_NetworkRemote, new NetworkRemoteSettingsPage(this), network);
|
||||
AddPage(Page_Streaming, new StreamingSettingsPage(this), network);
|
||||
|
||||
#ifdef HAVE_WIIMOTEDEV
|
||||
AddPage(Page_Wiimotedev, new WiimoteSettingsPage(this), general);
|
||||
AddPage(Page_Wiimotedev, new WiimoteSettingsPage(this), network);
|
||||
#endif
|
||||
|
||||
// User interface
|
||||
|
|
|
@ -65,6 +65,7 @@ class SettingsDialog : public QDialog {
|
|||
Page_GlobalSearch,
|
||||
Page_Appearance,
|
||||
Page_NetworkRemote,
|
||||
Page_Streaming,
|
||||
Page_Notifications,
|
||||
Page_Library,
|
||||
Page_Lastfm,
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/application.h"
|
||||
#include "iconloader.h"
|
||||
#include "streamingsettingspage.h"
|
||||
#include "ui_streamingsettingspage.h"
|
||||
#include "streaming/streamserver.h"
|
||||
#include "settingsdialog.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QHostInfo>
|
||||
|
||||
StreamingSettingsPage::StreamingSettingsPage(SettingsDialog* dialog)
|
||||
: SettingsPage(dialog), ui_(new Ui_StreamingSettingsPage) {
|
||||
ui_->setupUi(this);
|
||||
setWindowIcon(IconLoader::Load("ipodtouchicon"));
|
||||
}
|
||||
|
||||
StreamingSettingsPage::~StreamingSettingsPage() { delete ui_; }
|
||||
|
||||
void StreamingSettingsPage::Load() {
|
||||
QSettings s;
|
||||
|
||||
s.beginGroup(StreamServer::kSettingsGroup);
|
||||
|
||||
ui_->use_streaming->setChecked(s.value("use_streaming").toBool());
|
||||
ui_->stream_port->setValue(
|
||||
s.value("port", StreamServer::kDefaultServerPort).toInt());
|
||||
|
||||
ui_->bitrate_box->setValue(s.value("bitrate", 128).toInt());
|
||||
|
||||
s.endGroup();
|
||||
}
|
||||
|
||||
void StreamingSettingsPage::Save() {
|
||||
QSettings s;
|
||||
|
||||
s.beginGroup(StreamServer::kSettingsGroup);
|
||||
bool wasStreaming = s.value("use_streaming", false).toBool();
|
||||
|
||||
s.setValue("use_streaming", ui_->use_streaming->isChecked());
|
||||
s.setValue("port", ui_->stream_port->value());
|
||||
s.setValue("bitrate", ui_->bitrate_box->value());
|
||||
|
||||
s.endGroup();
|
||||
|
||||
if (wasStreaming != ui_->use_streaming->isChecked()) {
|
||||
if (ui_->use_streaming->isChecked())
|
||||
dialog()->app()->stream_server()->Listen();
|
||||
else
|
||||
dialog()->app()->stream_server()->StopListening();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef STREAMINGSETTINGSPAGE_H
|
||||
#define STREAMINGSETTINGSPAGE_H
|
||||
|
||||
#include "settingspage.h"
|
||||
|
||||
class Ui_StreamingSettingsPage;
|
||||
|
||||
class StreamingSettingsPage : public SettingsPage {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
StreamingSettingsPage(SettingsDialog* dialog);
|
||||
~StreamingSettingsPage();
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
private:
|
||||
Ui_StreamingSettingsPage* ui_;
|
||||
};
|
||||
|
||||
#endif // STREAMINGSETTINGSPAGE_H
|
|
@ -0,0 +1,190 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>StreamingSettingsPage</class>
|
||||
<widget class="QWidget" name="StreamingSettingsPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>385</width>
|
||||
<height>528</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Streaming</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="use_streaming">
|
||||
<property name="text">
|
||||
<string>Active steaming</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>This enables HTTP streaming. A client can stream any Clementine URL except for Spotify.</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="use_stream_container_2">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_stream_port">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>171</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="stream_port">
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8080</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Bitrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QSlider" name="bitrate_slider">
|
||||
<property name="maximum">
|
||||
<number>250</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="bitrate_box">
|
||||
<property name="suffix">
|
||||
<string> kBps</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>250</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>128</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<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>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>use_streaming</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>use_stream_container_2</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>59</x>
|
||||
<y>22</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>57</x>
|
||||
<y>43</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>bitrate_box</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_slider</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>325</x>
|
||||
<y>147</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>241</x>
|
||||
<y>146</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>bitrate_slider</sender>
|
||||
<signal>valueChanged(int)</signal>
|
||||
<receiver>bitrate_box</receiver>
|
||||
<slot>setValue(int)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>241</x>
|
||||
<y>146</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>325</x>
|
||||
<y>147</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Loading…
Reference in New Issue