More remote work. Clementine now requires QJson.
This commit is contained in:
parent
d4d7f19fab
commit
c9d5b8100b
|
@ -57,6 +57,7 @@ pkg_check_modules(PLIST libplist)
|
||||||
pkg_check_modules(USBMUXD libusbmuxd)
|
pkg_check_modules(USBMUXD libusbmuxd)
|
||||||
pkg_check_modules(LIBMTP libmtp>=1.0)
|
pkg_check_modules(LIBMTP libmtp>=1.0)
|
||||||
pkg_check_modules(INDICATEQT indicate-qt)
|
pkg_check_modules(INDICATEQT indicate-qt)
|
||||||
|
pkg_check_modules(QJSON QJson)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
|
@ -111,6 +112,7 @@ include_directories(${GLIB_INCLUDE_DIRS})
|
||||||
include_directories(${GLIBCONFIG_INCLUDE_DIRS})
|
include_directories(${GLIBCONFIG_INCLUDE_DIRS})
|
||||||
include_directories(${LIBXML_INCLUDE_DIRS})
|
include_directories(${LIBXML_INCLUDE_DIRS})
|
||||||
include_directories("3rdparty/universalchardet")
|
include_directories("3rdparty/universalchardet")
|
||||||
|
include_directories(${QJSON_INCLUDE_DIRS})
|
||||||
|
|
||||||
# Remove GLU and GL from the link line - they're not really required
|
# Remove GLU and GL from the link line - they're not really required
|
||||||
# and don't exist on my mingw toolchain
|
# and don't exist on my mingw toolchain
|
||||||
|
|
|
@ -814,6 +814,7 @@ target_link_libraries(clementine_lib
|
||||||
${QTSINGLECOREAPPLICATION_LIBRARIES}
|
${QTSINGLECOREAPPLICATION_LIBRARIES}
|
||||||
${QTIOCOMPRESSOR_LIBRARIES}
|
${QTIOCOMPRESSOR_LIBRARIES}
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
${QJSON_LIBRARIES}
|
||||||
dl
|
dl
|
||||||
z
|
z
|
||||||
)
|
)
|
||||||
|
|
|
@ -319,10 +319,11 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
Zeroconf* zeroconf = Zeroconf::GetZeroconf();
|
Zeroconf* zeroconf = Zeroconf::GetZeroconf();
|
||||||
if (zeroconf) {
|
if (zeroconf) {
|
||||||
HttpServer* server = new HttpServer;
|
HttpServer* server = new HttpServer(&player);
|
||||||
server->Listen(QHostAddress::Any, 12345);
|
int port = 12345;
|
||||||
|
while (!server->Listen(QHostAddress::Any, port)) { ++port; }
|
||||||
|
|
||||||
zeroconf->Publish("local", "_clementine._tcp", "Clementine", 12345);
|
zeroconf->Publish("local", "_clementine._tcp", "Clementine", port);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Window
|
// Window
|
||||||
|
|
|
@ -1,13 +1,27 @@
|
||||||
#include "httpconnection.h"
|
#include "httpconnection.h"
|
||||||
|
|
||||||
|
#include <QBuffer>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QTcpSocket>
|
#include <QTcpSocket>
|
||||||
|
|
||||||
HttpConnection::HttpConnection(QTcpSocket* socket)
|
#include <qjson/serializer.h>
|
||||||
|
|
||||||
|
#include "core/player.h"
|
||||||
|
#include "playlist/playlistitem.h"
|
||||||
|
|
||||||
|
HttpConnection::HttpConnection(Player* player, QTcpSocket* socket)
|
||||||
: QObject(socket),
|
: QObject(socket),
|
||||||
socket_(socket),
|
socket_(socket),
|
||||||
state_(WaitingForRequest) {
|
state_(WaitingForRequest),
|
||||||
|
player_(player),
|
||||||
|
cover_loader_(new AlbumCoverLoader(this)) {
|
||||||
connect(socket_, SIGNAL(readyRead()), SLOT(ReadyRead()));
|
connect(socket_, SIGNAL(readyRead()), SLOT(ReadyRead()));
|
||||||
|
connect(cover_loader_, SIGNAL(ImageLoaded(quint64, const QImage&)),
|
||||||
|
SLOT(ImageReady(quint64, const QImage&)));
|
||||||
|
connect(socket_, SIGNAL(disconnected()), socket_, SLOT(deleteLater()));
|
||||||
|
|
||||||
|
cover_loader_->SetDesiredHeight(400);
|
||||||
|
cover_loader_->SetScaleOutputImage(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::ReadyRead() {
|
void HttpConnection::ReadyRead() {
|
||||||
|
@ -40,6 +54,7 @@ void HttpConnection::ReadyRead() {
|
||||||
|
|
||||||
if (state_ == Error) {
|
if (state_ == Error) {
|
||||||
socket_->close();
|
socket_->close();
|
||||||
|
socket_->deleteLater();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,9 +79,64 @@ bool HttpConnection::ParseRequest(const QString& line) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpConnection::DoRequest() {
|
void HttpConnection::DoRequest() {
|
||||||
|
PlaylistItemPtr current_item = player_->GetCurrentItem();
|
||||||
|
if (current_item) {
|
||||||
|
quint64 id = cover_loader_->LoadImageAsync(current_item->Metadata());
|
||||||
|
pending_tasks_[id] = current_item->Metadata();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SendHeaders();
|
||||||
|
|
||||||
|
QVariantMap state = GetState();
|
||||||
|
|
||||||
|
QJson::Serializer serializer;
|
||||||
|
QString output = serializer.serialize(state);
|
||||||
|
socket_->write(output.toUtf8());
|
||||||
|
|
||||||
|
socket_->disconnectFromHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpConnection::ImageReady(quint64 id, const QImage& image) {
|
||||||
|
Song song = pending_tasks_.take(id);
|
||||||
|
SendSongInfo(song, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpConnection::SendHeaders() {
|
||||||
socket_->write("HTTP/1.0 200 OK\r\n");
|
socket_->write("HTTP/1.0 200 OK\r\n");
|
||||||
socket_->write("Content-type: application/json\r\n");
|
socket_->write("Content-type: application/json\r\n");
|
||||||
socket_->write("\r\n");
|
socket_->write("\r\n");
|
||||||
socket_->write("{content:'Hello World!'}");
|
}
|
||||||
socket_->close();
|
|
||||||
|
QVariantMap HttpConnection::GetState() {
|
||||||
|
QVariantMap json;
|
||||||
|
json.insert("state", player_->GetState());
|
||||||
|
json.insert("volume", player_->GetVolume());
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpConnection::SendSongInfo(Song song, const QImage& cover) {
|
||||||
|
SendHeaders();
|
||||||
|
|
||||||
|
QVariantMap metadata;
|
||||||
|
metadata.insert("title", song.title());
|
||||||
|
metadata.insert("album", song.album());
|
||||||
|
metadata.insert("artist", song.artist());
|
||||||
|
if (!cover.isNull()) {
|
||||||
|
QByteArray cover_data;
|
||||||
|
{
|
||||||
|
QBuffer cover_buffer(&cover_data);
|
||||||
|
cover_buffer.open(QIODevice::WriteOnly);
|
||||||
|
cover.save(&cover_buffer, "PNG");
|
||||||
|
}
|
||||||
|
metadata.insert("cover", cover_data.toBase64());
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap state = GetState();
|
||||||
|
state.insert("song", metadata);
|
||||||
|
|
||||||
|
QJson::Serializer serializer;
|
||||||
|
QString output = serializer.serialize(state);
|
||||||
|
socket_->write(output.toUtf8());
|
||||||
|
socket_->disconnectFromHost();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,20 +3,30 @@
|
||||||
|
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
#include "core/song.h"
|
||||||
|
|
||||||
class QTcpSocket;
|
class QTcpSocket;
|
||||||
|
|
||||||
|
class AlbumCoverLoader;
|
||||||
|
class Player;
|
||||||
|
|
||||||
class HttpConnection : public QObject {
|
class HttpConnection : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
HttpConnection(QTcpSocket* sock);
|
HttpConnection(Player* player, QTcpSocket* sock);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ReadyRead();
|
void ReadyRead();
|
||||||
|
void ImageReady(quint64 id, const QImage& image);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DoRequest();
|
void DoRequest();
|
||||||
bool ParseRequest(const QString& line);
|
bool ParseRequest(const QString& line);
|
||||||
|
void SendHeaders();
|
||||||
|
QVariantMap GetState();
|
||||||
|
void SendSongInfo(Song song, const QImage& cover);
|
||||||
|
|
||||||
QTcpSocket* socket_;
|
QTcpSocket* socket_;
|
||||||
|
|
||||||
|
@ -30,6 +40,11 @@ class HttpConnection : public QObject {
|
||||||
|
|
||||||
QNetworkAccessManager::Operation method_;
|
QNetworkAccessManager::Operation method_;
|
||||||
QString path_;
|
QString path_;
|
||||||
|
|
||||||
|
Player* player_;
|
||||||
|
AlbumCoverLoader* cover_loader_;
|
||||||
|
|
||||||
|
QMap<quint64, Song> pending_tasks_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
|
|
||||||
#include "httpconnection.h"
|
#include "httpconnection.h"
|
||||||
|
|
||||||
HttpServer::HttpServer(QObject* parent)
|
HttpServer::HttpServer(Player* player, QObject* parent)
|
||||||
: QObject(parent) {
|
: QObject(parent),
|
||||||
|
player_(player) {
|
||||||
connect(&server_, SIGNAL(newConnection()), SLOT(NewConnection()));
|
connect(&server_, SIGNAL(newConnection()), SLOT(NewConnection()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,5 +18,5 @@ bool HttpServer::Listen(const QHostAddress& addr, quint16 port) {
|
||||||
void HttpServer::NewConnection() {
|
void HttpServer::NewConnection() {
|
||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
QTcpSocket* socket = server_.nextPendingConnection();
|
QTcpSocket* socket = server_.nextPendingConnection();
|
||||||
new HttpConnection(socket);
|
new HttpConnection(player_, socket);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
|
|
||||||
#include <QTcpServer>
|
#include <QTcpServer>
|
||||||
|
|
||||||
|
class Player;
|
||||||
|
|
||||||
class HttpServer : public QObject {
|
class HttpServer : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
HttpServer(QObject* parent = 0);
|
HttpServer(Player* player, QObject* parent = 0);
|
||||||
bool Listen(const QHostAddress& addr, quint16 port);
|
bool Listen(const QHostAddress& addr, quint16 port);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
@ -14,6 +16,8 @@ class HttpServer : public QObject {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTcpServer server_;
|
QTcpServer server_;
|
||||||
|
|
||||||
|
Player* player_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue