Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit e3f22376 authored by Camilo Higuita's avatar Camilo Higuita

intial work on Linking mobile with desktop

parent da415dc4
......@@ -64,7 +64,8 @@ SOURCES += main.cpp \
db/conthread.cpp \
services/web/babeit.cpp \
utils/babeconsole.cpp \
services/local/youtubedl.cpp
services/local/youtubedl.cpp \
services/local/linking.cpp
RESOURCES += qml.qrc \
......@@ -120,7 +121,8 @@ HEADERS += \
services/web/babeit.h \
utils/babeconsole.h \
utils/singleton.h \
services/local/youtubedl.h
services/local/youtubedl.h \
services/local/linking.h
#TAGLIB
......
......@@ -5,6 +5,7 @@
#include <QVariantList>
#include "utils/bae.h"
#include "db/collectionDB.h"
#include "services/local/linking.h"
#if (defined (Q_OS_LINUX) && !defined (Q_OS_ANDROID))
class Notify;
......@@ -16,144 +17,141 @@ class CollectionDB;
class Pulpo;
class BabeSettings;
class ConThread;
using namespace BAE;
class Babe : public CollectionDB
{
Q_OBJECT
public:
explicit Babe(QObject *parent = nullptr);
~Babe();
Q_OBJECT
public:
explicit Babe(QObject *parent = nullptr);
~Babe();
BabeSettings *settings;
Linking link;
enum class HINT : uint
{
BIG_ALBUM = 200,
MEDIUM_ALBUM = 120,
SMALL_ALBUM = 80
};
Q_ENUM(HINT)
// Q_INVOKABLE void runPy();
// Q_INVOKABLE void runPy();
/* DATABASE INTERFACES */
/* DATABASE INTERFACES */
Q_INVOKABLE QVariantList get(const QString &queryTxt);
Q_INVOKABLE QVariantList getList(const QStringList &urls);
Q_INVOKABLE QVariantList get(const QString &queryTxt);
Q_INVOKABLE QVariantList getList(const QStringList &urls);
Q_INVOKABLE void set(const QString &table, const QVariantList &wheres);
Q_INVOKABLE void set(const QString &table, const QVariantList &wheres);
Q_INVOKABLE void trackPlaylist(const QStringList &urls, const QString &playlist);
Q_INVOKABLE void trackLyrics(const QString &url);
Q_INVOKABLE bool trackBabe(const QString &path);
Q_INVOKABLE QString artistArt(const QString &artist);
Q_INVOKABLE QString albumArt(const QString &album, const QString &artist);
Q_INVOKABLE QString artistWiki(const QString &artist);
Q_INVOKABLE QString albumWiki(const QString &album, const QString &artist);
Q_INVOKABLE void trackPlaylist(const QStringList &urls, const QString &playlist);
Q_INVOKABLE void trackLyrics(const QString &url);
Q_INVOKABLE bool trackBabe(const QString &path);
Q_INVOKABLE QString artistArt(const QString &artist);
Q_INVOKABLE QString albumArt(const QString &album, const QString &artist);
Q_INVOKABLE QString artistWiki(const QString &artist);
Q_INVOKABLE QString albumWiki(const QString &album, const QString &artist);
Q_INVOKABLE bool babeTrack(const QString &path, const bool &value);
Q_INVOKABLE bool babeTrack(const QString &path, const bool &value);
/* SETTINGS */
/* SETTINGS */
Q_INVOKABLE void scanDir(const QString &url);
Q_INVOKABLE void brainz(const bool &on);
Q_INVOKABLE bool brainzState();
Q_INVOKABLE void refreshCollection();
Q_INVOKABLE void getYoutubeTrack(const QString &message);
Q_INVOKABLE void scanDir(const QString &url);
Q_INVOKABLE void brainz(const bool &on);
Q_INVOKABLE bool brainzState();
Q_INVOKABLE void refreshCollection();
Q_INVOKABLE void getYoutubeTrack(const QString &message);
/* STATIC METHODS */
/* STATIC METHODS */
Q_INVOKABLE static void saveSetting(const QString &key, const QVariant &value, const QString &group);
Q_INVOKABLE static QVariant loadSetting(const QString &key, const QString &group, const QVariant &defaultValue);
Q_INVOKABLE static void saveSetting(const QString &key, const QVariant &value, const QString &group);
Q_INVOKABLE static QVariant loadSetting(const QString &key, const QString &group, const QVariant &defaultValue);
Q_INVOKABLE static void savePlaylist(const QStringList &list);
Q_INVOKABLE static QStringList lastPlaylist();
Q_INVOKABLE static void savePlaylist(const QStringList &list);
Q_INVOKABLE static QStringList lastPlaylist();
Q_INVOKABLE static void savePlaylistPos(const int &pos);
Q_INVOKABLE static int lastPlaylistPos();
Q_INVOKABLE static void savePlaylistPos(const int &pos);
Q_INVOKABLE static int lastPlaylistPos();
Q_INVOKABLE static bool fileExists(const QString &url);
Q_INVOKABLE static void showFolder(const QString &url);
Q_INVOKABLE static bool fileExists(const QString &url);
Q_INVOKABLE static void showFolder(const QString &url);
/*COLORS*/
Q_INVOKABLE static QString baseColor();
Q_INVOKABLE static QString darkColor();
Q_INVOKABLE static QString backgroundColor();
Q_INVOKABLE static QString foregroundColor();
Q_INVOKABLE static QString textColor();
Q_INVOKABLE static QString highlightColor();
Q_INVOKABLE static QString highlightTextColor();
Q_INVOKABLE static QString midColor();
Q_INVOKABLE static QString midLightColor();
Q_INVOKABLE static QString shadowColor();
Q_INVOKABLE static QString altColor();
Q_INVOKABLE static QString babeColor();
Q_INVOKABLE static QString babeAltColor();
/*COLORS*/
Q_INVOKABLE static QString baseColor();
Q_INVOKABLE static QString darkColor();
Q_INVOKABLE static QString backgroundColor();
Q_INVOKABLE static QString foregroundColor();
Q_INVOKABLE static QString textColor();
Q_INVOKABLE static QString highlightColor();
Q_INVOKABLE static QString highlightTextColor();
Q_INVOKABLE static QString midColor();
Q_INVOKABLE static QString midLightColor();
Q_INVOKABLE static QString shadowColor();
Q_INVOKABLE static QString altColor();
Q_INVOKABLE static QString babeColor();
Q_INVOKABLE static QString babeAltColor();
/*UTILS*/
Q_INVOKABLE static bool isMobile();
Q_INVOKABLE static int screenGeometry(QString side);
Q_INVOKABLE static int cursorPos(QString axis);
/*UTILS*/
Q_INVOKABLE static bool isMobile();
Q_INVOKABLE static int screenGeometry(QString side);
Q_INVOKABLE static int cursorPos(QString axis);
Q_INVOKABLE static QString moodColor(const int &pos);
Q_INVOKABLE static QString moodColor(const int &pos);
Q_INVOKABLE static QString homeDir();
Q_INVOKABLE static QString musicDir();
Q_INVOKABLE static QString sdDir();
Q_INVOKABLE static QString homeDir();
Q_INVOKABLE static QString musicDir();
Q_INVOKABLE static QString sdDir();
Q_INVOKABLE static QVariantList getDirs(const QString &pathUrl);
Q_INVOKABLE static QVariantMap getParentDir(const QString &path);
Q_INVOKABLE static QVariantList getDirs(const QString &pathUrl);
Q_INVOKABLE static QVariantMap getParentDir(const QString &path);
Q_INVOKABLE static QStringList defaultSources();
Q_INVOKABLE static QStringList defaultSources();
static void registerTypes();
static void registerTypes();
/*USEFUL*/
Q_INVOKABLE QString loadCover(const QString &url);
Q_INVOKABLE QVariantList searchFor(const QStringList &queries);
/*USEFUL*/
Q_INVOKABLE QString loadCover(const QString &url);
Q_INVOKABLE QVariantList searchFor(const QStringList &queries);
/*KDE*/
Q_INVOKABLE static QVariantList getDevices();
Q_INVOKABLE static bool sendToDevice(const QString &name, const QString &id, const QString &url);
/*KDE*/
Q_INVOKABLE static QVariantList getDevices();
Q_INVOKABLE static bool sendToDevice(const QString &name, const QString &id, const QString &url);
Q_INVOKABLE void notify(const QString &title, const QString &body);
Q_INVOKABLE void notifySong(const QString &url);
Q_INVOKABLE void notify(const QString &title, const QString &body);
Q_INVOKABLE void notifySong(const QString &url);
/*ANDROID*/
Q_INVOKABLE static void sendText(const QString &text);
Q_INVOKABLE static void sendTrack(const QString &url);
Q_INVOKABLE static void openFile(const QString &url);
Q_INVOKABLE static void androidStatusBarColor(const QString &color);
/*ANDROID*/
Q_INVOKABLE static void sendText(const QString &text);
Q_INVOKABLE static void sendTrack(const QString &url);
Q_INVOKABLE static void openFile(const QString &url);
Q_INVOKABLE static void androidStatusBarColor(const QString &color);
public slots:
void debug(const QString &msg);
public slots:
void debug(const QString &msg);
private:
private:
BabeSettings *settings;
ConThread *thread;
ConThread *thread;
#if (defined (Q_OS_LINUX) && !defined (Q_OS_ANDROID))
Notify *nof;
Notify *nof;
#elif defined (Q_OS_ANDROID)
NotificationClient *nof;
NotificationClient *nof;
#endif
QString fetchCoverArt(DB &song);
static QVariantList transformData(const DB_LIST &dbList);
QString fetchCoverArt(DB &song);
static QVariantList transformData(const DB_LIST &dbList);
void fetchTrackLyrics(DB &song);
void fetchTrackLyrics(DB &song);
signals:
void refreshTables(int size);
void refreshTracks();
void refreshAlbums();
void refreshArtists();
void trackLyricsReady(QString lyrics, QString url);
void skipTrack();
void babeIt();
void message(QString msg);
signals:
void refreshTables(int size);
void refreshTracks();
void refreshAlbums();
void refreshArtists();
void trackLyricsReady(QString lyrics, QString url);
void skipTrack();
void babeIt();
void message(QString msg);
};
......
......@@ -8,6 +8,7 @@
#include <QLibrary>
#include <QQuickStyle>
#include <QStyleHints>
#include "services/local/linking.h"
#ifdef Q_OS_ANDROID
#include "./3rdparty/kirigami/src/kirigamiplugin.h"
#include <QtWebView/QtWebView>
......@@ -53,7 +54,6 @@ int main(int argc, char *argv[])
Babe bae;
Player player;
/* Services */
YouTube youtube;
......@@ -71,6 +71,15 @@ int main(int argc, char *argv[])
context->setContextProperty("player", &player);
context->setContextProperty("bae", &bae);
context->setContextProperty("youtube", &youtube);
context->setContextProperty("link", &bae.link);
qmlRegisterUncreatableMetaObject(
LINK::staticMetaObject, // static meta object
"Link.Codes", // import statement (can be any string)
1, 0, // major and minor version of the import
"LINK", // name in QML (does not have to match C++ name)
"Error: only enums" // error in case someone tries to create a MyNamespace object
);
#ifdef Q_OS_ANDROID
KirigamiPlugin::getInstance().registerTypes();
......
......@@ -872,4 +872,11 @@ Kirigami.ApplicationWindow
onSkipTrack: Player.nextTrack()
onBabeIt: Player.babeTrack()
}
Connections
{
target: link
onServerConReady: H.notify(deviceName, "You're now linked!")
onClientConError: H.notify("Error connecting to server")
}
}
......@@ -79,5 +79,6 @@
<file>services/web/YoutubePlayer_A.qml</file>
<file>services/web/WebView.qml</file>
<file>services/web/WebView_A.qml</file>
<file>services/local/LinkingDialog.qml</file>
</qresource>
</RCC>
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import "../../view_models/BabeDialog"
import "../../utils/Help.js" as H
BabeDialog
{
title: "Add "+ tracks.length +" tracks to..."
standardButtons: Dialog.Save | Dialog.Cancel
margins: contentMargins
onAccepted:
{
if(ipField.text === link.deviceIp())
H.notify("Error", "Please provide a different IP address")
else
{
if(nameField.text.length<1)
nameField.text = "Device1"
bae.saveSetting("LINKINGIP", ipField.text, "BABE")
link.connectTo(ipField.text, link.getPort())
}
}
ColumnLayout
{
anchors.centerIn: parent
width: parent.width*0.8
height: parent.height*0.9
spacing: c
Item
{
Layout.fillWidth: true
Layout.fillHeight: true
}
Label
{
text:qsTr("Linking allows to connect two devices on the same network. Just provide the device IP address to which you want to connect")
verticalAlignment: Qt.AlignVCenter
elide: Text.ElideRight
font.pointSize: fontSizes.medium
wrapMode: Text.Wrap
Layout.fillWidth: true
}
Item
{
Layout.fillWidth: true
Layout.fillHeight: true
}
Label
{
text: qsTr("IP Address")
verticalAlignment: Qt.AlignVCenter
elide: Text.ElideRight
font.pointSize: fontSizes.medium
Layout.fillWidth: true
}
TextField
{
id: ipField
Layout.fillWidth: true
text: bae.loadSetting("LINKINGIP", "BABE", link.getIp())
}
Label
{
text: qsTr("Device Name")
verticalAlignment: Qt.AlignVCenter
elide: Text.ElideRight
font.pointSize: fontSizes.medium
Layout.fillWidth: true
}
TextField
{
id: nameField
Layout.fillWidth: true
text: bae.loadSetting("LINKINGIP", "BABE", "").name
}
Label
{
text:qsTr("Device IP address: \n") +link.deviceIp()
verticalAlignment: Qt.AlignVCenter
elide: Text.ElideRight
font.pointSize: fontSizes.medium
Layout.fillWidth: true
}
Item
{
Layout.fillWidth: true
Layout.fillHeight: true
}
}
}
#include "linking.h"
#include "socket.h"
#include <QHostAddress>
#include <QNetworkInterface>
#include "../../utils/babeconsole.h"
#include <QSysInfo>
Linking::Linking(QObject *parent) : QObject(parent)
{
this->server = new Socket(BAE::LinkPort.toUInt(), this);
connect(this->server, &Socket::connected, this, &Linking::init);
connect(this->server, &Socket::message, [this](QString msg)
{
qDebug()<<"Reciving message in server:" << msg;
this->decode(msg);
});
connect(&client, &QWebSocket::connected, this, &Linking::onConnected);
// connect(&client, &QWebSocket::error, [this](QAbstractSocket::SocketError error)
// {
// emit this->clientConError(error);
// });
connect(&client, &QWebSocket::disconnected, this, &Linking::closed);
connect(&client, &QWebSocket::textMessageReceived, [this](QString msg)
{
qDebug()<<msg;
});
}
void Linking::init(const int &index)
{
qDebug()<<"Got connected with index"<<index;
emit this->devicesLinked();
}
void Linking::setIp(const QString &ip)
{
this->IP = ip;
}
QString Linking::getIp()
{
return this->IP;
}
QString Linking::deviceIp()
{
auto ipList = this->checkAddresses();
if(ipList.isEmpty()) return "No IP";
return ipList.first();
}
QString Linking::getPort()
{
return BAE::LinkPort;
}
void Linking::ask(LINK::CODE code, QString msg)
{
auto JSON = QString("{ %1 : %2, %3 : \"%4\" }").arg(BAE::SLANG[BAE::W::CODE],
LINK::DECODE[code],
BAE::SLANG[BAE::W::MSG],
msg);
client.sendTextMessage(JSON);
}
void Linking::decode(const QString &json)
{
QJsonParseError jsonParseError;
auto jsonResponse = QJsonDocument::fromJson(json.toUtf8(), &jsonParseError);
if (jsonParseError.error != QJsonParseError::NoError) return;
if (!jsonResponse.isObject()) return;
QJsonObject mainJsonObject(jsonResponse.object());
auto data = mainJsonObject.toVariantMap();
auto code = data.value(BAE::SLANG[BAE::W::CODE]).toInt();
auto msg = data.value(BAE::SLANG[BAE::W::MSG]).toString();
qDebug()<<code<<msg<<data;
}
void Linking::onConnected()
{
qDebug()<<"Got connected to server";
this->ask(LINK::CODE::CONNECTED, QSysInfo::prettyProductName());
}
QStringList Linking::checkAddresses()
{
QList<QHostAddress> list = QNetworkInterface::allAddresses();
QStringList res;
for(int nIter=0; nIter<list.count(); nIter++)
{
if(!list[nIter].isLoopback())
if (list[nIter].protocol() == QAbstractSocket::IPv4Protocol )
res << list[nIter].toString();
}
return res;
}
void Linking::connectTo(QString ip, QString port)
{
this->IP = ip;
if(this->IP.isEmpty()) return;
auto url = QUrl(QString("ws://"+this->IP+":"+port));
client.open(url);
qDebug()<<url<<ip<<port;
}
void Linking::handleError(QAbstractSocket::SocketError error)
{
qDebug()<<error;
}
#ifndef LINKING_H
#define LINKING_H
#include <QObject>
#include <QWebSocket>
#include "../../utils/bae.h"
#include <QMap>
class Socket;
namespace LINK
{
Q_NAMESPACE
enum CODE
{
CONNECTED = 1,
ERROR = 2,
DISCONNECTED = 3,
SEARCHFOR = 4,
};
Q_ENUM_NS(CODE);
static QMap<CODE, QString> DECODE =
{
{CODE::CONNECTED, "CONNECTED"},
{CODE::ERROR, "ERROR"},
{CODE::DISCONNECTED, "DISCONNECTED"},
{CODE::SEARCHFOR, "SEARCHFOR"}
};
}
class Linking : public QObject
{
Q_OBJECT
private:
Socket *server;
QWebSocket client;
QString IP;
public:
explicit Linking(QObject *parent = nullptr);
void init(const int &index);
Q_INVOKABLE void setIp(const QString &ip);
Q_INVOKABLE QString getIp();
Q_INVOKABLE QString deviceIp();
Q_INVOKABLE QString getPort();
Q_INVOKABLE void ask(LINK::CODE code, QString msg);
void decode(const QString &json);
void onConnected();
QStringList checkAddresses();
Q_INVOKABLE void connectTo(QString ip, QString port);
signals:
void closed();
void devicesLinked();
void serverConReady(const QString deviceName);
void clientConError(const QString &message);
public slots:
void handleError(QAbstractSocket::SocketError error);
};
#endif // LINKING_H
......@@ -6,14 +6,12 @@
QT_USE_NAMESPACE
Socket::Socket(quint16 port, QObject *parent) :
QObject(parent),
Socket::Socket(quint16 port, QObject *parent) : QObject(parent),
m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Babe Server"),
QWebSocketServer::NonSecureMode, this))
{
if (this->m_pWebSocketServer->listen(QHostAddress::Any, port))
{
qDebug() << "Babe listening on port" << port;
connect(this->m_pWebSocketServer, &QWebSocketServer::newConnection,
this, &Socket::onNewConnection);
......
......@@ -26,10 +26,11 @@
BabeSettings::BabeSettings(QObject *parent) : QObject(parent)
{
this->connection = new CollectionDB(this);
this->connection = new CollectionDB(this);
this->brainDeamon = new Brain;
this->ytFetch = new youtubedl(this);
this->babeSocket = new Socket(static_cast<quint16>(BAE::BabePort.toInt()),this);
this->babeSocket = new Socket(static_cast<quint16>(BAE::BabePort.toInt()), this);
qDebug() << "Getting collectionDB info from: " << BAE::CollectionDBPath;
qDebug() << "Getting settings info from: " << BAE::SettingPath;
......
......@@ -26,32 +26,33 @@ using namespace BAE;
class BabeSettings : public QObject
{
Q_OBJECT
public:
explicit BabeSettings(QObject *parent = nullptr);
~BabeSettings();
void checkCollectionBrainz(const bool &state);
void refreshCollection();
void fetchYoutubeTrack(const QString &message);
public slots:
void startBrainz(const bool &on, const uint &speed = BAE::SEG::THREE);
void populateDB(const QStringList &paths);
private:
FileLoader fileLoader;
CollectionDB *connection;
Brain *brainDeamon;
youtubedl *ytFetch;
Socket *babeSocket;
signals: