source: smplayer/trunk/src/chromecast.cpp@ 188

Last change on this file since 188 was 188, checked in by Silvan Scherrer, 8 years ago

SMPlayer: update trunk to version 17.1.0

File size: 7.3 KB
Line 
1/* smplayer, GUI front-end for mplayer.
2 Copyright (C) 2006-2017 Ricardo Villalba <rvm@users.sourceforge.net>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17*/
18
19#include "chromecast.h"
20#include "links.h"
21#include <QUrl>
22#include <QFileInfo>
23#include <QDesktopServices>
24#include <QNetworkInterface>
25#include <QProcess>
26#include <QDir>
27#include <QSettings>
28#include <QDebug>
29#include "helper.h"
30
31//#define CHROMECAST_USE_SERVER_WEBFSD
32//#define CHROMECAST_USE_SERVER_SIMPLE_WEB_SERVER
33
34#if !defined(CHROMECAST_USE_SERVER_WEBFSD) && !defined(CHROMECAST_USE_SERVER_SIMPLE_WEB_SERVER)
35 #ifdef Q_OS_WIN
36 #define CHROMECAST_USE_SERVER_SIMPLE_WEB_SERVER
37 #else
38 #define CHROMECAST_USE_SERVER_WEBFSD
39 #endif
40#endif
41
42#define SERVE_FILE_DIR_ONLY
43
44Chromecast * Chromecast::instance_obj = 0;
45
46Chromecast * Chromecast::instance() {
47 if (instance_obj == 0) {
48 instance_obj = new Chromecast();
49 }
50 return instance_obj;
51}
52
53void Chromecast::deleteInstance() {
54 if (instance_obj) {
55 delete instance_obj;
56 instance_obj = 0;
57 }
58}
59
60
61Chromecast::Chromecast(QObject * parent)
62 : QObject(parent)
63 , server_process(0)
64 , settings(0)
65 , server_port(8010)
66 , directory_listing(true)
67 , server_needs_restart(false)
68{
69}
70
71Chromecast::~Chromecast() {
72 if (server_process) {
73 stopServer();
74 }
75 saveSettings();
76}
77
78void Chromecast::openStream(const QString & url, const QString & title) {
79 QDesktopServices::openUrl(QUrl(URL_CHROMECAST "/?title=" + title.toUtf8().toBase64() +
80 "&url=" + url.toUtf8().toBase64()));
81}
82
83void Chromecast::openLocal(const QString & file, const QString & title) {
84 qDebug() << "Chromecast::openLocal:" << file;
85
86 QFileInfo fi(file);
87 QString dir = fi.absolutePath();
88 QString filename = fi.fileName();
89
90 qDebug() << "Chromecast::openLocal: dir:" << dir;
91 qDebug() << "Chromecast::openLocal: filename:" << filename;
92
93 QString local_address = localAddress();
94 if (local_address.isEmpty()) local_address = findLocalAddress();
95 qDebug() << "Chromecast::openLocal: chosen address:" << local_address;
96
97 if (!local_address.isEmpty()) {
98 // Run web server
99
100 #ifdef SERVE_FILE_DIR_ONLY
101 startServer(dir);
102 QString url = "http://" + local_address + ":" + QString::number(server_port) + "/" + filename;
103 #else
104 QString root = QDir::rootPath();
105 startServer(root);
106 QString abs_filename = fi.absoluteFilePath();
107 if (abs_filename.startsWith(root)) {
108 abs_filename = abs_filename.mid(root.length());
109 }
110 QString url = "http://" + local_address + ":" + QString::number(server_port) + "/" + abs_filename;
111 #endif
112
113 qDebug() << "Chromecast::openLocal: url:" << url;
114
115 #if 1
116 QDesktopServices::openUrl(QUrl(URL_CHROMECAST "/?title=" + title.toUtf8().toBase64() +
117 "&url=" + url.toUtf8().toBase64()));
118 #endif
119 }
120}
121
122QStringList Chromecast::localAddresses() {
123 QStringList l;
124
125 foreach(const QHostAddress &address, QNetworkInterface::allAddresses()) {
126 if (address.protocol() == QAbstractSocket::IPv4Protocol && address != QHostAddress(QHostAddress::LocalHost)) {
127 l << address.toString();
128 }
129 }
130
131 return l;
132}
133
134QString Chromecast::findLocalAddress() {
135 QString local_address;
136
137 QStringList addresses = localAddresses();
138 qDebug() << "Chromecast::defaultLocalAddress: all IPv4 addresses:" << addresses;
139
140 foreach(QString address, addresses) {
141 //qDebug() << "Chromecast::defaultLocalAddress: address:" << address;
142 if (address.startsWith("192.") && !address.endsWith(".1")) {
143 local_address = address;
144 break;
145 }
146 }
147
148 if (local_address.isEmpty() && !addresses.isEmpty()) local_address = addresses[0];
149 return local_address;
150}
151
152void Chromecast::startServer(QString doc_root) {
153 qDebug("Chromecast::startServer");
154
155 static QString last_doc_root;
156
157 if (server_process == 0) {
158 server_process = new QProcess(this);
159 server_process->setProcessChannelMode( QProcess::MergedChannels );
160 connect(server_process, SIGNAL(readyReadStandardOutput()), this, SLOT(readProcessOutput()));
161 connect(server_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(processFinished(int, QProcess::ExitStatus)));
162 connect(server_process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
163 }
164
165 if (server_process->state() == QProcess::Running) {
166 if (!server_needs_restart && last_doc_root == doc_root) {
167 return;
168 } else {
169 stopServer();
170 }
171 }
172
173 QString prog;
174 QStringList args;
175
176#if defined(Q_OS_WIN) && defined(SERVE_FILE_DIR_ONLY)
177 doc_root = Helper::shortPathName(doc_root);
178#endif
179
180#if defined(CHROMECAST_USE_SERVER_WEBFSD)
181 prog = "webfsd";
182 args << "-F" << "-d" << "-4" << "-p" << QString::number(server_port) << "-r" << doc_root;
183 if (!directoryListing()) args << "-j";
184#elif defined(CHROMECAST_USE_SERVER_SIMPLE_WEB_SERVER)
185 prog = "simple_web_server";
186 #ifdef Q_OS_WIN
187 prog += ".exe";
188 #endif
189 args << "-p" << QString::number(server_port) << "-r" << doc_root;
190 if (!directoryListing()) args << "-j";
191#else
192 #error "No server defined"
193#endif
194
195 {
196 QString command = prog + " " + args.join(" ");
197 qDebug() << "Chromecast::startServer: command:" << command;
198 }
199
200 server_process->start(prog, args);
201
202 last_doc_root = doc_root;
203 server_needs_restart = false;
204}
205
206
207void Chromecast::stopServer() {
208 qDebug("Chromecast::stopServer");
209
210 if (server_process) {
211 server_process->terminate();
212 if (!server_process->waitForFinished(5000)) {
213 server_process->kill();
214 server_process->waitForFinished();
215 }
216 }
217}
218
219// Slots
220void Chromecast::readProcessOutput() {
221 QByteArray line;
222 while (server_process->canReadLine()) {
223 line = server_process->readLine().trimmed();
224 qDebug() << "Chromecast::readProcessOutput: line:" << line;
225 }
226}
227
228void Chromecast::processFinished(int exit_code, QProcess::ExitStatus exit_status) {
229 qDebug() << "Chromecast::processFinished: exit_code:" << exit_code << "exit_status:" << exit_status;
230}
231
232void Chromecast::processError(QProcess::ProcessError error) {
233 qDebug() << "Chromecast::processError:" << error;
234 if (error == QProcess::FailedToStart) {
235 qDebug("Chromecast::processError: process failed to start");
236 }
237}
238
239void Chromecast::loadSettings() {
240 qDebug("Chromecast::loadSettings");
241
242 if (settings) {
243 settings->beginGroup("chromecast/server");
244 setServerPort(settings->value("port", serverPort()).toInt());
245 setLocalAddress(settings->value("local_address", localAddress()).toString());
246 setDirectoryListing(settings->value("directory_listing", directoryListing()).toBool());
247 settings->endGroup();
248 }
249}
250
251void Chromecast::saveSettings() {
252 qDebug("Chromecast::saveSettings");
253
254 if (settings) {
255 settings->beginGroup("chromecast/server");
256 settings->setValue("port", serverPort());
257 settings->setValue("local_address", localAddress());
258 settings->setValue("directory_listing", directoryListing());
259 settings->endGroup();
260 }
261}
262
263#include "moc_chromecast.cpp"
Note: See TracBrowser for help on using the repository browser.