From ee9c989796fb6871378c79a01a8fd0d79d1ae17d Mon Sep 17 00:00:00 2001 From: EndrII <EndrIIMail@gmail.com> Date: Sun, 29 Oct 2017 14:47:36 +0300 Subject: [PATCH 01/14] sync lib header --- sync/song.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ sync/song.h | 29 +++++++++++++++++++++++++++++ sync/sync.cpp | 6 ++++++ sync/sync.h | 22 ++++++++++++++++++++++ sync/sync.pro | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 133 insertions(+) create mode 100644 sync/song.cpp create mode 100644 sync/song.h create mode 100644 sync/sync.cpp create mode 100644 sync/sync.h create mode 100644 sync/sync.pro diff --git a/sync/song.cpp b/sync/song.cpp new file mode 100644 index 0000000..2bb6ea9 --- /dev/null +++ b/sync/song.cpp @@ -0,0 +1,40 @@ +#include "song.h" +#include <QString> +#include <QByteArray> + +syncLib::SongHeader::SongHeader() +{ + this->id = 0; + this->name = ""; + this->size = 0; +} + +syncLib::SongHeader& syncLib::SongHeader::operator =(const syncLib::SongHeader& right){ + this->id = right.id; + this->name = right.name; + this->size = right.size; + return *this; +} + +bool syncLib::SongHeader::operator ==(const syncLib::SongHeader& right){ + return this->name == right.name && this->size == right.size; +} + + +syncLib::Song::Song(): + syncLib::SongHeader() +{ + source.clear(); +} + +syncLib::Song::Song(const SongHeader& from) + :syncLib::Song::Song() +{ + this->id = from.id; + this->name = from.name; + this->size = from.size; +} + +syncLib::Song::~Song(){ + source.clear(); +} diff --git a/sync/song.h b/sync/song.h new file mode 100644 index 0000000..7e931dc --- /dev/null +++ b/sync/song.h @@ -0,0 +1,29 @@ +#ifndef SONG_H +#define SONG_H +class QString; +class QByteArray; +namespace syncLib { + +class SongHeader +{ +public: + int id; + QString name; + int size; + SongHeader(); + SongHeader& operator = (const SongHeader& right); + bool operator == (const SongHeader& right); + virtual ~SongHeader(); +}; + +class Song : public SongHeader{ +private: + QByteArray source; +public: + Song(); + Song(const SongHeader& from); + ~Song(); +}; + +} +#endif // SONG_H diff --git a/sync/sync.cpp b/sync/sync.cpp new file mode 100644 index 0000000..7d22b54 --- /dev/null +++ b/sync/sync.cpp @@ -0,0 +1,6 @@ +#include "sync.h" +#include " + +Sync::Sync() +{ +} diff --git a/sync/sync.h b/sync/sync.h new file mode 100644 index 0000000..9e23056 --- /dev/null +++ b/sync/sync.h @@ -0,0 +1,22 @@ +#ifndef SYNC_H +#define SYNC_H + +class QString; +namespace syncLib { +class Song; +class Sync +{ +private: + bool save(Song song); +public: + bool Play(QString url) const; + void Pause() const; + void stop() const; + void jump() const; + Sync(); + ~Sync(); +}; +} + + +#endif // SYNC_H diff --git a/sync/sync.pro b/sync/sync.pro new file mode 100644 index 0000000..425ef3d --- /dev/null +++ b/sync/sync.pro @@ -0,0 +1,36 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2017-10-28T16:29:39 +# +#------------------------------------------------- + +QT += network multimedia + +QT -= gui + +TARGET = sync +TEMPLATE = lib +CONFIG += staticlib + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + sync.cpp \ + song.cpp + +HEADERS += \ + sync.h \ + song.h +unix { + target.path = /usr/lib + INSTALLS += target +} From d27642e821828b5cf81043431a31b6399e414790 Mon Sep 17 00:00:00 2001 From: EndrII <EndrIIMail@gmail.com> Date: Mon, 6 Nov 2017 01:33:16 +0300 Subject: [PATCH 02/14] added a class of node --- sync/node.cpp | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++ sync/node.h | 59 +++++++++++++++++++++ sync/song.cpp | 4 ++ sync/song.h | 5 +- sync/sync.cpp | 3 +- sync/sync.h | 4 +- sync/sync.pro | 6 ++- 7 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 sync/node.cpp create mode 100644 sync/node.h diff --git a/sync/node.cpp b/sync/node.cpp new file mode 100644 index 0000000..0986f1d --- /dev/null +++ b/sync/node.cpp @@ -0,0 +1,139 @@ +#include "node.h" +#include <QTcpSocket> +#include "song.h" +syncLib::package::package(){ + type = syncLib::package::t_void; + source.clear(); + playTime = 0; + playPoint = 0; +} +syncLib::package::package(const QByteArray &array): + syncLib::package::package(){ + parseFrom(array); +} +const Song& syncLib::package::getSong(){ + return source; +} + +unsigned int syncLib::package::getPlayTime(){ + return playTime; +} + +unsigned int syncLib::package::getPlayPoint(){ + return playPoint; +} + +syncLib::package::TypePackage syncLib::package::getType(){ + return type; +} + +bool syncLib::package::isValid(){ + switch (type) { + case package::t_void: + return false; + case package::t_close: + return true; + case package::t_sync: + return playTime > 0 && playPoint > 0; + case package::t_song: + return source.size > 0; + case package::t_stop: + return true; + default: + return false; + } +} + +QByteArray syncLib::package::parseTo(){ + QByteArray temp; + QDataStream stream(&temp); + temp.clear(); + if(isValid()){ + switch (type) { + case package::t_void: + break; + case package::t_close: + stream << (unsigned char)(type); + break; + case package::t_sync: + stream << (unsigned char)(type); + stream << playTime; + stream << playPoint; + break; + case package::t_song: + stream << (unsigned char)(type); + stream << source; + break; + case package::t_stop: + stream << (unsigned char)(type); + break; + default: + break; + } + return temp; + } +} + +bool syncLib::package::parseFrom(const QByteArray &array){ + type = t_void; + QDataStream stream(&array); + switch (type) { + case package::t_void: + return false; + case package::t_close: + return true; + case package::t_sync: + stream >> playTime; + stream >> playPoint; + return isValid(); + case package::t_song: + stream >> source; + return isValid(); + case package::t_stop: + return true; + default: + return isValid(); + } +} + +syncLib::Node::Node():QTcpServer(){ + connect(this,SIGNAL(acceptError(QAbstractSocket::SocketError)),SLOT(acceptError_(QAbstractSocket::SocketError))); + connect(this,SIGNAL(newConnection()),SLOT(newConnection_())); +} +void syncLib::Node::acceptError_(QTcpSocket*c){ + c->close(); + clients.removeOne(c); + emit ClientDisconnected(c); + delete c; +} +QList<QTcpSocket*>* syncLib::Node::getClients(){ + return &clients; +} +void syncLib::Node::newConnection_(){ + QTcpSocket *newClient=new QTcpSocket(nextPendingConnection()); + clients.push_back(newClient); + connect(newClient,SIGNAL(Disconnected(ETcpSocket*)),this,SLOT(acceptError_(QTcpSocket*))); + connect(newClient,SIGNAL(Message(ETcpSocket*)),this,SLOT(readData(QTcpSocket*))); + emit ClientConnected(newClient); +} +void syncLib::Node::readData(QTcpSocket *c){ + emit Message(c); +} +void syncLib::Node::WriteAll(const QByteArray &data){ + for(QTcpSocket*i:clients){ + i->Write(data); + } +} +void syncLib::Node::disconnectClient(QTcpSocket *c){ + c->getSource()->close(); + clients.removeOne(c); + delete c; +} + +syncLib::Node::~Node(){ + for(QTcpSocket *i:clients){ + i->getSource()->abort(); + delete i; + } + this->close(); +} diff --git a/sync/node.h b/sync/node.h new file mode 100644 index 0000000..822b3ca --- /dev/null +++ b/sync/node.h @@ -0,0 +1,59 @@ +#ifndef NODE_H +#define NODE_H +#include <QTcpServer> +class Song; +namespace syncLib { + + +class package +{ + enum TypePackage{ + t_void = 0x0, + t_close = 0x1, + t_sync = 0x2, + t_song = 0x4, + t_stop = 0x8 + }; +private: + TypePackage type; + Song source; + unsigned int playTime; + unsigned int playPoint; +public: + package(); + package(const QByteArray& array); + ~package(); + const Song& getSong() const; + unsigned int getPlayTime() const; + unsigned int getPlayPoint() const; + unsigned char getType() const; + bool isValid() const; + QByteArray parseTo() const; + bool parseFrom(const QByteArray& array); +}; + +class Node:public QTcpServer{ + Q_OBJECT +protected: + QList<QTcpSocket*> clients; +private slots: + void acceptError_(QTcpSocket*); + void newConnection_(); + void readData(QTcpSocket*_client); +public: + EServer(); + void WriteAll(const QByteArray&); + void disconnectClient(QTcpSocket*); + QList<QTcpSocket*>* getClients(); + ~EServer(); +signals: + void Error(QString); + void Message(QTcpSocket*); + void ClientDisconnected(QTcpSocket*); + void ClientConnected(QTcpSocket*); +}; + +} + + +#endif // NODE_H diff --git a/sync/song.cpp b/sync/song.cpp index 2bb6ea9..3f872c4 100644 --- a/sync/song.cpp +++ b/sync/song.cpp @@ -35,6 +35,10 @@ syncLib::Song::Song(const SongHeader& from) this->size = from.size; } +syncLib::Song::clear(){ + source.clear(); +} + syncLib::Song::~Song(){ source.clear(); } diff --git a/sync/song.h b/sync/song.h index 7e931dc..69eefd2 100644 --- a/sync/song.h +++ b/sync/song.h @@ -2,6 +2,7 @@ #define SONG_H class QString; class QByteArray; +//class Sync; namespace syncLib { class SongHeader @@ -22,8 +23,10 @@ private: public: Song(); Song(const SongHeader& from); + void clear(); ~Song(); -}; + friend class Sync; +}; } #endif // SONG_H diff --git a/sync/sync.cpp b/sync/sync.cpp index 7d22b54..dfcdceb 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -1,6 +1,7 @@ #include "sync.h" -#include " +#include "" Sync::Sync() { + } diff --git a/sync/sync.h b/sync/sync.h index 9e23056..efa4153 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -7,12 +7,12 @@ class Song; class Sync { private: - bool save(Song song); + bool save(const Song &song); public: bool Play(QString url) const; void Pause() const; void stop() const; - void jump() const; + void jump(const int seek) const; Sync(); ~Sync(); }; diff --git a/sync/sync.pro b/sync/sync.pro index 425ef3d..1a9d9af 100644 --- a/sync/sync.pro +++ b/sync/sync.pro @@ -25,11 +25,13 @@ DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ sync.cpp \ - song.cpp + song.cpp \ + node.cpp HEADERS += \ sync.h \ - song.h + song.h \ + node.h unix { target.path = /usr/lib INSTALLS += target From b8539d862d60f9b477daebd274cdacb6e8ca0b25 Mon Sep 17 00:00:00 2001 From: EndrII <EndrIIMail@gmail.com> Date: Mon, 6 Nov 2017 13:20:52 +0300 Subject: [PATCH 03/14] added node --- sync/node.cpp | 14 ++++++++++++++ sync/node.h | 8 ++++++++ sync/song.cpp | 33 +++++++++++++++++++++++++++++++++ sync/song.h | 8 +++++++- 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/sync/node.cpp b/sync/node.cpp index 0986f1d..42a24a2 100644 --- a/sync/node.cpp +++ b/sync/node.cpp @@ -1,11 +1,13 @@ #include "node.h" #include <QTcpSocket> #include "song.h" +#include <QDataStream> syncLib::package::package(){ type = syncLib::package::t_void; source.clear(); playTime = 0; playPoint = 0; + size = 0; } syncLib::package::package(const QByteArray &array): syncLib::package::package(){ @@ -53,19 +55,31 @@ QByteArray syncLib::package::parseTo(){ case package::t_void: break; case package::t_close: + stream << int(); stream << (unsigned char)(type); + stream.device()->seek(0); + stream << temp.size(); break; case package::t_sync: + stream << int(); stream << (unsigned char)(type); stream << playTime; stream << playPoint; + stream.device()->seek(0); + stream << temp.size(); break; case package::t_song: + stream << int(); stream << (unsigned char)(type); stream << source; + stream.device()->seek(0); + stream << temp.size(); break; case package::t_stop: + stream << int(); stream << (unsigned char)(type); + stream.device()->seek(0); + stream << temp.size(); break; default: break; diff --git a/sync/node.h b/sync/node.h index 822b3ca..8fa21f3 100644 --- a/sync/node.h +++ b/sync/node.h @@ -7,6 +7,13 @@ namespace syncLib { class package { + /*parse map */ + +/* + * 1 byle - type + * 4 byte - size of data of package (it avelable if type is t_sync or t_song) + * data +*/ enum TypePackage{ t_void = 0x0, t_close = 0x1, @@ -16,6 +23,7 @@ class package }; private: TypePackage type; + unsigned int size; Song source; unsigned int playTime; unsigned int playPoint; diff --git a/sync/song.cpp b/sync/song.cpp index 3f872c4..7e9aa0a 100644 --- a/sync/song.cpp +++ b/sync/song.cpp @@ -20,6 +20,12 @@ bool syncLib::SongHeader::operator ==(const syncLib::SongHeader& right){ return this->name == right.name && this->size == right.size; } +syncLib::SongHeader::getSize(){ + QByteArray size; + QDataStream stream(&size); + stream << id << name << this->size; + return size.size(); +} syncLib::Song::Song(): syncLib::SongHeader() @@ -27,6 +33,19 @@ syncLib::Song::Song(): source.clear(); } +friend QDataStream& operator << (QDataStream& stream, const syncLib::SongHeader& song){ + stream << song.id; + stream << song.name; + stream << song.size; + return stream; +} +friend QDataStream& operator >> (QDataStream& stream, syncLib::SongHeader& song){ + stream >> song.id; + stream >> song.name; + stream >> song.size; + return stream; +} + syncLib::Song::Song(const SongHeader& from) :syncLib::Song::Song() { @@ -42,3 +61,17 @@ syncLib::Song::clear(){ syncLib::Song::~Song(){ source.clear(); } + +syncLib::Song::getSize(){ + return syncLib::SongHeader::getSize() + source.size(); +} + +QDataStream operator << (QDataStream& stream,const syncLib::Song& song){ + stream << (syncLib::SongHeader)(*this); + stream << song.source; +} + +QDataStream operator << (QDataStream& stream, syncLib::Song& song){ + stream >> (syncLib::SongHeader)(*this); + stream >> song.source; +} diff --git a/sync/song.h b/sync/song.h index 69eefd2..dd28680 100644 --- a/sync/song.h +++ b/sync/song.h @@ -2,6 +2,7 @@ #define SONG_H class QString; class QByteArray; +class QDataStream; //class Sync; namespace syncLib { @@ -14,7 +15,10 @@ public: SongHeader(); SongHeader& operator = (const SongHeader& right); bool operator == (const SongHeader& right); + virtual unsigned int getSize(); virtual ~SongHeader(); + friend QDataStream& operator << (QDataStream& stream, const SongHeader& song); + friend QDataStream& operator >> (QDataStream& stream, SongHeader& song); }; class Song : public SongHeader{ @@ -24,8 +28,10 @@ public: Song(); Song(const SongHeader& from); void clear(); + unsigned int getSize() const; ~Song(); - + friend QDataStream& operator << (QDataStream& stream, const Song& song); + friend QDataStream& operator >> (QDataStream& stream, Song& song); friend class Sync; }; } From e99a5a7d4b2c6e3e9d9d91cc1e16a29d10ad0163 Mon Sep 17 00:00:00 2001 From: EndrII <EndrIIMail@gmail.com> Date: Thu, 9 Nov 2017 23:09:59 +0300 Subject: [PATCH 04/14] added a save method into sync --- sync/config.h | 17 ++++++++++++++++ sync/node.cpp | 21 ++++++++++++++++++++ sync/node.h | 2 ++ sync/song.cpp | 2 ++ sync/song.h | 1 - sync/sync.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++++--- sync/sync.h | 17 +++++++++++++++- sync/sync.pro | 5 +++-- 8 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 sync/config.h diff --git a/sync/config.h b/sync/config.h new file mode 100644 index 0000000..b6dca6c --- /dev/null +++ b/sync/config.h @@ -0,0 +1,17 @@ +#ifndef CONFIG_H +#define CONFIG_H + +// LIB VERSION +#define MAJOR_VERSION 0 +#define MINOR_VERSION 0 +#define REVISION_VERSION 0 + +// sqlite config +#define DATABASE_NAME "songdata.dat" +#define DATATABLE_NAME "songs" + +// network config +#define DEDAULT_PORT 1239 + + +#endif // CONFIG_H diff --git a/sync/node.cpp b/sync/node.cpp index 42a24a2..8114d8d 100644 --- a/sync/node.cpp +++ b/sync/node.cpp @@ -2,6 +2,9 @@ #include <QTcpSocket> #include "song.h" #include <QDataStream> + +#include "config.h" + syncLib::package::package(){ type = syncLib::package::t_void; source.clear(); @@ -144,6 +147,24 @@ void syncLib::Node::disconnectClient(QTcpSocket *c){ delete c; } +bool syncLib::Node::addNode(const QString &node,int port){ + + QTcpSocket *temp = new QTcpSocket; + if(temp->bind(node,port) && temp->open(QIODevice::ReadWrite)){ + clients.append(temp); + return true; + } + return false; +} + +bool syncLib::Node::addNode(QTcpSocket *node){ + if(node->isOpen()){ + clients.append(node); + return true; + } + return false; +} + syncLib::Node::~Node(){ for(QTcpSocket *i:clients){ i->getSource()->abort(); diff --git a/sync/node.h b/sync/node.h index 8fa21f3..82ff794 100644 --- a/sync/node.h +++ b/sync/node.h @@ -53,6 +53,8 @@ public: void WriteAll(const QByteArray&); void disconnectClient(QTcpSocket*); QList<QTcpSocket*>* getClients(); + bool addNode(const QString &node, int port = DEDAULT_PORT); + bool addNode(QTcpSocket* node); ~EServer(); signals: void Error(QString); diff --git a/sync/song.cpp b/sync/song.cpp index 7e9aa0a..c8acaa8 100644 --- a/sync/song.cpp +++ b/sync/song.cpp @@ -2,6 +2,8 @@ #include <QString> #include <QByteArray> +#include "config.h" + syncLib::SongHeader::SongHeader() { this->id = 0; diff --git a/sync/song.h b/sync/song.h index dd28680..a333a60 100644 --- a/sync/song.h +++ b/sync/song.h @@ -3,7 +3,6 @@ class QString; class QByteArray; class QDataStream; -//class Sync; namespace syncLib { class SongHeader diff --git a/sync/sync.cpp b/sync/sync.cpp index dfcdceb..91a4e46 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -1,7 +1,56 @@ #include "sync.h" -#include "" +#include <QtSql> +#include <QMultimedia> +#include <QMediaPlayer> +#include <QSqlQuery> +#include "song.h" +#include "node.h" -Sync::Sync() -{ +#include "config.h" + +#ifdef QT_DEBUG +#include <QDebug> +#endif + +namespace syncLib{ + +Sync::Sync(){ + node = new Node(); + player = new QMediaPlayer(nullptr,QMediaPlayer::LowLatency); +} + +void Sync::initDB(){ + if(db) return; + db = QSqlDatabase::addDatabase("QSQLITE"); + QDir d("./" + DATABASE_NAME); + db.setDatabaseName(d.absolutePath()); + if(db->open()){ + qyery = new QSqlQuery(db); + QString qyer = QString("CREATE TABLE IF NOT EXISTS %0 " + "id int NOT NULL AUTO_INCREMENT," + "name VARCHAR(100)," + "size INT NOT NULL," + "data BLOB NOT NULL").arg(DATATABLE_NAME); + qyery->exec(qyer); + } +} + +bool Sync::save(const Song &song){ + QString qyer = QString("INSERT INTO %0 (name, size, data) VALUES" + "(%1,%2, :data)").arg(DATATABLE_NAME, + song.name, + QString::number(song.size)); + qyery->prepare(qyer); + qyery->bindValue(":data",song.source); + + return qyery->exec(); +} + +Sync::~Sync(){ + delete node; + delete db; + delete player; +} } + diff --git a/sync/sync.h b/sync/sync.h index efa4153..5ea1ce3 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -1,12 +1,27 @@ #ifndef SYNC_H #define SYNC_H - +/* +data=QSqlDatabase::addDatabase("QSQLITE"); + QDir d("./Inventory"); + data.setDatabaseName(d.absolutePath()); + qDebug()<<d.absolutePath()<<data.open(); +*/ class QString; +class QSqlDatabase; +class QMediaPlayer; +class QSqlQuery; namespace syncLib { + class Song; +class Node; class Sync { private: + Node *node; + QSqlDatabase *db; + QMediaPlayer *player; + QSqlQuery *qyery; + void initDB(); bool save(const Song &song); public: bool Play(QString url) const; diff --git a/sync/sync.pro b/sync/sync.pro index 1a9d9af..45d9a76 100644 --- a/sync/sync.pro +++ b/sync/sync.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += network multimedia +QT += network multimedia sql QT -= gui @@ -31,7 +31,8 @@ SOURCES += \ HEADERS += \ sync.h \ song.h \ - node.h + node.h \ + config.h unix { target.path = /usr/lib INSTALLS += target From bf71e5610dbc30ab77e59d2e1c4a5e2c74f1b473 Mon Sep 17 00:00:00 2001 From: EndrII <EndrIIMail@gmail.com> Date: Sat, 11 Nov 2017 14:03:14 +0300 Subject: [PATCH 05/14] added comments for classes. --- sync/exaptions.h | 18 ++++++++++++++++++ sync/node.cpp | 28 ++++++++++++---------------- sync/node.h | 32 +++++++++++++++++++++++++++----- sync/song.h | 26 +++++++++++++++++++++++++- sync/sync.cpp | 10 ++++++++++ sync/sync.h | 48 ++++++++++++++++++++++++++++++++++++++++++------ sync/sync.pro | 3 ++- 7 files changed, 136 insertions(+), 29 deletions(-) create mode 100644 sync/exaptions.h diff --git a/sync/exaptions.h b/sync/exaptions.h new file mode 100644 index 0000000..2958433 --- /dev/null +++ b/sync/exaptions.h @@ -0,0 +1,18 @@ +#ifndef EXAPTIONS_H +#define EXAPTIONS_H + +#include <exception> +#include <QString> +#include <QTranslator> +/** + * @brief The MediaException class + */ +class MediaException:public std::exception +{ +public: + QString what(){ + return QObject::tr("Your operating system or platform has not supported media files."); + } +}; + +#endif // EXAPTIONS_H diff --git a/sync/node.cpp b/sync/node.cpp index 8114d8d..b7d5cae 100644 --- a/sync/node.cpp +++ b/sync/node.cpp @@ -8,8 +8,8 @@ syncLib::package::package(){ type = syncLib::package::t_void; source.clear(); - playTime = 0; - playPoint = 0; + playdata.run = 0; + playdata.seek = 0; size = 0; } syncLib::package::package(const QByteArray &array): @@ -20,12 +20,8 @@ const Song& syncLib::package::getSong(){ return source; } -unsigned int syncLib::package::getPlayTime(){ - return playTime; -} - -unsigned int syncLib::package::getPlayPoint(){ - return playPoint; +Syncer syncLib::package::getPlayData(){ + return playdata; } syncLib::package::TypePackage syncLib::package::getType(){ @@ -39,7 +35,7 @@ bool syncLib::package::isValid(){ case package::t_close: return true; case package::t_sync: - return playTime > 0 && playPoint > 0; + return Syncer.run > 0 && Syncer.seek > 0; case package::t_song: return source.size > 0; case package::t_stop: @@ -66,8 +62,8 @@ QByteArray syncLib::package::parseTo(){ case package::t_sync: stream << int(); stream << (unsigned char)(type); - stream << playTime; - stream << playPoint; + stream << playdata.run; + stream << playdata.seek; stream.device()->seek(0); stream << temp.size(); break; @@ -100,8 +96,8 @@ bool syncLib::package::parseFrom(const QByteArray &array){ case package::t_close: return true; case package::t_sync: - stream >> playTime; - stream >> playPoint; + stream >> playdata.run; + stream >> playdata.seek; return isValid(); case package::t_song: stream >> source; @@ -138,11 +134,11 @@ void syncLib::Node::readData(QTcpSocket *c){ } void syncLib::Node::WriteAll(const QByteArray &data){ for(QTcpSocket*i:clients){ - i->Write(data); + i->write(data); } } void syncLib::Node::disconnectClient(QTcpSocket *c){ - c->getSource()->close(); + c->close(); clients.removeOne(c); delete c; } @@ -167,7 +163,7 @@ bool syncLib::Node::addNode(QTcpSocket *node){ syncLib::Node::~Node(){ for(QTcpSocket *i:clients){ - i->getSource()->abort(); + i->abort(); delete i; } this->close(); diff --git a/sync/node.h b/sync/node.h index 82ff794..975a98b 100644 --- a/sync/node.h +++ b/sync/node.h @@ -2,9 +2,17 @@ #define NODE_H #include <QTcpServer> class Song; +class Syncer; namespace syncLib { - +/** + * @brief The package class. Package for translite media data on network + * + * parse map: + * 1 byle - type + * 4 byte - size of data of package (it avelable if type is t_sync or t_song) + * data + */ class package { /*parse map */ @@ -14,6 +22,14 @@ class package * 4 byte - size of data of package (it avelable if type is t_sync or t_song) * data */ + /** + * @brief The TypePackage enum + * t_void - this package empty and not valid. + * t_close - the information about close channel. + * t_sync - the infomation about sync playning media file on network. + * t_song - the package with this type is necessary for translite media data on network. + * t_stop - the package with type 'stop' necessary for stoping playning media files. + */ enum TypePackage{ t_void = 0x0, t_close = 0x1, @@ -25,15 +41,21 @@ private: TypePackage type; unsigned int size; Song source; - unsigned int playTime; - unsigned int playPoint; + Syncer playdata; public: package(); package(const QByteArray& array); ~package(); + /** + * @brief getSong + * @return Song + */ const Song& getSong() const; - unsigned int getPlayTime() const; - unsigned int getPlayPoint() const; + /** + * @brief getPlayTime + * @return time of playning media data + */ + Syncer getPlayData() const; unsigned char getType() const; bool isValid() const; QByteArray parseTo() const; diff --git a/sync/song.h b/sync/song.h index a333a60..2dcad39 100644 --- a/sync/song.h +++ b/sync/song.h @@ -3,8 +3,29 @@ class QString; class QByteArray; class QDataStream; +class time_t; namespace syncLib { +/** + * @brief The Syncer struct + * + */ +struct Syncer +{ + /** + * @brief seek - wher is play media file + */ + unsigned int seek; + /** + * @brief run when is play media file + */ + time_t run; +}; + +/** + * @brief The SongHeader class sound header with media information + * (id,size and name) + */ class SongHeader { public: @@ -19,7 +40,10 @@ public: friend QDataStream& operator << (QDataStream& stream, const SongHeader& song); friend QDataStream& operator >> (QDataStream& stream, SongHeader& song); }; - +/** + * @brief The Song class + * into this calss added mediadata of playable media file. + */ class Song : public SongHeader{ private: QByteArray source; diff --git a/sync/sync.cpp b/sync/sync.cpp index 91a4e46..94fb854 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -5,6 +5,7 @@ #include <QSqlQuery> #include "song.h" #include "node.h" +#include "exaptions.h" #include "config.h" @@ -17,6 +18,9 @@ namespace syncLib{ Sync::Sync(){ node = new Node(); player = new QMediaPlayer(nullptr,QMediaPlayer::LowLatency); + if(!player->isAvailable()){ + throw MediaException(); + } } void Sync::initDB(){ @@ -46,6 +50,12 @@ bool Sync::save(const Song &song){ return qyery->exec(); } +bool Sync::Play(const Song& song){ + QBuffer buffer(&song.source); + player->setMedia(QMediaContent(), &buffer); + player->play(); +} + Sync::~Sync(){ delete node; delete db; diff --git a/sync/sync.h b/sync/sync.h index 5ea1ce3..bd648c1 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -1,11 +1,6 @@ #ifndef SYNC_H #define SYNC_H -/* -data=QSqlDatabase::addDatabase("QSQLITE"); - QDir d("./Inventory"); - data.setDatabaseName(d.absolutePath()); - qDebug()<<d.absolutePath()<<data.open(); -*/ + class QString; class QSqlDatabase; class QMediaPlayer; @@ -14,6 +9,11 @@ namespace syncLib { class Song; class Node; +class Syncer; +/** + * @brief The Sync class is main class of this library. + * the 'sync' has supported synced playning media files on network and saving media data into local database. + */ class Sync { private: @@ -21,12 +21,48 @@ private: QSqlDatabase *db; QMediaPlayer *player; QSqlQuery *qyery; + /** + * @brief initDB initialize local database of song + */ void initDB(); + /** + * @brief save media data into local database; + * @param song savining media data. + * @return true if song saved else return false + */ bool save(const Song &song); public: + /** + * @brief Play song in this device, if device has not supported playning media data this method throw MediaExcrption. + * @param song playning media data. + * @param syncdata data of synbced playning of media data. + * @return true if all done else false. + */ + bool Play(const Song &song, Syncer* syncdata = nullptr); + /** + * @brief Play song from local media file. + * @param url of local media file. + * @return true if all done else false. + */ bool Play(QString url) const; + /** + * @brief Play song from local database by id. + * @param id_song of song. + * @return true if all done else false. + */ + bool Play(int id_song); + /** + * @brief Pause playning song. + */ void Pause() const; + /** + * @brief stop playning song. + */ void stop() const; + /** + * @brief jump - jump to new position of playning media data. + * @param seek - a new position of media data. + */ void jump(const int seek) const; Sync(); ~Sync(); diff --git a/sync/sync.pro b/sync/sync.pro index 45d9a76..22265db 100644 --- a/sync/sync.pro +++ b/sync/sync.pro @@ -32,7 +32,8 @@ HEADERS += \ sync.h \ song.h \ node.h \ - config.h + config.h \ + exaptions.h unix { target.path = /usr/lib INSTALLS += target From 1c5140448a38c329fb834a9439a25453f0fa1a19 Mon Sep 17 00:00:00 2001 From: EndrII <EndrIIMail@gmail.com> Date: Sat, 11 Nov 2017 20:35:30 +0300 Subject: [PATCH 06/14] added sync class --- sync/config.h | 2 +- sync/node.cpp | 1 - sync/node.h | 5 +-- sync/song.h | 6 ++-- sync/sync.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++----- sync/sync.h | 21 ++++++++----- 6 files changed, 97 insertions(+), 22 deletions(-) diff --git a/sync/config.h b/sync/config.h index b6dca6c..8aff070 100644 --- a/sync/config.h +++ b/sync/config.h @@ -12,6 +12,6 @@ // network config #define DEDAULT_PORT 1239 - +#define MAX_SYNC_TIME 10000 // 10 sec #endif // CONFIG_H diff --git a/sync/node.cpp b/sync/node.cpp index b7d5cae..079026d 100644 --- a/sync/node.cpp +++ b/sync/node.cpp @@ -3,7 +3,6 @@ #include "song.h" #include <QDataStream> -#include "config.h" syncLib::package::package(){ type = syncLib::package::t_void; diff --git a/sync/node.h b/sync/node.h index 975a98b..dc213e4 100644 --- a/sync/node.h +++ b/sync/node.h @@ -1,6 +1,7 @@ #ifndef NODE_H #define NODE_H #include <QTcpServer> +#include "config.h" class Song; class Syncer; namespace syncLib { @@ -71,13 +72,13 @@ private slots: void newConnection_(); void readData(QTcpSocket*_client); public: - EServer(); + Node(); void WriteAll(const QByteArray&); void disconnectClient(QTcpSocket*); QList<QTcpSocket*>* getClients(); bool addNode(const QString &node, int port = DEDAULT_PORT); bool addNode(QTcpSocket* node); - ~EServer(); + ~Node(); signals: void Error(QString); void Message(QTcpSocket*); diff --git a/sync/song.h b/sync/song.h index 2dcad39..83164f0 100644 --- a/sync/song.h +++ b/sync/song.h @@ -3,7 +3,7 @@ class QString; class QByteArray; class QDataStream; -class time_t; +class Time_point; namespace syncLib { /** @@ -17,9 +17,9 @@ struct Syncer */ unsigned int seek; /** - * @brief run when is play media file + * @brief run when is play media file (int64) */ - time_t run; + Time_point run; }; /** diff --git a/sync/sync.cpp b/sync/sync.cpp index 94fb854..afdfbbc 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -6,6 +6,8 @@ #include "song.h" #include "node.h" #include "exaptions.h" +#include "time.h" +#include "thread" #include "config.h" @@ -14,6 +16,14 @@ #endif namespace syncLib{ +/** + * @brief Clock system time on nanosecunds + */ +typedef std::chrono::high_resolution_clock Clock; +/** + * @brief Time_point on nanosecunds (int64) + */ +typedef Clock::time_point Time_point; Sync::Sync(){ node = new Node(); @@ -25,11 +35,11 @@ Sync::Sync(){ void Sync::initDB(){ if(db) return; - db = QSqlDatabase::addDatabase("QSQLITE"); - QDir d("./" + DATABASE_NAME); - db.setDatabaseName(d.absolutePath()); + *db = QSqlDatabase::addDatabase("QSQLITE"); + QDir d(QString("./%0").arg(DATABASE_NAME)); + db->setDatabaseName(d.absolutePath()); if(db->open()){ - qyery = new QSqlQuery(db); + qyery = new QSqlQuery(*db); QString qyer = QString("CREATE TABLE IF NOT EXISTS %0 " "id int NOT NULL AUTO_INCREMENT," "name VARCHAR(100)," @@ -39,21 +49,79 @@ void Sync::initDB(){ } } -bool Sync::save(const Song &song){ +int Sync::save(const Song &song){ QString qyer = QString("INSERT INTO %0 (name, size, data) VALUES" "(%1,%2, :data)").arg(DATATABLE_NAME, song.name, QString::number(song.size)); qyery->prepare(qyer); qyery->bindValue(":data",song.source); - - return qyery->exec(); + if(!qyery->exec()) + return -1; + if(qyery->exec(QString("SELECT MAAX(id) form %0").arg(DATATABLE_NAME))) + return -1; + return qyery->value(0).toInt(); } -bool Sync::Play(const Song& song){ +bool Sync::Play(const Song& song, Syncer *syncdata){ QBuffer buffer(&song.source); player->setMedia(QMediaContent(), &buffer); + if(syncdata){ + Time_point sync_time = syncdata->run - Clock::now(); + auto max_sync = Time_point(MAX_SYNC_TIME * 1000000); + if(sync_time > max_sync && sync_time <= 0) + return false; + do { + std::this_thread::yield(); + } while (Clock::now() < syncdata->run); + player->setPosition(syncdata->seek); + } player->play(); + return true; +} + +bool Sync::Play(int id_song){ + + QString qyer = QString("SELECT * from %0 where id=%1").arg(DATATABLE_NAME).arg(id_song); + if(!qyery->exec(qyer)){ + return false; + } + Song song; + song.id = qyery->value(0).toInt(); + song.name = qyery->value(1).toString(); + song.size = qyery->value(2).toInt(); + song.source = qyery->value(3).toByteArray(); + return Sync::Play(song); +} + +bool Sync::Play(QString url){ + QFile f(url); + if(!f.open(QIODevice::ReadOnly)){ + return false; + } + QByteArray bytes = f.readAll(); + f.close(); + QString name = url.right(url.lastIndexOf(QRegularExpression("[\\/]"))); // meby [[\\\/]] + Song song; + song.name = name; + song.size = bytes.size(); + song.source = bytes; + song.id = Sync::save(song); + if(song.id < 0) + return false; + return Sync::Play(song); +} + +void Sync::Pause(){ + player->pause(); +} + +void Sync::stop(){ + player->stop(); +} + +void Sync::jump(const int seek){ + player->setPosition(seek); } Sync::~Sync(){ diff --git a/sync/sync.h b/sync/sync.h index bd648c1..a0c9ec7 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -10,6 +10,7 @@ namespace syncLib { class Song; class Node; class Syncer; + /** * @brief The Sync class is main class of this library. * the 'sync' has supported synced playning media files on network and saving media data into local database. @@ -26,11 +27,17 @@ private: */ void initDB(); /** - * @brief save media data into local database; + * @brief save media data into local database. * @param song savining media data. - * @return true if song saved else return false + * @return id of song saved on local database. */ - bool save(const Song &song); + int save(const Song &song); + /** + * @brief fromDataBase return a song from local database by id. + * @param id of song saved in local database. + * @return song drom local database. + */ + Song fromDataBase(const int id); public: /** * @brief Play song in this device, if device has not supported playning media data this method throw MediaExcrption. @@ -44,7 +51,7 @@ public: * @param url of local media file. * @return true if all done else false. */ - bool Play(QString url) const; + bool Play(QString url); /** * @brief Play song from local database by id. * @param id_song of song. @@ -54,16 +61,16 @@ public: /** * @brief Pause playning song. */ - void Pause() const; + void Pause(); /** * @brief stop playning song. */ - void stop() const; + void stop(); /** * @brief jump - jump to new position of playning media data. * @param seek - a new position of media data. */ - void jump(const int seek) const; + void jump(const int seek); Sync(); ~Sync(); }; From b7b4e3182b350c74f02a5e5008075cd48669cbe5 Mon Sep 17 00:00:00 2001 From: EndrII <EndrIIMail@gmail.com> Date: Sun, 12 Nov 2017 13:26:37 +0300 Subject: [PATCH 07/14] fixed sync time methods --- sync/config.h | 2 +- sync/song.cpp | 3 --- sync/song.h | 17 +++++++++++------ sync/sync.cpp | 38 +++++++++++++++++++++++++------------- sync/sync.h | 21 ++++++++++++++++----- 5 files changed, 53 insertions(+), 28 deletions(-) diff --git a/sync/config.h b/sync/config.h index 8aff070..ce3eef9 100644 --- a/sync/config.h +++ b/sync/config.h @@ -12,6 +12,6 @@ // network config #define DEDAULT_PORT 1239 -#define MAX_SYNC_TIME 10000 // 10 sec +#define MAX_SYNC_TIME 10 * 1000 * 1000 // 10 sec on microsec #endif // CONFIG_H diff --git a/sync/song.cpp b/sync/song.cpp index c8acaa8..d2f2439 100644 --- a/sync/song.cpp +++ b/sync/song.cpp @@ -1,7 +1,4 @@ #include "song.h" -#include <QString> -#include <QByteArray> - #include "config.h" syncLib::SongHeader::SongHeader() diff --git a/sync/song.h b/sync/song.h index 83164f0..bbb58e0 100644 --- a/sync/song.h +++ b/sync/song.h @@ -1,9 +1,14 @@ #ifndef SONG_H #define SONG_H -class QString; -class QByteArray; -class QDataStream; -class Time_point; +#include <QString> +#include <QByteArray> +#include <QDataStream> + +/** + * @brief Time_point on nanosecunds (uint64_t) + */ +typedef uint64_t microseconds; + namespace syncLib { /** @@ -17,9 +22,9 @@ struct Syncer */ unsigned int seek; /** - * @brief run when is play media file (int64) + * @brief run when is play media file (int) */ - Time_point run; + microseconds run; }; /** diff --git a/sync/sync.cpp b/sync/sync.cpp index afdfbbc..7f4845d 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -16,14 +16,6 @@ #endif namespace syncLib{ -/** - * @brief Clock system time on nanosecunds - */ -typedef std::chrono::high_resolution_clock Clock; -/** - * @brief Time_point on nanosecunds (int64) - */ -typedef Clock::time_point Time_point; Sync::Sync(){ node = new Node(); @@ -63,17 +55,37 @@ int Sync::save(const Song &song){ return qyery->value(0).toInt(); } -bool Sync::Play(const Song& song, Syncer *syncdata){ +/* + * information about chrono + * https://stackoverflow.com/questions/31255486/c-how-do-i-convert-a-stdchronotime-point-to-long-and-back + */ + +microseconds Sync::now(){ + auto tim = std::chrono::system_clock::now(); + auto mc = std::chrono::time_point_cast<std::chrono::microseconds>(tim); + auto epoh = mc.time_since_epoch(); +#ifdef QT_DEBUG + qDebug() << epoh.count(); +#endif + return epoh.count(); +} + +Clock Sync::from(const microseconds& mc){ + std::chrono::duration<long> dur(mc); + return Clock(dur); +} + +bool Sync::Play(Song& song, Syncer *syncdata){ QBuffer buffer(&song.source); player->setMedia(QMediaContent(), &buffer); if(syncdata){ - Time_point sync_time = syncdata->run - Clock::now(); - auto max_sync = Time_point(MAX_SYNC_TIME * 1000000); - if(sync_time > max_sync && sync_time <= 0) + microseconds sync_time = syncdata->run - now(); + if(sync_time > MAX_SYNC_TIME && sync_time <= 0) return false; + Clock run_time = from(syncdata->run); do { std::this_thread::yield(); - } while (Clock::now() < syncdata->run); + } while (std::chrono::high_resolution_clock::now() < run_time); player->setPosition(syncdata->seek); } player->play(); diff --git a/sync/sync.h b/sync/sync.h index a0c9ec7..2c0c995 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -1,15 +1,15 @@ #ifndef SYNC_H #define SYNC_H - -class QString; +#include "song.h" +#include <chrono> class QSqlDatabase; class QMediaPlayer; class QSqlQuery; namespace syncLib { -class Song; +typedef std::chrono::time_point<std::chrono::high_resolution_clock> Clock; + class Node; -class Syncer; /** * @brief The Sync class is main class of this library. @@ -38,6 +38,17 @@ private: * @return song drom local database. */ Song fromDataBase(const int id); + /** + * @brief now - get now time on microsecunds + * @return - count of microsecunds + */ + microseconds now(); + /** + * @brief from cast to chrono secunds + * @param mcrs microseconds of uint_64 + * @return microseconds of chrono + */ + Clock from(const microseconds &mcrs); public: /** * @brief Play song in this device, if device has not supported playning media data this method throw MediaExcrption. @@ -45,7 +56,7 @@ public: * @param syncdata data of synbced playning of media data. * @return true if all done else false. */ - bool Play(const Song &song, Syncer* syncdata = nullptr); + bool Play(Song &song, Syncer* syncdata = nullptr); /** * @brief Play song from local media file. * @param url of local media file. From 3acfbb5a103d85f821b1ac6c151eb671278d2ba6 Mon Sep 17 00:00:00 2001 From: EndrII <EndrIIMail@gmail.com> Date: Mon, 13 Nov 2017 23:05:59 +0300 Subject: [PATCH 08/14] buidl fix --- sync/node.cpp | 55 ++++++++++++++++++++++++++++----------------------- sync/node.h | 7 +++---- sync/song.cpp | 45 ++++++++++++++++++++++------------------- sync/song.h | 6 +++--- 4 files changed, 61 insertions(+), 52 deletions(-) diff --git a/sync/node.cpp b/sync/node.cpp index 079026d..9c1198b 100644 --- a/sync/node.cpp +++ b/sync/node.cpp @@ -3,38 +3,39 @@ #include "song.h" #include <QDataStream> +namespace syncLib{ -syncLib::package::package(){ - type = syncLib::package::t_void; +package::package(){ + type = package::t_void; source.clear(); playdata.run = 0; playdata.seek = 0; size = 0; } -syncLib::package::package(const QByteArray &array): - syncLib::package::package(){ +package::package(const QByteArray &array): + package::package(){ parseFrom(array); } -const Song& syncLib::package::getSong(){ +const Song& package::getSong() const{ return source; } -Syncer syncLib::package::getPlayData(){ +Syncer package::getPlayData() const{ return playdata; } -syncLib::package::TypePackage syncLib::package::getType(){ +package::TypePackage package::getType() const{ return type; } -bool syncLib::package::isValid(){ +bool package::isValid() const{ switch (type) { case package::t_void: return false; case package::t_close: return true; case package::t_sync: - return Syncer.run > 0 && Syncer.seek > 0; + return playdata.run > 0 && playdata.seek > 0; case package::t_song: return source.size > 0; case package::t_stop: @@ -44,9 +45,9 @@ bool syncLib::package::isValid(){ } } -QByteArray syncLib::package::parseTo(){ +QByteArray package::parseTo(){ QByteArray temp; - QDataStream stream(&temp); + QDataStream stream(temp); temp.clear(); if(isValid()){ switch (type) { @@ -82,13 +83,13 @@ QByteArray syncLib::package::parseTo(){ default: break; } - return temp; } + return temp; } -bool syncLib::package::parseFrom(const QByteArray &array){ +bool package::parseFrom(const QByteArray &array){ type = t_void; - QDataStream stream(&array); + QDataStream stream(array); switch (type) { case package::t_void: return false; @@ -108,51 +109,51 @@ bool syncLib::package::parseFrom(const QByteArray &array){ } } -syncLib::Node::Node():QTcpServer(){ +Node::Node():QTcpServer(){ connect(this,SIGNAL(acceptError(QAbstractSocket::SocketError)),SLOT(acceptError_(QAbstractSocket::SocketError))); connect(this,SIGNAL(newConnection()),SLOT(newConnection_())); } -void syncLib::Node::acceptError_(QTcpSocket*c){ +void Node::acceptError_(QTcpSocket*c){ c->close(); clients.removeOne(c); emit ClientDisconnected(c); delete c; } -QList<QTcpSocket*>* syncLib::Node::getClients(){ +QList<QTcpSocket*>* Node::getClients(){ return &clients; } -void syncLib::Node::newConnection_(){ +void Node::newConnection_(){ QTcpSocket *newClient=new QTcpSocket(nextPendingConnection()); clients.push_back(newClient); connect(newClient,SIGNAL(Disconnected(ETcpSocket*)),this,SLOT(acceptError_(QTcpSocket*))); connect(newClient,SIGNAL(Message(ETcpSocket*)),this,SLOT(readData(QTcpSocket*))); emit ClientConnected(newClient); } -void syncLib::Node::readData(QTcpSocket *c){ +void Node::readData(QTcpSocket *c){ emit Message(c); } -void syncLib::Node::WriteAll(const QByteArray &data){ +void Node::WriteAll(const QByteArray &data){ for(QTcpSocket*i:clients){ i->write(data); } } -void syncLib::Node::disconnectClient(QTcpSocket *c){ +void Node::disconnectClient(QTcpSocket *c){ c->close(); clients.removeOne(c); delete c; } -bool syncLib::Node::addNode(const QString &node,int port){ +bool Node::addNode(const QString &node,int port){ QTcpSocket *temp = new QTcpSocket; - if(temp->bind(node,port) && temp->open(QIODevice::ReadWrite)){ + if(temp->bind(QHostAddress(node),port) && temp->open(QIODevice::ReadWrite)){ clients.append(temp); return true; } return false; } -bool syncLib::Node::addNode(QTcpSocket *node){ +bool Node::addNode(QTcpSocket *node){ if(node->isOpen()){ clients.append(node); return true; @@ -160,10 +161,14 @@ bool syncLib::Node::addNode(QTcpSocket *node){ return false; } -syncLib::Node::~Node(){ +Node::~Node(){ for(QTcpSocket *i:clients){ i->abort(); delete i; } this->close(); } + +} + + diff --git a/sync/node.h b/sync/node.h index dc213e4..9fd42e7 100644 --- a/sync/node.h +++ b/sync/node.h @@ -1,8 +1,7 @@ #ifndef NODE_H #define NODE_H #include <QTcpServer> -#include "config.h" -class Song; +#include <song.h> class Syncer; namespace syncLib { @@ -57,9 +56,9 @@ public: * @return time of playning media data */ Syncer getPlayData() const; - unsigned char getType() const; + TypePackage getType() const; bool isValid() const; - QByteArray parseTo() const; + QByteArray parseTo(); bool parseFrom(const QByteArray& array); }; diff --git a/sync/song.cpp b/sync/song.cpp index d2f2439..97a68f9 100644 --- a/sync/song.cpp +++ b/sync/song.cpp @@ -1,76 +1,81 @@ #include "song.h" -#include "config.h" -syncLib::SongHeader::SongHeader() +namespace syncLib{ + +SongHeader::SongHeader() { this->id = 0; this->name = ""; this->size = 0; } -syncLib::SongHeader& syncLib::SongHeader::operator =(const syncLib::SongHeader& right){ +SongHeader& SongHeader::operator =(const SongHeader& right){ this->id = right.id; this->name = right.name; this->size = right.size; return *this; } -bool syncLib::SongHeader::operator ==(const syncLib::SongHeader& right){ +bool SongHeader::operator ==(const SongHeader& right){ return this->name == right.name && this->size == right.size; } -syncLib::SongHeader::getSize(){ +unsigned int SongHeader::getSize() const{ QByteArray size; - QDataStream stream(&size); + QDataStream stream(size); stream << id << name << this->size; return size.size(); } -syncLib::Song::Song(): - syncLib::SongHeader() +Song::Song(): + SongHeader() { source.clear(); } -friend QDataStream& operator << (QDataStream& stream, const syncLib::SongHeader& song){ +QDataStream& operator << (QDataStream& stream, const SongHeader& song){ stream << song.id; stream << song.name; stream << song.size; return stream; } -friend QDataStream& operator >> (QDataStream& stream, syncLib::SongHeader& song){ +QDataStream& operator >> (QDataStream& stream, SongHeader& song){ stream >> song.id; stream >> song.name; stream >> song.size; return stream; } -syncLib::Song::Song(const SongHeader& from) - :syncLib::Song::Song() +Song::Song(const SongHeader& from) + :Song::Song() { this->id = from.id; this->name = from.name; this->size = from.size; } -syncLib::Song::clear(){ +void Song::clear(){ source.clear(); } -syncLib::Song::~Song(){ +Song::~Song(){ source.clear(); } -syncLib::Song::getSize(){ - return syncLib::SongHeader::getSize() + source.size(); +unsigned int Song::getSize() const{ + return SongHeader::getSize() + source.size(); } -QDataStream operator << (QDataStream& stream,const syncLib::Song& song){ - stream << (syncLib::SongHeader)(*this); +QDataStream& operator << (QDataStream& stream,const Song& song){ + stream << static_cast<const SongHeader&>(song); stream << song.source; + return stream; } -QDataStream operator << (QDataStream& stream, syncLib::Song& song){ - stream >> (syncLib::SongHeader)(*this); +QDataStream& operator >> (QDataStream& stream, Song& song){ + stream >> static_cast<SongHeader&>(song); stream >> song.source; + return stream; +} + } diff --git a/sync/song.h b/sync/song.h index bbb58e0..c7ba636 100644 --- a/sync/song.h +++ b/sync/song.h @@ -3,11 +3,11 @@ #include <QString> #include <QByteArray> #include <QDataStream> - +#include <config.h> /** * @brief Time_point on nanosecunds (uint64_t) */ -typedef uint64_t microseconds; +typedef quint64 microseconds; namespace syncLib { @@ -40,7 +40,7 @@ public: SongHeader(); SongHeader& operator = (const SongHeader& right); bool operator == (const SongHeader& right); - virtual unsigned int getSize(); + virtual unsigned int getSize()const; virtual ~SongHeader(); friend QDataStream& operator << (QDataStream& stream, const SongHeader& song); friend QDataStream& operator >> (QDataStream& stream, SongHeader& song); From c732a3d8bce7dfef28b70be04d435f7ea58f3f39 Mon Sep 17 00:00:00 2001 From: EndrII <EndrIIMail@gmail.com> Date: Sat, 18 Nov 2017 01:29:14 +0300 Subject: [PATCH 09/14] added custom TCP sockets --- sync/ETcpSocket.cpp | 143 ++++++++++++++++++++++++++++++++++++++++++++ sync/ETcpSocket.h | 53 ++++++++++++++++ sync/exaptions.h | 8 +++ sync/node.cpp | 53 +++++++++------- sync/node.h | 19 +++--- sync/sync.pro | 6 +- 6 files changed, 249 insertions(+), 33 deletions(-) create mode 100755 sync/ETcpSocket.cpp create mode 100755 sync/ETcpSocket.h diff --git a/sync/ETcpSocket.cpp b/sync/ETcpSocket.cpp new file mode 100755 index 0000000..91c0e7b --- /dev/null +++ b/sync/ETcpSocket.cpp @@ -0,0 +1,143 @@ +#include "ETcpSocket.h" +#include "exaptions.h" + +ETcpSocket::ETcpSocket() +{ + source=new QTcpSocket(); + init(); +} +ETcpSocket::ETcpSocket(QTcpSocket*ptr) +{ + source=ptr; + init(); +} + +ETcpSocket::ETcpSocket(const QString& address, int port){ + source = new QTcpSocket(); + if(!source->bind(QHostAddress(address),port) || !source->open(QIODevice::ReadWrite)){ + throw addNodeExaption(); + } + init(); +} + +void ETcpSocket::init(){ + array=new QByteArray; + connect(source,SIGNAL(connected()),this,SLOT(connected_())); + connect(source,SIGNAL(disconnected()),this,SLOT(disconnected_())); + connect(source,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error_(QAbstractSocket::SocketError))); + connect(source,SIGNAL(hostFound()),this,SLOT(hostFound_())); + connect(source,SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)),this,SLOT(proxyAuthenticationRequired_(const QNetworkProxy &, QAuthenticator *))); + connect(source,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(stateChanged_(QAbstractSocket::SocketState))); + connect(source,SIGNAL(readyRead()),this,SLOT(readReady_())); +} + +void ETcpSocket::error_(QAbstractSocket::SocketError i){ + emit Error(this,i); +} + +void ETcpSocket::connected_(){ + emit Connected(this); +} + +void ETcpSocket::disconnected_(){ + emit Disconnected(this); +} + +void ETcpSocket::hostFound_(){ + emit HostFound(this); +} + +void ETcpSocket::proxyAuthenticationRequired_(const QNetworkProxy &proxy, QAuthenticator *authenticator){ + emit ProxyAuthenticationRequired(this,proxy,authenticator); +} + +void ETcpSocket::stateChanged_(QAbstractSocket::SocketState socketState){ + emit StateChanged(this,socketState); +} + +void ETcpSocket::readReady_(){ + bool sizewrite=array->isEmpty(); + //while(source->bytesAvailable()) + array->append(source->readAll()); + QDataStream stream(array,QIODevice::ReadOnly); + if(sizewrite) + stream>>size; +#ifdef QT_DEBUG + qDebug()<<"messae size:"<<size; + qDebug()<<"message package size:"<<array->size(); +#endif + if(size==array->size()) + { + array->remove(0,sizeof(qint32)); + ReadyStack.push_back(array); + array=new QByteArray; + emit Message(this); + }else{ + emit donwload(array->size(),size); + } + // emit ReadReady(this); +} + +QString ETcpSocket::name() const{ + return source->peerAddress().toString(); +} + +QByteArray* ETcpSocket::topStack(){ + if(ReadyStack.size()) + return ReadyStack.front(); + return NULL; +} + +QTcpSocket* ETcpSocket::getSource()const{ + return source; +} + +void ETcpSocket::nextItem(){ + if(ReadyStack.size()) + ReadyStack.pop_front(); +} + +int ETcpSocket::sizeDescriptPackege(){ + return sizeof(qint32); +} + +QString ETcpSocket::toStringTcp(){ + return source->peerAddress().toString(); +} + +bool ETcpSocket::Write(const QByteArray&data){ + if(source->state()==QTcpSocket::ConnectedState){ + QByteArray array; + QDataStream stream(&array,QIODevice::ReadWrite); + stream<<qint32(0); + //stream<<data; + array.append(data); + stream.device()->seek(0); + stream<<qint32(array.size()); +#ifdef QT_DEBUG + qDebug()<<"size :"<<array.size(); + qint64 temp= source->write(array); + qDebug()<<"size write:"<<temp<<" size packege:"<<array.size(); + return temp==(array.size()); +#else + return source->write(array)==(array.size()); +#endif + } + return false; +} + +ETcpSocket::~ETcpSocket() +{ + for(QByteArray*i:ReadyStack){ + i->clear(); + delete i; + } + disconnect(source,SIGNAL(connected()),this,SLOT(connected_())); + disconnect(source,SIGNAL(disconnected()),this,SLOT(disconnected_())); + disconnect(source,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error_(QAbstractSocket::SocketError))); + disconnect(source,SIGNAL(hostFound()),this,SLOT(hostFound_())); + disconnect(source,SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)),this,SLOT(proxyAuthenticationRequired_(const QNetworkProxy &, QAuthenticator *))); + disconnect(source,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(stateChanged_(QAbstractSocket::SocketState))); + disconnect(source,SIGNAL(readyRead()),this,SLOT(readReady_())); + source->deleteLater(); +} diff --git a/sync/ETcpSocket.h b/sync/ETcpSocket.h new file mode 100755 index 0000000..0b329ce --- /dev/null +++ b/sync/ETcpSocket.h @@ -0,0 +1,53 @@ +#ifndef CLIENT_H +#define CLIENT_H +#include <QTcpSocket> +#include <QTcpServer> +#include <QList> +#include <QDataStream> +class ETcpSocket:public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name) +private: + QTcpSocket *source; + QByteArray *array; + qint32 size; + QList<QByteArray*> ReadyStack; + void init(); + +private slots: + void connected_(); + void disconnected_(); + void error_(QAbstractSocket::SocketError socketError); + void hostFound_(); + void readReady_(); + void proxyAuthenticationRequired_(const QNetworkProxy &proxy, QAuthenticator *authenticator); + void stateChanged_(QAbstractSocket::SocketState socketState); +public: + explicit ETcpSocket(); + explicit ETcpSocket(QTcpSocket*); + explicit ETcpSocket(const QString& addres,int port); + QTcpSocket* getSource()const; + QByteArray* topStack(); + void nextItem(); + int sizeDescriptPackege(); + bool Write(const QByteArray&); + ~ETcpSocket(); +public slots: + QString name()const; + QString toStringTcp(); +signals: + void donwload(int val,int max); + void ReadyComplit(ETcpSocket*,QDataStream&); + void Connected(ETcpSocket*); + void Message(ETcpSocket*); + void Disconnected(ETcpSocket*); + void Error(ETcpSocket*,QAbstractSocket::SocketError socketError); + void HostFound(ETcpSocket*); + void ProxyAuthenticationRequired(ETcpSocket*,const QNetworkProxy &proxy, QAuthenticator *authenticator); + void StateChanged(ETcpSocket*,QAbstractSocket::SocketState socketState); + //void Connected(QTcpSocket*); + //void errorConnect(QTcpSocket*,QAbstractSocket::SocketError); +}; + +#endif // CLIENT_H diff --git a/sync/exaptions.h b/sync/exaptions.h index 2958433..3cb196c 100644 --- a/sync/exaptions.h +++ b/sync/exaptions.h @@ -15,4 +15,12 @@ public: } }; +class addNodeExaption:public std::exception +{ +public: + QString what(){ + return QObject::tr("Address not available"); + } +}; + #endif // EXAPTIONS_H diff --git a/sync/node.cpp b/sync/node.cpp index 9c1198b..f4fde0c 100644 --- a/sync/node.cpp +++ b/sync/node.cpp @@ -2,7 +2,7 @@ #include <QTcpSocket> #include "song.h" #include <QDataStream> - +#include "exaptions.h" namespace syncLib{ package::package(){ @@ -113,48 +113,57 @@ Node::Node():QTcpServer(){ connect(this,SIGNAL(acceptError(QAbstractSocket::SocketError)),SLOT(acceptError_(QAbstractSocket::SocketError))); connect(this,SIGNAL(newConnection()),SLOT(newConnection_())); } -void Node::acceptError_(QTcpSocket*c){ - c->close(); +void Node::acceptError_(ETcpSocket*c){ + c->getSource()->close(); clients.removeOne(c); emit ClientDisconnected(c); delete c; } -QList<QTcpSocket*>* Node::getClients(){ +QList<ETcpSocket*>* Node::getClients(){ return &clients; } void Node::newConnection_(){ - QTcpSocket *newClient=new QTcpSocket(nextPendingConnection()); + ETcpSocket *newClient=new ETcpSocket(nextPendingConnection()); clients.push_back(newClient); - connect(newClient,SIGNAL(Disconnected(ETcpSocket*)),this,SLOT(acceptError_(QTcpSocket*))); - connect(newClient,SIGNAL(Message(ETcpSocket*)),this,SLOT(readData(QTcpSocket*))); + connect(newClient,SIGNAL(Disconnected(ETcpSocket*)),this,SLOT(acceptError_(ETcpSocket*))); + connect(newClient,SIGNAL(Message(ETcpSocket*)),this,SLOT(readData(ETcpSocket*))); emit ClientConnected(newClient); } -void Node::readData(QTcpSocket *c){ - emit Message(c); +void Node::readData(ETcpSocket *c){ + package _package; + _package.parseFrom(*c->topStack()); + emit Message(_package,c); } void Node::WriteAll(const QByteArray &data){ - for(QTcpSocket*i:clients){ - i->write(data); + for(ETcpSocket*i:clients){ + i->getSource()->write(data); } } -void Node::disconnectClient(QTcpSocket *c){ - c->close(); +void Node::disconnectClient(ETcpSocket *c){ + c->getSource()->close(); clients.removeOne(c); delete c; } bool Node::addNode(const QString &node,int port){ + ETcpSocket *temp; - QTcpSocket *temp = new QTcpSocket; - if(temp->bind(QHostAddress(node),port) && temp->open(QIODevice::ReadWrite)){ - clients.append(temp); - return true; + try{ + temp = new ETcpSocket(node,port); + }catch(addNodeExaption &e){ +#ifdef QT_DEBUG + qDebug() << e.what(); +#endif + return false; } - return false; + + clients.push_back(temp); + return true; + } -bool Node::addNode(QTcpSocket *node){ - if(node->isOpen()){ +bool Node::addNode(ETcpSocket *node){ + if(node->getSource()->isOpen()){ clients.append(node); return true; } @@ -162,8 +171,8 @@ bool Node::addNode(QTcpSocket *node){ } Node::~Node(){ - for(QTcpSocket *i:clients){ - i->abort(); + for(ETcpSocket *i:clients){ + i->getSource()->close(); delete i; } this->close(); diff --git a/sync/node.h b/sync/node.h index 9fd42e7..86658a4 100644 --- a/sync/node.h +++ b/sync/node.h @@ -1,6 +1,7 @@ #ifndef NODE_H #define NODE_H #include <QTcpServer> +#include "ETcpSocket.h" #include <song.h> class Syncer; namespace syncLib { @@ -65,24 +66,24 @@ public: class Node:public QTcpServer{ Q_OBJECT protected: - QList<QTcpSocket*> clients; + QList<ETcpSocket*> clients; private slots: - void acceptError_(QTcpSocket*); + void acceptError_(ETcpSocket*); void newConnection_(); - void readData(QTcpSocket*_client); + void readData(ETcpSocket*_client); public: Node(); void WriteAll(const QByteArray&); - void disconnectClient(QTcpSocket*); - QList<QTcpSocket*>* getClients(); + void disconnectClient(ETcpSocket*); + QList<ETcpSocket*>* getClients(); bool addNode(const QString &node, int port = DEDAULT_PORT); - bool addNode(QTcpSocket* node); + bool addNode(ETcpSocket* node); ~Node(); signals: void Error(QString); - void Message(QTcpSocket*); - void ClientDisconnected(QTcpSocket*); - void ClientConnected(QTcpSocket*); + void Message(const package&,ETcpSocket*); + void ClientDisconnected(ETcpSocket*); + void ClientConnected(ETcpSocket*); }; } diff --git a/sync/sync.pro b/sync/sync.pro index 22265db..7afcbd9 100644 --- a/sync/sync.pro +++ b/sync/sync.pro @@ -26,14 +26,16 @@ DEFINES += QT_DEPRECATED_WARNINGS SOURCES += \ sync.cpp \ song.cpp \ - node.cpp + node.cpp \ + ETcpSocket.cpp HEADERS += \ sync.h \ song.h \ node.h \ config.h \ - exaptions.h + exaptions.h \ + ETcpSocket.h unix { target.path = /usr/lib INSTALLS += target From 285f068358839e4f28f3349e534cbc2c1ecfb915 Mon Sep 17 00:00:00 2001 From: EndrII <EndrIIMail@gmail.com> Date: Mon, 20 Nov 2017 00:37:12 +0300 Subject: [PATCH 10/14] added a create package method --- sync/ETcpSocket.cpp | 5 +- sync/ETcpSocket.h | 21 ++++++++ sync/config.h | 3 +- sync/node.cpp | 59 ++++++++++++++--------- sync/node.h | 37 +++++++------- sync/song.cpp | 2 +- sync/song.h | 6 +-- sync/sync.cpp | 114 +++++++++++++++++++++++++++++++++++++------- sync/sync.h | 35 ++++++++++++-- 9 files changed, 217 insertions(+), 65 deletions(-) diff --git a/sync/ETcpSocket.cpp b/sync/ETcpSocket.cpp index 91c0e7b..39b2f98 100755 --- a/sync/ETcpSocket.cpp +++ b/sync/ETcpSocket.cpp @@ -70,7 +70,7 @@ void ETcpSocket::readReady_(){ { array->remove(0,sizeof(qint32)); ReadyStack.push_back(array); - array=new QByteArray; + array=new QByteArray(); emit Message(this); }else{ emit donwload(array->size(),size); @@ -93,8 +93,9 @@ QTcpSocket* ETcpSocket::getSource()const{ } void ETcpSocket::nextItem(){ - if(ReadyStack.size()) + if( ReadyStack.size()){ ReadyStack.pop_front(); + } } int ETcpSocket::sizeDescriptPackege(){ diff --git a/sync/ETcpSocket.h b/sync/ETcpSocket.h index 0b329ce..c87d518 100755 --- a/sync/ETcpSocket.h +++ b/sync/ETcpSocket.h @@ -4,6 +4,27 @@ #include <QTcpServer> #include <QList> #include <QDataStream> + +/** + * @brief The ETcpSocket class + * example : + * ETcpSocket *tcp; + * try{ + * tcp = new ETcpSocket(addres,port); + * }catch(addNodeExaption e){ + * e.what(); + * } + * QByteArray *array; + * while(array = tcp.getSource()){ + * package pkg(*array); + * package ans = ansver(pkg); + * tcp.Write(ans); + * array->clear(); + * delete array; + * + * } + * + */ class ETcpSocket:public QObject { Q_OBJECT diff --git a/sync/config.h b/sync/config.h index ce3eef9..f22598d 100644 --- a/sync/config.h +++ b/sync/config.h @@ -12,6 +12,7 @@ // network config #define DEDAULT_PORT 1239 -#define MAX_SYNC_TIME 10 * 1000 * 1000 // 10 sec on microsec +#define MAX_SYNC_TIME 20 * 1000 // 10 sec on microsec +#define SYNC_TIME 5 * 1000 // 5 sec on microsec #endif // CONFIG_H diff --git a/sync/node.cpp b/sync/node.cpp index f4fde0c..2aeee09 100644 --- a/sync/node.cpp +++ b/sync/node.cpp @@ -6,11 +6,7 @@ namespace syncLib{ package::package(){ - type = package::t_void; - source.clear(); - playdata.run = 0; - playdata.seek = 0; - size = 0; + clear(); } package::package(const QByteArray &array): package::package(){ @@ -24,42 +20,51 @@ Syncer package::getPlayData() const{ return playdata; } -package::TypePackage package::getType() const{ +TypePackage package::getType() const{ return type; } bool package::isValid() const{ switch (type) { - case package::t_void: + case TypePackage::t_void: return false; - case package::t_close: + case TypePackage::t_close: return true; - case package::t_sync: + case TypePackage::t_sync: return playdata.run > 0 && playdata.seek > 0; - case package::t_song: + case TypePackage::t_song: return source.size > 0; - case package::t_stop: + case TypePackage::t_song_h: + return header.size > 0; + case TypePackage::t_stop: return true; default: return false; } } +void package::clear(){ + type = TypePackage::t_void; + source.clear(); + playdata.run = 0; + playdata.seek = 0; +} + QByteArray package::parseTo(){ QByteArray temp; QDataStream stream(temp); temp.clear(); if(isValid()){ switch (type) { - case package::t_void: + case TypePackage::t_void: break; - case package::t_close: + case TypePackage::t_close: stream << int(); stream << (unsigned char)(type); stream.device()->seek(0); stream << temp.size(); break; - case package::t_sync: + case TypePackage::t_sync: stream << int(); stream << (unsigned char)(type); stream << playdata.run; @@ -67,14 +72,21 @@ QByteArray package::parseTo(){ stream.device()->seek(0); stream << temp.size(); break; - case package::t_song: + case TypePackage::t_song: stream << int(); stream << (unsigned char)(type); stream << source; stream.device()->seek(0); stream << temp.size(); break; - case package::t_stop: + case TypePackage::t_song_h: + stream << int(); + stream << (unsigned char)(type); + stream << header; + stream.device()->seek(0); + stream << temp.size(); + break; + case TypePackage::t_stop: stream << int(); stream << (unsigned char)(type); stream.device()->seek(0); @@ -88,21 +100,24 @@ QByteArray package::parseTo(){ } bool package::parseFrom(const QByteArray &array){ - type = t_void; + type = TypePackage::t_void; QDataStream stream(array); switch (type) { - case package::t_void: + case TypePackage::t_void: return false; - case package::t_close: + case TypePackage::t_close: return true; - case package::t_sync: + case TypePackage::t_sync: stream >> playdata.run; stream >> playdata.seek; return isValid(); - case package::t_song: + case TypePackage::t_song: stream >> source; return isValid(); - case package::t_stop: + case TypePackage::t_song_h: + stream >> header; + return isValid(); + case TypePackage::t_stop: return true; default: return isValid(); diff --git a/sync/node.h b/sync/node.h index 86658a4..6006511 100644 --- a/sync/node.h +++ b/sync/node.h @@ -6,6 +6,23 @@ class Syncer; namespace syncLib { +/** + * @brief The TypePackage enum + * t_void - this package empty and not valid. + * t_close - the information about close channel. + * t_sync - the infomation about sync playning media file on network. + * t_song - the package with this type is necessary for translite media data on network. + * t_stop - the package with type 'stop' necessary for stoping playning media files. + */ +enum TypePackage{ + t_void = 0x0, + t_close = 0x1, + t_sync = 0x2, + t_song_h = 0x4, + t_song = 0x8, + t_stop = 0x10 +}; + /** * @brief The package class. Package for translite media data on network * @@ -23,25 +40,11 @@ class package * 4 byte - size of data of package (it avelable if type is t_sync or t_song) * data */ - /** - * @brief The TypePackage enum - * t_void - this package empty and not valid. - * t_close - the information about close channel. - * t_sync - the infomation about sync playning media file on network. - * t_song - the package with this type is necessary for translite media data on network. - * t_stop - the package with type 'stop' necessary for stoping playning media files. - */ - enum TypePackage{ - t_void = 0x0, - t_close = 0x1, - t_sync = 0x2, - t_song = 0x4, - t_stop = 0x8 - }; + private: TypePackage type; - unsigned int size; Song source; + SongHeader header; Syncer playdata; public: package(); @@ -59,8 +62,10 @@ public: Syncer getPlayData() const; TypePackage getType() const; bool isValid() const; + void clear(); QByteArray parseTo(); bool parseFrom(const QByteArray& array); + friend class Sync; }; class Node:public QTcpServer{ diff --git a/sync/song.cpp b/sync/song.cpp index 97a68f9..05ac05f 100644 --- a/sync/song.cpp +++ b/sync/song.cpp @@ -4,7 +4,7 @@ namespace syncLib{ SongHeader::SongHeader() { - this->id = 0; + this->id = -1; this->name = ""; this->size = 0; } diff --git a/sync/song.h b/sync/song.h index c7ba636..a23a084 100644 --- a/sync/song.h +++ b/sync/song.h @@ -7,7 +7,7 @@ /** * @brief Time_point on nanosecunds (uint64_t) */ -typedef quint64 microseconds; +typedef quint64 milliseconds; namespace syncLib { @@ -20,11 +20,11 @@ struct Syncer /** * @brief seek - wher is play media file */ - unsigned int seek; + milliseconds seek; /** * @brief run when is play media file (int) */ - microseconds run; + milliseconds run; }; /** diff --git a/sync/sync.cpp b/sync/sync.cpp index 7f4845d..c90b4a5 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -3,8 +3,6 @@ #include <QMultimedia> #include <QMediaPlayer> #include <QSqlQuery> -#include "song.h" -#include "node.h" #include "exaptions.h" #include "time.h" #include "thread" @@ -55,14 +53,37 @@ int Sync::save(const Song &song){ return qyery->value(0).toInt(); } +bool Sync::load(const SongHeader &song,Song &result){ + result.clear(); + if(song.id > -1){ + QString qyer = QString("SELECT * from %0 where id=%1").arg(DATATABLE_NAME).arg(song.id); + if(!qyery->exec(qyer)){ + return false; + } + }else if(!song.name.isEmpty() && song.size > 0){ + QString qyer = QString("SELECT * from %0 where name=%1 and size=%2").arg(DATATABLE_NAME).arg(song.name).arg(song.size); + if(!qyery->exec(qyer)){ + return false; + } + }else { + return false; + } + + result.id = qyery->value(0).toInt(); + result.name = qyery->value(1).toString(); + result.size = qyery->value(2).toInt(); + result.source = qyery->value(3).toByteArray(); + return true; +} + /* * information about chrono * https://stackoverflow.com/questions/31255486/c-how-do-i-convert-a-stdchronotime-point-to-long-and-back */ -microseconds Sync::now(){ +milliseconds Sync::now(){ auto tim = std::chrono::system_clock::now(); - auto mc = std::chrono::time_point_cast<std::chrono::microseconds>(tim); + auto mc = std::chrono::time_point_cast<std::chrono::milliseconds>(tim); auto epoh = mc.time_since_epoch(); #ifdef QT_DEBUG qDebug() << epoh.count(); @@ -70,29 +91,37 @@ microseconds Sync::now(){ return epoh.count(); } -Clock Sync::from(const microseconds& mc){ - std::chrono::duration<long> dur(mc); +Clock Sync::from(const milliseconds& mc){ + std::chrono::milliseconds dur(mc); return Clock(dur); } +bool Sync::Play(SongHeader &header, Syncer *syncdata){ + QString qyer = QString("SELECT * from %0 where name=%1 and size=%2").arg(DATATABLE_NAME).arg(header.name).arg(header.size); + if(!qyery->exec(qyer)){ + return false; + } + Song song; + song.id = qyery->value(0).toInt(); + song.name = qyery->value(1).toString(); + song.size = qyery->value(2).toInt(); + song.source = qyery->value(3).toByteArray(); + return Sync::Play(song,syncdata); +} + bool Sync::Play(Song& song, Syncer *syncdata){ QBuffer buffer(&song.source); player->setMedia(QMediaContent(), &buffer); - if(syncdata){ - microseconds sync_time = syncdata->run - now(); - if(sync_time > MAX_SYNC_TIME && sync_time <= 0) - return false; - Clock run_time = from(syncdata->run); - do { - std::this_thread::yield(); - } while (std::chrono::high_resolution_clock::now() < run_time); - player->setPosition(syncdata->seek); + if(syncdata && !sync(*syncdata)){ + return false; } + fbroadcaster = !bool(syncdata); player->play(); + playList->push_front(static_cast<SongHeader>(song)); return true; } -bool Sync::Play(int id_song){ +bool Sync::Play(int id_song, Syncer *syncdata){ QString qyer = QString("SELECT * from %0 where id=%1").arg(DATATABLE_NAME).arg(id_song); if(!qyery->exec(qyer)){ @@ -103,7 +132,7 @@ bool Sync::Play(int id_song){ song.name = qyery->value(1).toString(); song.size = qyery->value(2).toInt(); song.source = qyery->value(3).toByteArray(); - return Sync::Play(song); + return Sync::Play(song,syncdata); } bool Sync::Play(QString url){ @@ -136,6 +165,56 @@ void Sync::jump(const int seek){ player->setPosition(seek); } +bool Sync::sync(const Syncer &sync){ + milliseconds sync_time = sync.run - now(); + if(sync_time > MAX_SYNC_TIME && sync_time <= 0) + return false; + Clock run_time = from(sync.run); + do { + std::this_thread::yield(); + } while (std::chrono::high_resolution_clock::now() < run_time); + player->setPosition(sync.seek); + return true; +} + +bool Sync::createPackage(TypePackage type, package &pac){ + pac.clear(); + + if(type & TypePackage::t_close){ + pac.type = type; + + }else if(type & TypePackage::t_sync){ + if(!fbroadcaster) + return false; + + pac.type = type; + pac.playdata.run = now() + SYNC_TIME; + pac.playdata.seek = player->position() + SYNC_TIME; + + }else if(type & TypePackage::t_song_h){ + if(!fbroadcaster || playList->isEmpty()) + return false; + + pac.type = type; + pac.header = playList->front(); + + }else if(type & TypePackage::t_song){ + if(!fbroadcaster || playList->isEmpty()) + return false; + + pac.type = type; + if(!load(playList->front(), pac.source)) + return false; + + }else if(type & TypePackage::t_stop){ + pac.type = type; + + }else{ + return false; + } + return pac.isValid(); +} + Sync::~Sync(){ delete node; delete db; @@ -144,3 +223,4 @@ Sync::~Sync(){ } + diff --git a/sync/sync.h b/sync/sync.h index 2c0c995..c5a4a1a 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -1,6 +1,7 @@ #ifndef SYNC_H #define SYNC_H #include "song.h" +#include "node.h" #include <chrono> class QSqlDatabase; class QMediaPlayer; @@ -21,11 +22,20 @@ private: Node *node; QSqlDatabase *db; QMediaPlayer *player; + QList<SongHeader>* playList; QSqlQuery *qyery; + bool fbroadcaster; /** * @brief initDB initialize local database of song */ void initDB(); + /** + * @brief load song of database; + * @brief song - + * @brief result - the resulting value; + * @return true if everything's done + */ + bool load(const SongHeader &song, Song &result); /** * @brief save media data into local database. * @param song savining media data. @@ -42,14 +52,28 @@ private: * @brief now - get now time on microsecunds * @return - count of microsecunds */ - microseconds now(); + milliseconds now(); /** * @brief from cast to chrono secunds * @param mcrs microseconds of uint_64 * @return microseconds of chrono */ - Clock from(const microseconds &mcrs); + Clock from(const milliseconds &mcrs); + /** + * @brief createPackage - Create a package that shows current state of the node + * @param type - Type of an answer + * @param pac - the resulting value + * @return true if everything's done + */ + bool createPackage(TypePackage type ,package& pac); public: + /** + * @brief Play song in this device, if device has not supported playning media data this method throw MediaExcrption. + * @param header of song + * @param syncdata data of synbced playning of media data. + * @return true if all done else false. + */ + bool Play(SongHeader &header, Syncer* syncdata = nullptr); /** * @brief Play song in this device, if device has not supported playning media data this method throw MediaExcrption. * @param song playning media data. @@ -68,7 +92,7 @@ public: * @param id_song of song. * @return true if all done else false. */ - bool Play(int id_song); + bool Play(int id_song, Syncer* syncdata = nullptr); /** * @brief Pause playning song. */ @@ -82,6 +106,11 @@ public: * @param seek - a new position of media data. */ void jump(const int seek); + /** + * @brief sync with server + * @param sync - data of sync + */ + bool sync(const Syncer& sync); Sync(); ~Sync(); }; From df97b12a6fcf74576fa4fd0c5fa7b59d9d5c82c3 Mon Sep 17 00:00:00 2001 From: MasatoNakamoto <MasatoNakamoto@gmail.com> Date: Tue, 21 Nov 2017 16:44:55 +0300 Subject: [PATCH 11/14] fix package parse --- sync/node.cpp | 139 ++++++++++++++++++++++++++------------------------ sync/node.h | 13 ++--- sync/sync.cpp | 21 ++++---- 3 files changed, 89 insertions(+), 84 deletions(-) diff --git a/sync/node.cpp b/sync/node.cpp index 2aeee09..3db9f6b 100644 --- a/sync/node.cpp +++ b/sync/node.cpp @@ -25,22 +25,45 @@ TypePackage package::getType() const{ } bool package::isValid() const{ - switch (type) { - case TypePackage::t_void: - return false; - case TypePackage::t_close: - return true; - case TypePackage::t_sync: - return playdata.run > 0 && playdata.seek > 0; - case TypePackage::t_song: - return source.size > 0; - case TypePackage::t_song_h: - return header.size > 0; - case TypePackage::t_stop: - return true; - default: + + bool ret = true; + if(type == TypePackage::t_void){ return false; + } + + if(type & TypePackage::t_play){ + ret = ret && true; + + } + + if(type & TypePackage::t_sync){ + ret = ret && (playdata.run > 0 && playdata.seek > 0); + + } + + if(type & TypePackage::t_song_h){ + ret = ret && header.size > 0; + + } + + if(type & TypePackage::t_song){ + ret = ret && source.size > 0; + + } + + if(type & TypePackage::t_close){ + ret = ret && true; + + } + + if(type & TypePackage::t_stop){ + ret = ret && true; + + } + + return ret; + } void package::clear(){ @@ -55,46 +78,24 @@ QByteArray package::parseTo(){ QDataStream stream(temp); temp.clear(); if(isValid()){ - switch (type) { - case TypePackage::t_void: - break; - case TypePackage::t_close: - stream << int(); - stream << (unsigned char)(type); - stream.device()->seek(0); - stream << temp.size(); - break; - case TypePackage::t_sync: - stream << int(); - stream << (unsigned char)(type); + stream << static_cast<unsigned char>(type); + + if(type & TypePackage::t_sync){ stream << playdata.run; stream << playdata.seek; - stream.device()->seek(0); - stream << temp.size(); - break; - case TypePackage::t_song: - stream << int(); - stream << (unsigned char)(type); - stream << source; - stream.device()->seek(0); - stream << temp.size(); - break; - case TypePackage::t_song_h: - stream << int(); - stream << (unsigned char)(type); - stream << header; - stream.device()->seek(0); - stream << temp.size(); - break; - case TypePackage::t_stop: - stream << int(); - stream << (unsigned char)(type); - stream.device()->seek(0); - stream << temp.size(); - break; - default: - break; + } + + if(type & TypePackage::t_song_h){ + stream << header; + + } + + if(type & TypePackage::t_song){ + stream << source; + + } + } return temp; } @@ -102,26 +103,28 @@ QByteArray package::parseTo(){ bool package::parseFrom(const QByteArray &array){ type = TypePackage::t_void; QDataStream stream(array); - switch (type) { - case TypePackage::t_void: - return false; - case TypePackage::t_close: - return true; - case TypePackage::t_sync: + + unsigned char temp_type; + stream >> temp_type; + type = static_cast<TypePackage> (temp_type); + + if(type & TypePackage::t_sync){ stream >> playdata.run; stream >> playdata.seek; - return isValid(); - case TypePackage::t_song: - stream >> source; - return isValid(); - case TypePackage::t_song_h: - stream >> header; - return isValid(); - case TypePackage::t_stop: - return true; - default: - return isValid(); + } + + if(type & TypePackage::t_song_h){ + stream >> header; + + } + + if(type & TypePackage::t_song){ + stream >> source; + + } + + return isValid(); } Node::Node():QTcpServer(){ diff --git a/sync/node.h b/sync/node.h index 6006511..02a419e 100644 --- a/sync/node.h +++ b/sync/node.h @@ -15,12 +15,13 @@ namespace syncLib { * t_stop - the package with type 'stop' necessary for stoping playning media files. */ enum TypePackage{ - t_void = 0x0, - t_close = 0x1, - t_sync = 0x2, - t_song_h = 0x4, - t_song = 0x8, - t_stop = 0x10 + t_void = 0x00, + t_play = 0x01, + t_sync = 0x02, + t_song_h = 0x04, + t_song = 0x08, + t_close = 0x10, + t_stop = 0x20 }; /** diff --git a/sync/sync.cpp b/sync/sync.cpp index c90b4a5..5c2619a 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -116,6 +116,8 @@ bool Sync::Play(Song& song, Syncer *syncdata){ return false; } fbroadcaster = !bool(syncdata); +// if(fbroadcaster){ +// } player->play(); playList->push_front(static_cast<SongHeader>(song)); return true; @@ -180,10 +182,9 @@ bool Sync::sync(const Syncer &sync){ bool Sync::createPackage(TypePackage type, package &pac){ pac.clear(); - if(type & TypePackage::t_close){ - pac.type = type; + pac.type = type; - }else if(type & TypePackage::t_sync){ + if(type & TypePackage::t_sync){ if(!fbroadcaster) return false; @@ -191,14 +192,18 @@ bool Sync::createPackage(TypePackage type, package &pac){ pac.playdata.run = now() + SYNC_TIME; pac.playdata.seek = player->position() + SYNC_TIME; - }else if(type & TypePackage::t_song_h){ + } + + if(type & TypePackage::t_song_h){ if(!fbroadcaster || playList->isEmpty()) return false; pac.type = type; pac.header = playList->front(); - }else if(type & TypePackage::t_song){ + } + + if(type & TypePackage::t_song){ if(!fbroadcaster || playList->isEmpty()) return false; @@ -206,12 +211,8 @@ bool Sync::createPackage(TypePackage type, package &pac){ if(!load(playList->front(), pac.source)) return false; - }else if(type & TypePackage::t_stop){ - pac.type = type; - - }else{ - return false; } + return pac.isValid(); } From 1dd34adac5860b6f4ad7d6ade9453b19e7be1031 Mon Sep 17 00:00:00 2001 From: MasatoNakamoto <MasatoNakamoto@gmail.com> Date: Wed, 22 Nov 2017 20:05:53 +0300 Subject: [PATCH 12/14] added new package render --- sync/exaptions.h | 16 ++++++++++++++++ sync/node.cpp | 10 +++++++--- sync/node.h | 18 ++++++++++-------- sync/sync.cpp | 44 +++++++++++++++++++++++++++++++++++++++++--- sync/sync.h | 20 +++++++++++++++++++- 5 files changed, 93 insertions(+), 15 deletions(-) diff --git a/sync/exaptions.h b/sync/exaptions.h index 3cb196c..4c2f02e 100644 --- a/sync/exaptions.h +++ b/sync/exaptions.h @@ -23,4 +23,20 @@ public: } }; +class createPackageExaption:public std::exception +{ +public: + QString what(){ + return QObject::tr("Сould not generate network packet"); + } +}; + +class badAnswerExaption:public std::exception +{ +public: + QString what(){ + return QObject::tr("could not parse message nodes."); + } +}; + #endif // EXAPTIONS_H diff --git a/sync/node.cpp b/sync/node.cpp index 3db9f6b..939d136 100644 --- a/sync/node.cpp +++ b/sync/node.cpp @@ -131,15 +131,18 @@ Node::Node():QTcpServer(){ connect(this,SIGNAL(acceptError(QAbstractSocket::SocketError)),SLOT(acceptError_(QAbstractSocket::SocketError))); connect(this,SIGNAL(newConnection()),SLOT(newConnection_())); } + void Node::acceptError_(ETcpSocket*c){ c->getSource()->close(); clients.removeOne(c); emit ClientDisconnected(c); delete c; } + QList<ETcpSocket*>* Node::getClients(){ return &clients; } + void Node::newConnection_(){ ETcpSocket *newClient=new ETcpSocket(nextPendingConnection()); clients.push_back(newClient); @@ -147,16 +150,17 @@ void Node::newConnection_(){ connect(newClient,SIGNAL(Message(ETcpSocket*)),this,SLOT(readData(ETcpSocket*))); emit ClientConnected(newClient); } + void Node::readData(ETcpSocket *c){ - package _package; - _package.parseFrom(*c->topStack()); - emit Message(_package,c); + emit Message(c); } + void Node::WriteAll(const QByteArray &data){ for(ETcpSocket*i:clients){ i->getSource()->write(data); } } + void Node::disconnectClient(ETcpSocket *c){ c->getSource()->close(); clients.removeOne(c); diff --git a/sync/node.h b/sync/node.h index 02a419e..29f4253 100644 --- a/sync/node.h +++ b/sync/node.h @@ -15,13 +15,15 @@ namespace syncLib { * t_stop - the package with type 'stop' necessary for stoping playning media files. */ enum TypePackage{ - t_void = 0x00, - t_play = 0x01, - t_sync = 0x02, - t_song_h = 0x04, - t_song = 0x08, - t_close = 0x10, - t_stop = 0x20 + t_void = 0x00, + t_play = 0x01, + t_sync = 0x02, + t_song_h = 0x04, + t_song = 0x08, + t_close = 0x10, + t_stop = 0x20, + t_what = 0x40, + t_brodcaster = 0x80 }; /** @@ -87,7 +89,7 @@ public: ~Node(); signals: void Error(QString); - void Message(const package&,ETcpSocket*); + void Message(ETcpSocket*); void ClientDisconnected(ETcpSocket*); void ClientConnected(ETcpSocket*); }; diff --git a/sync/sync.cpp b/sync/sync.cpp index 5c2619a..e3a674a 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -21,6 +21,8 @@ Sync::Sync(){ if(!player->isAvailable()){ throw MediaException(); } + initDB(); + connect(node,SIGNAL(Message(ETcpSocket*)),SLOT(packageRender(ETcpSocket*))); } void Sync::initDB(){ @@ -188,7 +190,6 @@ bool Sync::createPackage(TypePackage type, package &pac){ if(!fbroadcaster) return false; - pac.type = type; pac.playdata.run = now() + SYNC_TIME; pac.playdata.seek = player->position() + SYNC_TIME; @@ -198,7 +199,6 @@ bool Sync::createPackage(TypePackage type, package &pac){ if(!fbroadcaster || playList->isEmpty()) return false; - pac.type = type; pac.header = playList->front(); } @@ -207,19 +207,57 @@ bool Sync::createPackage(TypePackage type, package &pac){ if(!fbroadcaster || playList->isEmpty()) return false; - pac.type = type; if(!load(playList->front(), pac.source)) return false; } + if(fbroadcaster) + pac.type = TypePackage(pac.type | t_brodcaster); return pac.isValid(); } +void Sync::packageRender(ETcpSocket *socket){ + + QByteArray *array; + while((array = socket->topStack())){ + package pkg; + if(!pkg.parseFrom((*array))){ + throw badAnswerExaption(); + } +// package answer; + +// scaning servers + if(pkg.getType() & t_brodcaster && servers.indexOf(socket) == -1){ + servers.append(socket); + } + + if(!(pkg.getType() & t_brodcaster) && servers.indexOf(socket) != -1){ + servers.removeOne(socket); + } + + +// socket.Write(ans); + array->clear(); + delete array; + + } +} + +void Sync::rescan(bool){ + package pac; + if(!createPackage(t_what,pac)){ + throw createPackageExaption(); + return; + } + node->WriteAll(pac.parseTo()); +} + Sync::~Sync(){ delete node; delete db; delete player; + servers.clear(); } } diff --git a/sync/sync.h b/sync/sync.h index c5a4a1a..4b824b7 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -16,15 +16,25 @@ class Node; * @brief The Sync class is main class of this library. * the 'sync' has supported synced playning media files on network and saving media data into local database. */ -class Sync +class Sync : public QObject { + Q_OBJECT private: Node *node; QSqlDatabase *db; QMediaPlayer *player; QList<SongHeader>* playList; QSqlQuery *qyery; + QList<ETcpSocket*> servers; bool fbroadcaster; + + + + /** + * @brief rescan - search for existing servers + * result saved in servers + */ + void rescan(bool global = false); /** * @brief initDB initialize local database of song */ @@ -66,6 +76,14 @@ private: * @return true if everything's done */ bool createPackage(TypePackage type ,package& pac); +private slots: + + /** + * @brief packageRender - the handler of all messages received. + * @param socket + */ + void packageRender(ETcpSocket* socket); + public: /** * @brief Play song in this device, if device has not supported playning media data this method throw MediaExcrption. From ed8d77121e87001b47be740e3929cee9379926c1 Mon Sep 17 00:00:00 2001 From: EndrII <EndrIIMail@gmail.com> Date: Wed, 22 Nov 2017 22:34:55 +0300 Subject: [PATCH 13/14] added local scaner --- sync/LocalScanner.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++ sync/LocalScanner.h | 29 ++++++++++++++++++ sync/config.h | 3 +- sync/sync.cpp | 21 ++++++++++++- sync/sync.h | 9 ++++-- sync/sync.pro | 6 ++-- 6 files changed, 131 insertions(+), 6 deletions(-) create mode 100755 sync/LocalScanner.cpp create mode 100755 sync/LocalScanner.h diff --git a/sync/LocalScanner.cpp b/sync/LocalScanner.cpp new file mode 100755 index 0000000..1c6da23 --- /dev/null +++ b/sync/LocalScanner.cpp @@ -0,0 +1,69 @@ +#include "LocalScanner.h" +#include "config.h" + +LocalScanner::LocalScanner(): + QObject() +{ + wiat.setInterval(1000); + connect(&wiat,SIGNAL(timeout()),SLOT(scaned_())); +} + +void LocalScanner::clear(){ + results.clear(); +} + +void LocalScanner::setInterval(int msec){ + wiat.setInterval(msec); +} + +void LocalScanner::clearSocets(){ + for(ETcpSocket* i:socets) + delete i; + socets.clear(); +} + +QHostAddress LocalScanner::thisAdress(){ + QList<QHostAddress> adress= QNetworkInterface::allAddresses(); + for(QHostAddress &ip:adress) + if(ip.protocol() == QAbstractSocket::IPv4Protocol && ip != QHostAddress(QHostAddress::LocalHost)) + return ip; + return QHostAddress::LocalHost; +} + +void LocalScanner::scane(){ + if(!socets.empty()) + return ; + QList<QHostAddress> adress= QNetworkInterface::allAddresses(); + clear(); + wiat.start(); + for(QHostAddress &ip:adress){ + if(ip.protocol() == QAbstractSocket::IPv4Protocol && ip != QHostAddress(QHostAddress::LocalHost)){ + for(int i=0;i<256;i++){ + QString adr= ip.toString(); + adr=adr.left(adr.lastIndexOf("."))+"."+QString::number(i); + ETcpSocket *temp=new ETcpSocket; + connect(temp,SIGNAL(Connected(ETcpSocket*)),SLOT(connected(ETcpSocket*))); + temp->getSource()->connectToHost(adr,DEDAULT_PORT); + socets.push_back(temp); + } + } + } +} + +void LocalScanner::scaned_(){ + wiat.stop(); + emit scaned(&results); + clearSocets(); +} + +void LocalScanner::connected(ETcpSocket *c){ + socets.removeOne(c); + results.push_back(c); +} + +LocalScanner::~LocalScanner(){ + for(ETcpSocket* i: socets) + delete i; + socets.clear(); + +} diff --git a/sync/LocalScanner.h b/sync/LocalScanner.h new file mode 100755 index 0000000..0db7ada --- /dev/null +++ b/sync/LocalScanner.h @@ -0,0 +1,29 @@ +#ifndef LocalServers_H +#define LocalServers_H +#include <QNetworkInterface> +#include <QHostInfo> +#include <QList> +#include <QTimer> +#include "ETcpSocket.h" + +class LocalScanner:public QObject{ + Q_OBJECT +private: + QList<ETcpSocket*> socets; + QList<ETcpSocket*> results; + QTimer wiat; + void clear(); + void clearSocets(); +private slots: + void scaned_(); + void connected(ETcpSocket *); +public: + void scane(); + void setInterval(int msec); + static QHostAddress thisAdress(); + LocalScanner(); + ~LocalScanner(); +signals: + void scaned(QList<ETcpSocket*>*); +}; +#endif // LocalServers_H diff --git a/sync/config.h b/sync/config.h index f22598d..5ae3218 100644 --- a/sync/config.h +++ b/sync/config.h @@ -12,7 +12,8 @@ // network config #define DEDAULT_PORT 1239 -#define MAX_SYNC_TIME 20 * 1000 // 10 sec on microsec +#define MAX_SYNC_TIME 20 * 1000 // 10 sec on microsec #define SYNC_TIME 5 * 1000 // 5 sec on microsec +#define DEEP_SCANER_INTERVAL 10000 // 10 sec #endif // CONFIG_H diff --git a/sync/sync.cpp b/sync/sync.cpp index e3a674a..13b0f7a 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -23,6 +23,8 @@ Sync::Sync(){ } initDB(); connect(node,SIGNAL(Message(ETcpSocket*)),SLOT(packageRender(ETcpSocket*))); + connect(&deepScaner,SIGNAL(scaned(QList<ETcpSocket*>*)),SLOT(deepScaned(QList<ETcpSocket*>*))); + } void Sync::initDB(){ @@ -244,13 +246,30 @@ void Sync::packageRender(ETcpSocket *socket){ } } -void Sync::rescan(bool){ +void Sync::rescan(bool deep){ package pac; if(!createPackage(t_what,pac)){ throw createPackageExaption(); return; } node->WriteAll(pac.parseTo()); + + if(deep){ + deepScaner.setInterval(DEEP_SCANER_INTERVAL); + deepScaner.scane(); + } +} + +void Sync::deepScaned(QList<ETcpSocket *> * list){ + package pac; + if(!createPackage(t_what,pac)){ + throw createPackageExaption(); + return; + } + QByteArray array = pac.parseTo(); + for(ETcpSocket * i: *list){ + i->Write(array); + } } Sync::~Sync(){ diff --git a/sync/sync.h b/sync/sync.h index 4b824b7..e3a3fc2 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -2,6 +2,7 @@ #define SYNC_H #include "song.h" #include "node.h" +#include "LocalScanner.h" #include <chrono> class QSqlDatabase; class QMediaPlayer; @@ -27,14 +28,14 @@ private: QSqlQuery *qyery; QList<ETcpSocket*> servers; bool fbroadcaster; - + LocalScanner deepScaner; /** * @brief rescan - search for existing servers * result saved in servers */ - void rescan(bool global = false); + void rescan(bool deep = false); /** * @brief initDB initialize local database of song */ @@ -83,6 +84,10 @@ private slots: * @param socket */ void packageRender(ETcpSocket* socket); + /** + * @brief deepScaned scaning in local network + */ + void deepScaned(QList<ETcpSocket *> *); public: /** diff --git a/sync/sync.pro b/sync/sync.pro index 7afcbd9..a7e7377 100644 --- a/sync/sync.pro +++ b/sync/sync.pro @@ -27,7 +27,8 @@ SOURCES += \ sync.cpp \ song.cpp \ node.cpp \ - ETcpSocket.cpp + ETcpSocket.cpp \ + LocalScanner.cpp HEADERS += \ sync.h \ @@ -35,7 +36,8 @@ HEADERS += \ node.h \ config.h \ exaptions.h \ - ETcpSocket.h + ETcpSocket.h \ + LocalScanner.h unix { target.path = /usr/lib INSTALLS += target From 5515846b2fe200aaa7cdfd7953170aac328443be Mon Sep 17 00:00:00 2001 From: EndrII <EndrIIMail@gmail.com> Date: Fri, 24 Nov 2017 21:17:41 +0300 Subject: [PATCH 14/14] synchronization library completed --- sync/ETcpSocket.cpp | 2 +- sync/LocalScanner.cpp | 1 - sync/exaptions.h | 22 ++++++- sync/node.cpp | 11 +++- sync/node.h | 19 ++++-- sync/sync.cpp | 134 +++++++++++++++++++++++++++++++----------- sync/sync.h | 12 ++-- 7 files changed, 147 insertions(+), 54 deletions(-) diff --git a/sync/ETcpSocket.cpp b/sync/ETcpSocket.cpp index 39b2f98..c78b20a 100755 --- a/sync/ETcpSocket.cpp +++ b/sync/ETcpSocket.cpp @@ -15,7 +15,7 @@ ETcpSocket::ETcpSocket(QTcpSocket*ptr) ETcpSocket::ETcpSocket(const QString& address, int port){ source = new QTcpSocket(); if(!source->bind(QHostAddress(address),port) || !source->open(QIODevice::ReadWrite)){ - throw addNodeExaption(); + throw AddNodeExaption(); } init(); } diff --git a/sync/LocalScanner.cpp b/sync/LocalScanner.cpp index 1c6da23..9dc76fb 100755 --- a/sync/LocalScanner.cpp +++ b/sync/LocalScanner.cpp @@ -57,7 +57,6 @@ void LocalScanner::scaned_(){ } void LocalScanner::connected(ETcpSocket *c){ - socets.removeOne(c); results.push_back(c); } diff --git a/sync/exaptions.h b/sync/exaptions.h index 4c2f02e..54a9126 100644 --- a/sync/exaptions.h +++ b/sync/exaptions.h @@ -15,7 +15,7 @@ public: } }; -class addNodeExaption:public std::exception +class AddNodeExaption:public std::exception { public: QString what(){ @@ -23,7 +23,7 @@ public: } }; -class createPackageExaption:public std::exception +class CreatePackageExaption:public std::exception { public: QString what(){ @@ -31,7 +31,7 @@ public: } }; -class badAnswerExaption:public std::exception +class BadAnswerExaption:public std::exception { public: QString what(){ @@ -39,4 +39,20 @@ public: } }; +class BrodcastConflict:public std::exception +{ +public: + QString what(){ + return QObject::tr("The server received the packet from the server."); + } +}; + +class SyncError:public std::exception +{ +public: + QString what(){ + return QObject::tr("The playlist is empty, the player has nothing to play."); + } +}; + #endif // EXAPTIONS_H diff --git a/sync/node.cpp b/sync/node.cpp index 939d136..5b09839 100644 --- a/sync/node.cpp +++ b/sync/node.cpp @@ -12,15 +12,20 @@ package::package(const QByteArray &array): package::package(){ parseFrom(array); } + +const SongHeader& package::getHeader() const{ + return header; +} + const Song& package::getSong() const{ return source; } -Syncer package::getPlayData() const{ +const Syncer& package::getPlayData() const{ return playdata; } -TypePackage package::getType() const{ +const Type& package::getType() const{ return type; } @@ -172,7 +177,7 @@ bool Node::addNode(const QString &node,int port){ try{ temp = new ETcpSocket(node,port); - }catch(addNodeExaption &e){ + }catch(AddNodeExaption &e){ #ifdef QT_DEBUG qDebug() << e.what(); #endif diff --git a/sync/node.h b/sync/node.h index 29f4253..6bc2e4a 100644 --- a/sync/node.h +++ b/sync/node.h @@ -6,6 +6,8 @@ class Syncer; namespace syncLib { +typedef unsigned char Type; + /** * @brief The TypePackage enum * t_void - this package empty and not valid. @@ -17,9 +19,9 @@ namespace syncLib { enum TypePackage{ t_void = 0x00, t_play = 0x01, - t_sync = 0x02, - t_song_h = 0x04, - t_song = 0x08, + t_song_h = 0x02, + t_song = 0x04, + t_sync = 0x08, t_close = 0x10, t_stop = 0x20, t_what = 0x40, @@ -45,7 +47,7 @@ class package */ private: - TypePackage type; + Type type; Song source; SongHeader header; Syncer playdata; @@ -53,6 +55,11 @@ public: package(); package(const QByteArray& array); ~package(); + /** + * @brief getHeader + * @return Header of the song + */ + const SongHeader& getHeader() const; /** * @brief getSong * @return Song @@ -62,8 +69,8 @@ public: * @brief getPlayTime * @return time of playning media data */ - Syncer getPlayData() const; - TypePackage getType() const; + const Syncer &getPlayData() const; + const Type& getType() const; bool isValid() const; void clear(); QByteArray parseTo(); diff --git a/sync/sync.cpp b/sync/sync.cpp index 13b0f7a..16d674d 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -100,7 +100,7 @@ Clock Sync::from(const milliseconds& mc){ return Clock(dur); } -bool Sync::Play(SongHeader &header, Syncer *syncdata){ +bool Sync::play(const SongHeader &header, const Syncer *syncdata){ QString qyer = QString("SELECT * from %0 where name=%1 and size=%2").arg(DATATABLE_NAME).arg(header.name).arg(header.size); if(!qyery->exec(qyer)){ return false; @@ -110,24 +110,31 @@ bool Sync::Play(SongHeader &header, Syncer *syncdata){ song.name = qyery->value(1).toString(); song.size = qyery->value(2).toInt(); song.source = qyery->value(3).toByteArray(); - return Sync::Play(song,syncdata); + return Sync::play(song,syncdata); } -bool Sync::Play(Song& song, Syncer *syncdata){ +bool Sync::play(Song &song, Syncer *syncdata){ QBuffer buffer(&song.source); player->setMedia(QMediaContent(), &buffer); if(syncdata && !sync(*syncdata)){ return false; } + fbroadcaster = !bool(syncdata); -// if(fbroadcaster){ -// } + if(fbroadcaster){ + package pac; + if(!createPackage(t_song_h | t_sync, pac)){ + throw CreatePackageExaption(); + } + node->WriteAll(pac.parseTo()); + } + player->play(); playList->push_front(static_cast<SongHeader>(song)); return true; } -bool Sync::Play(int id_song, Syncer *syncdata){ +bool Sync::play(int id_song, Syncer *syncdata){ QString qyer = QString("SELECT * from %0 where id=%1").arg(DATATABLE_NAME).arg(id_song); if(!qyery->exec(qyer)){ @@ -138,10 +145,10 @@ bool Sync::Play(int id_song, Syncer *syncdata){ song.name = qyery->value(1).toString(); song.size = qyery->value(2).toInt(); song.source = qyery->value(3).toByteArray(); - return Sync::Play(song,syncdata); + return Sync::play(song,syncdata); } -bool Sync::Play(QString url){ +bool Sync::play(QString url){ QFile f(url); if(!f.open(QIODevice::ReadOnly)){ return false; @@ -156,10 +163,10 @@ bool Sync::Play(QString url){ song.id = Sync::save(song); if(song.id < 0) return false; - return Sync::Play(song); + return Sync::play(song); } -void Sync::Pause(){ +void Sync::pause(){ player->pause(); } @@ -183,36 +190,35 @@ bool Sync::sync(const Syncer &sync){ return true; } -bool Sync::createPackage(TypePackage type, package &pac){ +bool Sync::createPackage(Type type, package &pac){ pac.clear(); pac.type = type; - if(type & TypePackage::t_sync){ - if(!fbroadcaster) - return false; + if(type & TypePackage::t_sync && fbroadcaster){ pac.playdata.run = now() + SYNC_TIME; pac.playdata.seek = player->position() + SYNC_TIME; } - if(type & TypePackage::t_song_h){ - if(!fbroadcaster || playList->isEmpty()) + if(type & TypePackage::t_song_h && fbroadcaster){ + if(playList->isEmpty()) return false; pac.header = playList->front(); } - if(type & TypePackage::t_song){ - if(!fbroadcaster || playList->isEmpty()) + if(type & TypePackage::t_song && fbroadcaster){ + if(playList->isEmpty()) return false; if(!load(playList->front(), pac.source)) return false; } + if(fbroadcaster) pac.type = TypePackage(pac.type | t_brodcaster); @@ -223,25 +229,85 @@ void Sync::packageRender(ETcpSocket *socket){ QByteArray *array; while((array = socket->topStack())){ - package pkg; - if(!pkg.parseFrom((*array))){ - throw badAnswerExaption(); - } + package pkg; + if(!pkg.parseFrom((*array))){ + throw BadAnswerExaption(); + continue; + } // package answer; -// scaning servers - if(pkg.getType() & t_brodcaster && servers.indexOf(socket) == -1){ - servers.append(socket); - } +// scaning servers - if(!(pkg.getType() & t_brodcaster) && servers.indexOf(socket) != -1){ - servers.removeOne(socket); - } + if(pkg.getType() & t_brodcaster && servers.indexOf(socket) == -1){ + servers.append(socket); + } + if(!(pkg.getType() & t_brodcaster) && servers.indexOf(socket) != -1){ + servers.removeOne(socket); + } -// socket.Write(ans); - array->clear(); - delete array; + if(fbroadcaster == (pkg.getType() & t_brodcaster)){ + throw BrodcastConflict(); + return; + } + + if(pkg.getType() & t_brodcaster){ + +// if requst from server + + if(pkg.getType() & t_play){ + player->play(); + } + + if((pkg.getType() & t_song_h) && !play(pkg.getHeader(), &pkg.getPlayData())){ + if((pkg.getType() & t_song) && !play(pkg.getSong(), &pkg.getPlayData())){ + package answer; + if(!createPackage(t_song | t_sync, answer)){ + throw CreatePackageExaption(); + } + socket->Write(answer.parseTo()); + + } + } + + if(pkg.getType() & t_close){ + socket->getSource()->close(); + node->getClients()->removeOne(socket); + delete socket; + } + + if(pkg.getType() & t_what){ + package answer; + if(!createPackage(t_void, answer)){ + throw CreatePackageExaption(); + } + socket->Write(answer.parseTo()); + } + + if(pkg.getType() & t_sync){ + if(playList->empty()){ + throw SyncError(); + } + } + + }else{ + + package answer; + if(!createPackage(pkg.getType() | ~t_what | ~t_play | ~t_stop | ~t_brodcaster, answer)){ + throw CreatePackageExaption(); + } + socket->Write(answer.parseTo()); + + if(pkg.getType() & t_close){ + socket->getSource()->close(); + node->getClients()->removeOne(socket); + delete socket; + } + + } + + array->clear(); + delete array; } } @@ -249,7 +315,7 @@ void Sync::packageRender(ETcpSocket *socket){ void Sync::rescan(bool deep){ package pac; if(!createPackage(t_what,pac)){ - throw createPackageExaption(); + throw CreatePackageExaption(); return; } node->WriteAll(pac.parseTo()); @@ -263,7 +329,7 @@ void Sync::rescan(bool deep){ void Sync::deepScaned(QList<ETcpSocket *> * list){ package pac; if(!createPackage(t_what,pac)){ - throw createPackageExaption(); + throw CreatePackageExaption(); return; } QByteArray array = pac.parseTo(); diff --git a/sync/sync.h b/sync/sync.h index e3a3fc2..d64967e 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -76,7 +76,7 @@ private: * @param pac - the resulting value * @return true if everything's done */ - bool createPackage(TypePackage type ,package& pac); + bool createPackage(Type type ,package& pac); private slots: /** @@ -96,30 +96,30 @@ public: * @param syncdata data of synbced playning of media data. * @return true if all done else false. */ - bool Play(SongHeader &header, Syncer* syncdata = nullptr); + bool play(const SongHeader &header, const Syncer *syncdata = nullptr); /** * @brief Play song in this device, if device has not supported playning media data this method throw MediaExcrption. * @param song playning media data. * @param syncdata data of synbced playning of media data. * @return true if all done else false. */ - bool Play(Song &song, Syncer* syncdata = nullptr); + bool play(Song &song, Syncer *syncdata = nullptr); /** * @brief Play song from local media file. * @param url of local media file. * @return true if all done else false. */ - bool Play(QString url); + bool play(QString url); /** * @brief Play song from local database by id. * @param id_song of song. * @return true if all done else false. */ - bool Play(int id_song, Syncer* syncdata = nullptr); + bool play(int id_song, Syncer* syncdata = nullptr); /** * @brief Pause playning song. */ - void Pause(); + void pause(); /** * @brief stop playning song. */