mirror of
https://github.com/QuasarApp/SoundBand.git
synced 2025-04-26 23:34:32 +00:00
commit
7b6e435460
@ -34,7 +34,9 @@ SOURCES += main.cpp \
|
|||||||
serverlistmodel.cpp \
|
serverlistmodel.cpp \
|
||||||
playlistsmodel.cpp \
|
playlistsmodel.cpp \
|
||||||
currentplaylistmodel.cpp \
|
currentplaylistmodel.cpp \
|
||||||
../sync/playlist.cpp
|
../sync/playlist.cpp \
|
||||||
|
../sync/syncpackage.cpp \
|
||||||
|
../sync/basepackage.cpp
|
||||||
|
|
||||||
|
|
||||||
RESOURCES += qml.qrc
|
RESOURCES += qml.qrc
|
||||||
@ -71,5 +73,7 @@ HEADERS += \
|
|||||||
serverlistmodel.h \
|
serverlistmodel.h \
|
||||||
playlistsmodel.h \
|
playlistsmodel.h \
|
||||||
currentplaylistmodel.h \
|
currentplaylistmodel.h \
|
||||||
../sync/playlist.h
|
../sync/playlist.h \
|
||||||
|
../sync/syncpackage.h \
|
||||||
|
../sync/basepackage.h
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include "currentplaylistmodel.h"
|
#include "currentplaylistmodel.h"
|
||||||
|
|
||||||
using namespace syncLib;
|
|
||||||
|
|
||||||
CurrentPlayListModel::CurrentPlayListModel(QObject *parent) :
|
CurrentPlayListModel::CurrentPlayListModel(QObject *parent) :
|
||||||
QAbstractListModel(parent),
|
QAbstractListModel(parent),
|
||||||
syncEngine(nullptr),
|
syncEngine(nullptr),
|
||||||
@ -47,13 +45,13 @@ void CurrentPlayListModel::fetchMore(const QModelIndex & /* index */)
|
|||||||
int remainder = playList->size() - itemCount;
|
int remainder = playList->size() - itemCount;
|
||||||
int itemsToFetch = qMin(100, remainder);
|
int itemsToFetch = qMin(100, remainder);
|
||||||
|
|
||||||
if(itemsToFetch < 0){
|
if (itemsToFetch < 0) {
|
||||||
beginRemoveRows(QModelIndex(), 0, 0 - itemsToFetch - 1 );
|
beginRemoveRows(QModelIndex(), 0, 0 - itemsToFetch - 1 );
|
||||||
|
|
||||||
itemCount += itemsToFetch;
|
itemCount += itemsToFetch;
|
||||||
|
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}else{
|
} else if (itemsToFetch > 0) {
|
||||||
beginInsertRows(QModelIndex(), itemCount, itemCount + itemsToFetch - 1);
|
beginInsertRows(QModelIndex(), itemCount, itemCount + itemsToFetch - 1);
|
||||||
|
|
||||||
itemCount += itemsToFetch;
|
itemCount += itemsToFetch;
|
||||||
@ -78,10 +76,8 @@ QVariant CurrentPlayListModel::data(const QModelIndex &index, int role) const
|
|||||||
switch (role) {
|
switch (role) {
|
||||||
case nameRole:
|
case nameRole:
|
||||||
return playList->at(index.row()).name;
|
return playList->at(index.row()).name;
|
||||||
break;
|
|
||||||
case idRole:
|
case idRole:
|
||||||
return playList->at(index.row()).id;
|
return playList->at(index.row()).id;
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ class CurrentPlayListModel : public QAbstractListModel
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
SyncEngine * syncEngine;
|
SyncEngine * syncEngine;
|
||||||
const QList<syncLib::SongStorage> *playList;
|
const QList<SongStorage> *playList;
|
||||||
int itemCount;
|
int itemCount;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include "playlistmodel.h"
|
#include "playlistmodel.h"
|
||||||
|
|
||||||
using namespace syncLib;
|
|
||||||
|
|
||||||
PlayListModel::PlayListModel(QObject *parent) :
|
PlayListModel::PlayListModel(QObject *parent) :
|
||||||
QAbstractListModel(parent),
|
QAbstractListModel(parent),
|
||||||
syncEngine(nullptr)
|
syncEngine(nullptr)
|
||||||
@ -55,7 +53,7 @@ void PlayListModel::fetchMore(const QModelIndex & /* index */)
|
|||||||
itemCount += itemsToFetch;
|
itemCount += itemsToFetch;
|
||||||
|
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}else{
|
}else if (itemsToFetch > 0){
|
||||||
beginInsertRows(QModelIndex(), itemCount, itemCount + itemsToFetch - 1);
|
beginInsertRows(QModelIndex(), itemCount, itemCount + itemsToFetch - 1);
|
||||||
|
|
||||||
itemCount += itemsToFetch;
|
itemCount += itemsToFetch;
|
||||||
@ -94,7 +92,7 @@ QVariant PlayListModel::data(const QModelIndex &index, int role) const
|
|||||||
|
|
||||||
bool PlayListModel::select(int id){
|
bool PlayListModel::select(int id){
|
||||||
|
|
||||||
for(QList<syncLib::SongStorage>::Iterator i = playList.begin(); i < playList.end(); i++){
|
for(QList<SongStorage>::Iterator i = playList.begin(); i < playList.end(); i++){
|
||||||
if(i->id == id){
|
if(i->id == id){
|
||||||
|
|
||||||
if((i->isSelected = !i->isSelected)){
|
if((i->isSelected = !i->isSelected)){
|
||||||
@ -114,7 +112,7 @@ bool PlayListModel::select(int id){
|
|||||||
QList<int> PlayListModel::getSelected(){
|
QList<int> PlayListModel::getSelected(){
|
||||||
QList<int> result;
|
QList<int> result;
|
||||||
|
|
||||||
for(QList<syncLib::SongStorage>::Iterator i = playList.begin(); i < playList.end(); i++){
|
for(QList<SongStorage>::Iterator i = playList.begin(); i < playList.end(); i++){
|
||||||
if(i->isSelected){
|
if(i->isSelected){
|
||||||
result.push_back(i->id);
|
result.push_back(i->id);
|
||||||
}
|
}
|
||||||
@ -124,7 +122,7 @@ QList<int> PlayListModel::getSelected(){
|
|||||||
|
|
||||||
bool PlayListModel::isSelected(int id){
|
bool PlayListModel::isSelected(int id){
|
||||||
|
|
||||||
for(QList<syncLib::SongStorage>::Iterator i = playList.begin(); i < playList.end(); i++){
|
for(QList<SongStorage>::Iterator i = playList.begin(); i < playList.end(); i++){
|
||||||
if(i->id == id){
|
if(i->id == id){
|
||||||
return i->isSelected;
|
return i->isSelected;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ class PlayListModel : public QAbstractListModel
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
SyncEngine * syncEngine;
|
SyncEngine * syncEngine;
|
||||||
QList<syncLib::SongStorage> playList;
|
QList<SongStorage> playList;
|
||||||
QString playListName;
|
QString playListName;
|
||||||
int itemCount;
|
int itemCount;
|
||||||
|
|
||||||
|
@ -42,13 +42,13 @@ void PlayListsModel::fetchMore(const QModelIndex & /* index */)
|
|||||||
int remainder = playLists.size() - itemCount;
|
int remainder = playLists.size() - itemCount;
|
||||||
int itemsToFetch = qMin(100, remainder);
|
int itemsToFetch = qMin(100, remainder);
|
||||||
|
|
||||||
if(itemsToFetch < 0){
|
if (itemsToFetch < 0) {
|
||||||
beginRemoveRows(QModelIndex(), 0, 0 - itemsToFetch - 1 );
|
beginRemoveRows(QModelIndex(), 0, 0 - itemsToFetch - 1 );
|
||||||
|
|
||||||
itemCount += itemsToFetch;
|
itemCount += itemsToFetch;
|
||||||
|
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}else{
|
} else if (itemsToFetch > 0) {
|
||||||
beginInsertRows(QModelIndex(), itemCount, itemCount + itemsToFetch - 1);
|
beginInsertRows(QModelIndex(), itemCount, itemCount + itemsToFetch - 1);
|
||||||
|
|
||||||
itemCount += itemsToFetch;
|
itemCount += itemsToFetch;
|
||||||
|
@ -41,13 +41,13 @@ void ServerListModel::fetchMore(const QModelIndex & /* index */)
|
|||||||
int remainder = servers->size() - itemCount;
|
int remainder = servers->size() - itemCount;
|
||||||
int itemsToFetch = qMin(100, remainder);
|
int itemsToFetch = qMin(100, remainder);
|
||||||
|
|
||||||
if(itemsToFetch < 0){
|
if (itemsToFetch < 0) {
|
||||||
beginRemoveRows(QModelIndex(), 0, 0 - itemsToFetch - 1 );
|
beginRemoveRows(QModelIndex(), 0, 0 - itemsToFetch - 1 );
|
||||||
|
|
||||||
itemCount += itemsToFetch;
|
itemCount += itemsToFetch;
|
||||||
|
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}else{
|
} else if (itemsToFetch > 0) {
|
||||||
beginInsertRows(QModelIndex(), itemCount, itemCount + itemsToFetch - 1);
|
beginInsertRows(QModelIndex(), itemCount, itemCount + itemsToFetch - 1);
|
||||||
|
|
||||||
itemCount += itemsToFetch;
|
itemCount += itemsToFetch;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
SyncEngine::SyncEngine()
|
SyncEngine::SyncEngine()
|
||||||
{
|
{
|
||||||
sync = new syncLib::Sync();
|
sync = new Sync();
|
||||||
sqlApi = sync->getSqlApi();
|
sqlApi = sync->getSqlApi();
|
||||||
|
|
||||||
connect(sync, SIGNAL(networkStateChange()), this, SIGNAL(serversCountChanged()));
|
connect(sync, SIGNAL(networkStateChange()), this, SIGNAL(serversCountChanged()));
|
||||||
@ -44,7 +44,7 @@ bool SyncEngine::init(){
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QList<syncLib::SongStorage>* SyncEngine::currentPlayList() const{
|
const QList<SongStorage>* SyncEngine::currentPlayList() const{
|
||||||
|
|
||||||
return sync->getPlayList();
|
return sync->getPlayList();
|
||||||
}
|
}
|
||||||
@ -196,7 +196,7 @@ bool SyncEngine::addSong(const QString &songUrl){
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SyncEngine::removeSong(int id){
|
bool SyncEngine::removeSong(int id){
|
||||||
syncLib::SongHeader header;
|
SongHeader header;
|
||||||
header.id = id;
|
header.id = id;
|
||||||
if(!sqlApi->removeSong(header))
|
if(!sqlApi->removeSong(header))
|
||||||
return false;
|
return false;
|
||||||
@ -223,7 +223,7 @@ bool SyncEngine::removePlayList(const QString &name){
|
|||||||
|
|
||||||
bool SyncEngine::addToPlayList(int id, const QString &playList){
|
bool SyncEngine::addToPlayList(int id, const QString &playList){
|
||||||
|
|
||||||
syncLib::SongHeader header;
|
SongHeader header;
|
||||||
header.id = id;
|
header.id = id;
|
||||||
|
|
||||||
if(!sqlApi->addToPlayList(header, playList)){
|
if(!sqlApi->addToPlayList(header, playList)){
|
||||||
@ -239,7 +239,7 @@ bool SyncEngine::addToPlayList(int id, const QString &playList){
|
|||||||
|
|
||||||
bool SyncEngine::removeFromPlayList(int id, const QString &playList){
|
bool SyncEngine::removeFromPlayList(int id, const QString &playList){
|
||||||
|
|
||||||
syncLib::SongHeader header;
|
SongHeader header;
|
||||||
header.id = id;
|
header.id = id;
|
||||||
|
|
||||||
if(!sqlApi->removeFromPlayList(header, playList)){
|
if(!sqlApi->removeFromPlayList(header, playList)){
|
||||||
|
@ -20,8 +20,8 @@ class SyncEngine : public QObject
|
|||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
syncLib::Sync *sync;
|
Sync *sync;
|
||||||
syncLib::MySql * sqlApi;
|
MySql * sqlApi;
|
||||||
QString _lastError;
|
QString _lastError;
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ ETcpSocket::ETcpSocket(QTcpSocket*ptr)
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
ETcpSocket::ETcpSocket(const QString& address, int port){
|
ETcpSocket::ETcpSocket(const QString& address, unsigned short port){
|
||||||
source = new QTcpSocket();
|
source = new QTcpSocket();
|
||||||
source->connectToHost(address, port);
|
source->connectToHost(address, port);
|
||||||
if(!source->waitForConnected(DEEP_SCANER_INTERVAL) || !source->open(QIODevice::ReadWrite)){
|
if(!source->waitForConnected(DEEP_SCANER_INTERVAL) || !source->open(QIODevice::ReadWrite)){
|
||||||
@ -24,14 +24,134 @@ ETcpSocket::ETcpSocket(const QString& address, int port){
|
|||||||
|
|
||||||
void ETcpSocket::init(){
|
void ETcpSocket::init(){
|
||||||
array = new QByteArray;
|
array = new QByteArray;
|
||||||
|
time = 0;
|
||||||
|
fSynced = false;
|
||||||
|
|
||||||
connect(source,SIGNAL(connected()),this,SLOT(connected_()));
|
connect(source, SIGNAL(connected()), this, SLOT(connected_()));
|
||||||
connect(source,SIGNAL(disconnected()),this,SLOT(disconnected_()));
|
connect(source, SIGNAL(disconnected()), this, SLOT(disconnected_()));
|
||||||
connect(source,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error_(QAbstractSocket::SocketError)));
|
connect(source, SIGNAL(error(QAbstractSocket::SocketError)),
|
||||||
connect(source,SIGNAL(hostFound()),this,SLOT(hostFound_()));
|
this, SLOT(error_(QAbstractSocket::SocketError)));
|
||||||
connect(source,SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)),this,SLOT(proxyAuthenticationRequired_(const QNetworkProxy &, QAuthenticator *)));
|
connect(source, SIGNAL(hostFound()), this,SLOT(hostFound_()));
|
||||||
connect(source,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(stateChanged_(QAbstractSocket::SocketState)));
|
connect(source,
|
||||||
connect(source,SIGNAL(readyRead()),this,SLOT(readReady_()));
|
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_()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ETcpSocket::_driverResponse(const SyncPackage& from) {
|
||||||
|
|
||||||
|
if(!from.isValid()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncPackage pac;
|
||||||
|
|
||||||
|
switch (from.type) {
|
||||||
|
case t_Header:
|
||||||
|
syncList.clear();
|
||||||
|
precisionSync = from.getPrecision();
|
||||||
|
lastTime = ChronoTime::now();
|
||||||
|
pac.sourceBytes = ChronoTime::now();
|
||||||
|
pac.nativeTime = from.getTime();
|
||||||
|
pac.type = t_Source;
|
||||||
|
pac.firstByte = 0;
|
||||||
|
|
||||||
|
_Write(pac.parseTo(), true);
|
||||||
|
|
||||||
|
syncList[0] = pac;
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
case t_Source:
|
||||||
|
syncList[from.getIndex()] = from;
|
||||||
|
pac.type = t_Responce;
|
||||||
|
pac.firstByte = from.getIndex();
|
||||||
|
pac.sourceBytes = ChronoTime::now();
|
||||||
|
|
||||||
|
_Write(pac.parseTo(), true);
|
||||||
|
break;
|
||||||
|
case t_Responce:
|
||||||
|
syncList[from.getIndex()].ping = ChronoTime::now() - lastTime;
|
||||||
|
lastTime = ChronoTime::now();
|
||||||
|
|
||||||
|
if(syncList.size() >= precisionSync){
|
||||||
|
pac.type = t_End;
|
||||||
|
|
||||||
|
auto ping = syncList.first().ping;
|
||||||
|
auto index = syncList.begin();
|
||||||
|
for (auto i = syncList.begin(); i != syncList.end(); i++) {
|
||||||
|
if (i.value().ping < ping) {
|
||||||
|
ping = i.value().ping;
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pac.firstByte = index->firstByte;
|
||||||
|
pac.sourceBytes = index->ping;
|
||||||
|
pac.nativeTime = index->nativeTime;
|
||||||
|
|
||||||
|
_Write(pac.parseTo(), true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pac.type = t_Source;
|
||||||
|
pac.firstByte = from.getIndex() + 1;
|
||||||
|
pac.sourceBytes = ChronoTime::now();
|
||||||
|
pac.nativeTime = from.getTime();
|
||||||
|
|
||||||
|
_Write(pac.parseTo(), true);
|
||||||
|
|
||||||
|
syncList[pac.firstByte] = pac;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case t_End: {
|
||||||
|
|
||||||
|
if(syncList.size() <= from.getIndex()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ping = from.getPing();
|
||||||
|
|
||||||
|
if (ping > 10) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
time = from.getNative() - syncList[from.getIndex()].getTime() - from.getPing() / 2;
|
||||||
|
fSynced = true;
|
||||||
|
qDebug() << "syncTime :" << time;
|
||||||
|
|
||||||
|
emit synced();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ETcpSocket::_driverStart() {
|
||||||
|
syncList.clear();
|
||||||
|
|
||||||
|
SyncPackage pac;
|
||||||
|
|
||||||
|
precisionSync = SYNC_COUNT;
|
||||||
|
pac.type = t_Header;
|
||||||
|
pac.firstByte = precisionSync;
|
||||||
|
pac.sourceBytes = ChronoTime::now();
|
||||||
|
|
||||||
|
_Write(pac.parseTo(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ETcpSocket::_driver(QByteArray *data){
|
||||||
|
SyncPackage pac;
|
||||||
|
if(!pac.parseFrom(*data)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_driverResponse(pac);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ETcpSocket::error_(QAbstractSocket::SocketError i){
|
void ETcpSocket::error_(QAbstractSocket::SocketError i){
|
||||||
@ -70,9 +190,16 @@ void ETcpSocket::readReady_(){
|
|||||||
qDebug()<<"messae size:" << size;
|
qDebug()<<"messae size:" << size;
|
||||||
qDebug()<<"message package size:" << array->size();
|
qDebug()<<"message package size:" << array->size();
|
||||||
#endif
|
#endif
|
||||||
if(size==array->size())
|
if(size == array->size())
|
||||||
{
|
{
|
||||||
array->remove(0, sizeof(qint32));
|
array->remove(0, sizeof(qint32));
|
||||||
|
if(array->back()){
|
||||||
|
_driver(array);
|
||||||
|
delete array;
|
||||||
|
array = new QByteArray();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
array->remove(array->size() - 1, 1);
|
||||||
ReadyStack.push_back(array);
|
ReadyStack.push_back(array);
|
||||||
array=new QByteArray();
|
array=new QByteArray();
|
||||||
emit Message(this);
|
emit Message(this);
|
||||||
@ -97,13 +224,31 @@ QString ETcpSocket::localName() const{
|
|||||||
QByteArray* ETcpSocket::topStack(){
|
QByteArray* ETcpSocket::topStack(){
|
||||||
if(ReadyStack.size())
|
if(ReadyStack.size())
|
||||||
return ReadyStack.front();
|
return ReadyStack.front();
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
milliseconds ETcpSocket::getTime()const{
|
||||||
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTcpSocket* ETcpSocket::getSource()const{
|
QTcpSocket* ETcpSocket::getSource()const{
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ETcpSocket::sync(){
|
||||||
|
if(fSynced){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_driverStart();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ETcpSocket::isSynced()const{
|
||||||
|
return fSynced;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ETcpSocket::nextItem(bool free){
|
void ETcpSocket::nextItem(bool free){
|
||||||
if( ReadyStack.size()){
|
if( ReadyStack.size()){
|
||||||
if(free){
|
if(free){
|
||||||
@ -122,13 +267,18 @@ QString ETcpSocket::toStringTcp(){
|
|||||||
return source->peerAddress().toString();
|
return source->peerAddress().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ETcpSocket::Write(const QByteArray&data){
|
bool ETcpSocket::Write(const QByteArray &data){
|
||||||
|
return _Write(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ETcpSocket::_Write(const QByteArray&data, bool isDriver){
|
||||||
if(source->state()==QTcpSocket::ConnectedState){
|
if(source->state()==QTcpSocket::ConnectedState){
|
||||||
QByteArray array;
|
QByteArray array;
|
||||||
QDataStream stream(&array, QIODevice::ReadWrite);
|
QDataStream stream(&array, QIODevice::ReadWrite);
|
||||||
|
|
||||||
stream << qint32(0);
|
stream << qint32(0);
|
||||||
array.append(data);
|
array.append(data);
|
||||||
|
array.append(qint8(isDriver));
|
||||||
stream.device()->seek(0);
|
stream.device()->seek(0);
|
||||||
stream<<qint32(array.size());
|
stream<<qint32(array.size());
|
||||||
|
|
||||||
@ -144,12 +294,19 @@ bool ETcpSocket::Write(const QByteArray&data){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ETcpSocket::isValid(){
|
||||||
|
return source->isValid() && source->isOpen();
|
||||||
|
}
|
||||||
|
|
||||||
ETcpSocket::~ETcpSocket()
|
ETcpSocket::~ETcpSocket()
|
||||||
{
|
{
|
||||||
for(QByteArray*i:ReadyStack){
|
for(QByteArray*i:ReadyStack){
|
||||||
i->clear();
|
i->clear();
|
||||||
delete i;
|
delete i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
syncList.clear();
|
||||||
|
|
||||||
disconnect(source,SIGNAL(connected()),this,SLOT(connected_()));
|
disconnect(source,SIGNAL(connected()),this,SLOT(connected_()));
|
||||||
disconnect(source,SIGNAL(disconnected()),this,SLOT(disconnected_()));
|
disconnect(source,SIGNAL(disconnected()),this,SLOT(disconnected_()));
|
||||||
disconnect(source,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error_(QAbstractSocket::SocketError)));
|
disconnect(source,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(error_(QAbstractSocket::SocketError)));
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <QTcpServer>
|
#include <QTcpServer>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include "chronotime.h"
|
#include "syncpackage.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,9 +36,41 @@ private:
|
|||||||
QTcpSocket *source;
|
QTcpSocket *source;
|
||||||
QByteArray *array;
|
QByteArray *array;
|
||||||
qint32 size;
|
qint32 size;
|
||||||
|
milliseconds time;
|
||||||
|
milliseconds lastTime;
|
||||||
|
char precisionSync;
|
||||||
QList<QByteArray*> ReadyStack;
|
QList<QByteArray*> ReadyStack;
|
||||||
|
bool fSynced;
|
||||||
|
QMap<char ,SyncPackage> syncList;
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief _driverResponse
|
||||||
|
* @param pac
|
||||||
|
* @return true if all done
|
||||||
|
*/
|
||||||
|
bool _driverResponse(const SyncPackage &from);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief _driverResponse
|
||||||
|
* @param pac
|
||||||
|
* @return true if all done
|
||||||
|
*/
|
||||||
|
void _driverStart();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief _driver
|
||||||
|
* @return true is package of Driver
|
||||||
|
*/
|
||||||
|
void _driver(QByteArray*);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write - sends a message to the network.
|
||||||
|
* @param isDriver - flag of driver info
|
||||||
|
* @return true if all done else false.
|
||||||
|
*/
|
||||||
|
bool _Write(const QByteArray&, bool isDriver = false);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void connected_();
|
void connected_();
|
||||||
@ -51,7 +83,18 @@ private slots:
|
|||||||
public:
|
public:
|
||||||
explicit ETcpSocket();
|
explicit ETcpSocket();
|
||||||
explicit ETcpSocket(QTcpSocket*);
|
explicit ETcpSocket(QTcpSocket*);
|
||||||
explicit ETcpSocket(const QString& addres,int port);
|
explicit ETcpSocket(const QString& addres, unsigned short port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief sync
|
||||||
|
*/
|
||||||
|
void sync();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief isSynced
|
||||||
|
* @return true
|
||||||
|
*/
|
||||||
|
bool isSynced()const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief setCheckInterval - set new interval of chking ping
|
* @brief setCheckInterval - set new interval of chking ping
|
||||||
@ -66,10 +109,15 @@ public:
|
|||||||
int getCheckInterval()const;
|
int getCheckInterval()const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief getPing
|
* @brief setTime set new Time
|
||||||
* @return ping of soccket;
|
|
||||||
*/
|
*/
|
||||||
int getPing()const;
|
void setTime(milliseconds newTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getTime
|
||||||
|
* @return time of soccket;
|
||||||
|
*/
|
||||||
|
milliseconds getTime()const;
|
||||||
/**
|
/**
|
||||||
* @brief getSource
|
* @brief getSource
|
||||||
* @return Qt TCP socket
|
* @return Qt TCP socket
|
||||||
@ -92,6 +140,13 @@ public:
|
|||||||
* @return size of Descript of Packege
|
* @return size of Descript of Packege
|
||||||
*/
|
*/
|
||||||
int sizeDescriptPackege();
|
int sizeDescriptPackege();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief isValid
|
||||||
|
* @return true if socket active;
|
||||||
|
*/
|
||||||
|
bool isValid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Write - sends a message to the network.
|
* @brief Write - sends a message to the network.
|
||||||
* @return true if all done else false.
|
* @return true if all done else false.
|
||||||
@ -163,6 +218,12 @@ signals:
|
|||||||
void StateChanged(ETcpSocket*,QAbstractSocket::SocketState socketState);
|
void StateChanged(ETcpSocket*,QAbstractSocket::SocketState socketState);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief synced emited when host is synced
|
||||||
|
*/
|
||||||
|
void synced();
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CLIENT_H
|
#endif // CLIENT_H
|
||||||
|
118
sync/basepackage.cpp
Normal file
118
sync/basepackage.cpp
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
#include "basepackage.h"
|
||||||
|
|
||||||
|
package::package()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
package::package( QByteArray &array):
|
||||||
|
package::package(){
|
||||||
|
parseFrom(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
const SongHeader& package::getHeader() const{
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Song& package::getSong() const{
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Syncer& package::getPlayData() const{
|
||||||
|
return playdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Type& package::getType() const{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool package::isValid() const{
|
||||||
|
|
||||||
|
bool ret = true;
|
||||||
|
if(type == TypePackage::t_void){
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type & TypePackage::t_sync && type & t_brodcaster){
|
||||||
|
ret = ret && playdata.seek > 0 && playdata.timeOn > 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type & TypePackage::t_song_h && type & t_brodcaster){
|
||||||
|
ret = ret && header.size > 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type & TypePackage::t_song && type & t_brodcaster){
|
||||||
|
ret = ret && source.size > 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void package::clear(){
|
||||||
|
type = TypePackage::t_void;
|
||||||
|
source.clear();
|
||||||
|
playdata.seek = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray package::parseTo(){
|
||||||
|
QByteArray temp;
|
||||||
|
QDataStream stream(&temp, QIODevice::WriteOnly);
|
||||||
|
temp.clear();
|
||||||
|
if(isValid()){
|
||||||
|
stream << static_cast<unsigned char>(type);
|
||||||
|
|
||||||
|
if(type & TypePackage::t_sync && type & t_brodcaster){
|
||||||
|
stream << playdata.seek;
|
||||||
|
stream << playdata.timeOn;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type & TypePackage::t_song_h && type & t_brodcaster){
|
||||||
|
stream << header;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type & TypePackage::t_song && type & t_brodcaster){
|
||||||
|
stream << source;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool package::parseFrom(QByteArray &array){
|
||||||
|
type = TypePackage::t_void;
|
||||||
|
QDataStream stream(&array, QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
unsigned char temp_type;
|
||||||
|
stream >> temp_type;
|
||||||
|
type = static_cast<TypePackage> (temp_type);
|
||||||
|
|
||||||
|
if(type & TypePackage::t_sync){
|
||||||
|
stream >> playdata.seek;
|
||||||
|
stream >> playdata.timeOn;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type & TypePackage::t_song_h){
|
||||||
|
stream >> header;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type & TypePackage::t_song){
|
||||||
|
stream >> source;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
package::~package(){}
|
||||||
|
|
112
sync/basepackage.h
Normal file
112
sync/basepackage.h
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#ifndef BASEPACKAGE_H
|
||||||
|
#define BASEPACKAGE_H
|
||||||
|
|
||||||
|
#include "song.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
|
typedef unsigned char Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The TypePackage enum
|
||||||
|
* t_void = this package empty and not valid.
|
||||||
|
* t_play = play current audio file.
|
||||||
|
* t_song_h = the header of playing audio file.
|
||||||
|
* t_song = the package with this type is necessary for translite media data on network.
|
||||||
|
* t_sync = the infomation about sync playning media file on network.
|
||||||
|
* t_close = the information about close channel.
|
||||||
|
* t_syncTime = getLocalTime of socket
|
||||||
|
* t_what = request for information about the node
|
||||||
|
* t_brodcaster = information about the node
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum TypePackage{
|
||||||
|
t_void = 0x00,
|
||||||
|
t_play = 0x01,
|
||||||
|
t_song_h = 0x02,
|
||||||
|
t_song = 0x04,
|
||||||
|
t_sync = 0x08,
|
||||||
|
t_close = 0x10,
|
||||||
|
t_pause = 0x20,
|
||||||
|
t_what = 0x40,
|
||||||
|
t_brodcaster = 0x80
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The package class. Package for translite media data on network
|
||||||
|
*
|
||||||
|
* parse map:
|
||||||
|
* 1 byle - type
|
||||||
|
* data
|
||||||
|
*/
|
||||||
|
class package
|
||||||
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type type;
|
||||||
|
Song source;
|
||||||
|
SongHeader header;
|
||||||
|
bool fbroadcaster;
|
||||||
|
Syncer playdata;
|
||||||
|
public:
|
||||||
|
package();
|
||||||
|
package(QByteArray &array);
|
||||||
|
~package();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getHeader
|
||||||
|
* @return Header of the song
|
||||||
|
*/
|
||||||
|
const SongHeader& getHeader() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getSong
|
||||||
|
* @return Song
|
||||||
|
*/
|
||||||
|
const Song& getSong() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getPlayTime
|
||||||
|
* @return time of playning media data
|
||||||
|
*/
|
||||||
|
const Syncer &getPlayData() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getType
|
||||||
|
* @return type of package
|
||||||
|
*/
|
||||||
|
const Type& getType() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getTime
|
||||||
|
* @return time of sended package pc
|
||||||
|
*/
|
||||||
|
const milliseconds& getTime()const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief isValid
|
||||||
|
* @return true if package is valid
|
||||||
|
*/
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief clear all date of package
|
||||||
|
*/
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief parseTo parse this package to byte array
|
||||||
|
* @return byte array
|
||||||
|
*/
|
||||||
|
QByteArray parseTo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief parseFrom create a package from bytes
|
||||||
|
* @param array of bytes
|
||||||
|
* @return true if package valid
|
||||||
|
*/
|
||||||
|
bool parseFrom(QByteArray& array);
|
||||||
|
friend class Sync;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BASEPACKAGE_H
|
@ -1,24 +1,32 @@
|
|||||||
#include "chronotime.h"
|
#include "chronotime.h"
|
||||||
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
ChronoTime::ChronoTime()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* information about chrono
|
* information about chrono
|
||||||
* https://stackoverflow.com/questions/31255486/c-how-do-i-convert-a-stdchronotime-point-to-long-and-back
|
* https://stackoverflow.com/questions/31255486/c-how-do-i-convert-a-stdchronotime-point-to-long-and-back
|
||||||
*/
|
*/
|
||||||
|
milliseconds ChronoTime::stdTime() {
|
||||||
milliseconds ChronoTime::now(int calibration){
|
|
||||||
auto tim = std::chrono::system_clock::now();
|
auto tim = std::chrono::system_clock::now();
|
||||||
auto mc = std::chrono::time_point_cast<std::chrono::milliseconds>(tim);
|
auto mc = std::chrono::time_point_cast<std::chrono::milliseconds>(tim);
|
||||||
auto epoh = mc.time_since_epoch();
|
auto epoh = mc.time_since_epoch();
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
qDebug() << epoh.count();
|
qDebug() << epoh.count();
|
||||||
#endif
|
#endif
|
||||||
return epoh.count() + calibration;
|
return epoh.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
milliseconds ChronoTime::qtTime() {
|
||||||
|
return QDateTime::currentMSecsSinceEpoch();
|
||||||
|
}
|
||||||
|
|
||||||
|
ChronoTime::ChronoTime()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
milliseconds ChronoTime::now(milliseconds calibration){
|
||||||
|
return qtTime() + calibration;
|
||||||
}
|
}
|
||||||
|
|
||||||
Clock ChronoTime::from(const milliseconds& mc){
|
Clock ChronoTime::from(const milliseconds& mc){
|
||||||
|
@ -11,13 +11,16 @@ typedef std::chrono::time_point<std::chrono::high_resolution_clock> Clock;
|
|||||||
|
|
||||||
class ChronoTime
|
class ChronoTime
|
||||||
{
|
{
|
||||||
|
private :
|
||||||
|
static milliseconds stdTime();
|
||||||
|
static milliseconds qtTime();
|
||||||
public:
|
public:
|
||||||
ChronoTime();
|
ChronoTime();
|
||||||
/**
|
/**
|
||||||
* @brief now - get now time on microsecunds
|
* @brief now - get now time on microsecunds
|
||||||
* @return - count of microsecunds
|
* @return - count of microsecunds
|
||||||
*/
|
*/
|
||||||
static milliseconds now(int calibration = 0);
|
static milliseconds now(milliseconds calibration = 0);
|
||||||
/**
|
/**
|
||||||
* @brief from cast to chrono secunds
|
* @brief from cast to chrono secunds
|
||||||
* @param mcrs microseconds of uint_64
|
* @param mcrs microseconds of uint_64
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
#define RESYNC_TIME 1000 // 1 sec on millisec
|
#define RESYNC_TIME 1000 // 1 sec on millisec
|
||||||
#define MAX_RESYNC_COUNT 3
|
#define MAX_RESYNC_COUNT 3
|
||||||
#define SYNC_TIME 5 * 1000 // 5 sec on millisec
|
#define SYNC_TIME 5 * 1000 // 5 sec on millisec
|
||||||
|
#define SYNC_COUNT 20
|
||||||
#define DEEP_SCANER_INTERVAL 1000 // 1 sec
|
#define DEEP_SCANER_INTERVAL 1000 // 1 sec
|
||||||
#define CHECK_PING_INTERVAL 5 * 60 *1000// 5 minutes
|
|
||||||
|
|
||||||
// sync
|
// sync
|
||||||
#define MIN_DIFFERENCE 10 // millisec
|
#define MIN_DIFFERENCE 10 // millisec
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include "playlist.h"
|
#include "playlist.h"
|
||||||
|
|
||||||
namespace syncLib{
|
|
||||||
|
|
||||||
MySql::MySql(const QString &databasename):
|
MySql::MySql(const QString &databasename):
|
||||||
db(nullptr),
|
db(nullptr),
|
||||||
qyery(nullptr)
|
qyery(nullptr)
|
||||||
@ -119,43 +117,7 @@ void MySql::initDB(const QString &database){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MySql::find(const QMediaContent &song, SongStorage &response){
|
bool MySql::find(const SongHeader &song, SongStorage &response){
|
||||||
QList<SongStorage> songs;
|
|
||||||
|
|
||||||
if(!updateAvailableSongs(songs)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(SongStorage &i: songs){
|
|
||||||
if(i == song){
|
|
||||||
response = i;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MySql::find(const QMediaContent &song, SongHeader &response){
|
|
||||||
QList<SongStorage> songs;
|
|
||||||
|
|
||||||
if(!updateAvailableSongs(songs)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(SongStorage &i: songs){
|
|
||||||
if(i == song){
|
|
||||||
response = (SongHeader&)i;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MySql::find(const SongHeader &song, QMediaContent &response){
|
|
||||||
QList<SongStorage> songs;
|
QList<SongStorage> songs;
|
||||||
|
|
||||||
if(!updateAvailableSongs(songs)){
|
if(!updateAvailableSongs(songs)){
|
||||||
@ -164,7 +126,7 @@ bool MySql::find(const SongHeader &song, QMediaContent &response){
|
|||||||
|
|
||||||
for(SongStorage &i: songs){
|
for(SongStorage &i: songs){
|
||||||
if((SongHeader&)i == song){
|
if((SongHeader&)i == song){
|
||||||
response = i.toMedia();
|
response = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,6 +144,9 @@ bool MySql::saveToStorage(QUrl &url, const Song &song) const{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDir dir;
|
||||||
|
dir.mkpath(songDir);
|
||||||
|
|
||||||
QFile file(songDir + "/" + song.name);
|
QFile file(songDir + "/" + song.name);
|
||||||
|
|
||||||
if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
|
if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
|
||||||
@ -510,5 +475,5 @@ MySql::~MySql(){
|
|||||||
QSqlDatabase::removeDatabase(dataBaseName);
|
QSqlDatabase::removeDatabase(dataBaseName);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
21
sync/mysql.h
21
sync/mysql.h
@ -6,8 +6,6 @@
|
|||||||
class QSqlDatabase;
|
class QSqlDatabase;
|
||||||
class QSqlQuery;
|
class QSqlQuery;
|
||||||
|
|
||||||
namespace syncLib {
|
|
||||||
|
|
||||||
class MySql
|
class MySql
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -43,23 +41,7 @@ public:
|
|||||||
* @param response Media Content of finded song
|
* @param response Media Content of finded song
|
||||||
* @return true if song finded
|
* @return true if song finded
|
||||||
*/
|
*/
|
||||||
bool find(const SongHeader& song, QMediaContent& response);
|
bool find(const SongHeader& song, SongStorage &response);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief find - find song
|
|
||||||
* @param song - song header
|
|
||||||
* @param response Media Content of finded song
|
|
||||||
* @return true if song finded
|
|
||||||
*/
|
|
||||||
bool find(const QMediaContent& song, SongHeader& response);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief find - find song
|
|
||||||
* @param song - media Content
|
|
||||||
* @param response header of finded song
|
|
||||||
* @return true if song finded
|
|
||||||
*/
|
|
||||||
bool find(const QMediaContent& song, SongStorage &response);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief setSoundDir
|
* @brief setSoundDir
|
||||||
@ -194,5 +176,4 @@ public:
|
|||||||
|
|
||||||
~MySql();
|
~MySql();
|
||||||
};
|
};
|
||||||
}
|
|
||||||
#endif // MYSQL_H
|
#endif // MYSQL_H
|
||||||
|
137
sync/node.cpp
137
sync/node.cpp
@ -2,123 +2,10 @@
|
|||||||
#include "exaptions.h"
|
#include "exaptions.h"
|
||||||
#include "LocalScanner.h"
|
#include "LocalScanner.h"
|
||||||
|
|
||||||
namespace syncLib{
|
|
||||||
|
|
||||||
package::package()
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
package::package( QByteArray &array):
|
|
||||||
package::package(){
|
|
||||||
parseFrom(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
const SongHeader& package::getHeader() const{
|
|
||||||
return header;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Song& package::getSong() const{
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Syncer& package::getPlayData() const{
|
|
||||||
return playdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Type& package::getType() const{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool package::isValid() const{
|
|
||||||
|
|
||||||
bool ret = true;
|
|
||||||
if(type == TypePackage::t_void){
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(type & TypePackage::t_sync && type & t_brodcaster){
|
|
||||||
ret = ret && (playdata.seek > 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(type & TypePackage::t_song_h && type & t_brodcaster){
|
|
||||||
ret = ret && header.size > 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(type & TypePackage::t_song && type & t_brodcaster){
|
|
||||||
ret = ret && source.size > 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void package::clear(){
|
|
||||||
type = TypePackage::t_void;
|
|
||||||
source.clear();
|
|
||||||
playdata.seek = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray package::parseTo(){
|
|
||||||
QByteArray temp;
|
|
||||||
QDataStream stream(&temp, QIODevice::WriteOnly);
|
|
||||||
temp.clear();
|
|
||||||
if(isValid()){
|
|
||||||
stream << static_cast<unsigned char>(type);
|
|
||||||
|
|
||||||
if(type & TypePackage::t_sync && type & t_brodcaster){
|
|
||||||
stream << playdata.seek;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(type & TypePackage::t_song_h && type & t_brodcaster){
|
|
||||||
stream << header;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(type & TypePackage::t_song && type & t_brodcaster){
|
|
||||||
stream << source;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool package::parseFrom(QByteArray &array){
|
|
||||||
type = TypePackage::t_void;
|
|
||||||
QDataStream stream(&array, QIODevice::ReadOnly);
|
|
||||||
|
|
||||||
unsigned char temp_type;
|
|
||||||
stream >> temp_type;
|
|
||||||
type = static_cast<TypePackage> (temp_type);
|
|
||||||
|
|
||||||
if(type & TypePackage::t_sync){
|
|
||||||
stream >> playdata.seek;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(type & TypePackage::t_song_h){
|
|
||||||
stream >> header;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(type & TypePackage::t_song){
|
|
||||||
stream >> source;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return isValid();
|
|
||||||
}
|
|
||||||
|
|
||||||
package::~package(){}
|
|
||||||
|
|
||||||
Node::Node(const QString &addres, int port):QTcpServer(){
|
Node::Node(const QString &addres, int port):QTcpServer(){
|
||||||
QString address = addres;
|
QString address = addres;
|
||||||
|
fBroadcaster = false;
|
||||||
if(address == DEFAULT_ADRESS){
|
if(address == DEFAULT_ADRESS){
|
||||||
address = LocalScanner::thisAddress().toString();
|
address = LocalScanner::thisAddress().toString();
|
||||||
}
|
}
|
||||||
@ -132,7 +19,9 @@ Node::Node(const QString &addres, int port):QTcpServer(){
|
|||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
qDebug() << "node started on:" << serverAddress().toString() << "port:" << serverPort();
|
qDebug() << "node started on:" << serverAddress().toString() << "port:" << serverPort();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
connect(this,SIGNAL(newConnection()),SLOT(newConnection_()));
|
connect(this,SIGNAL(newConnection()),SLOT(newConnection_()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::acceptError_(ETcpSocket*c){
|
void Node::acceptError_(ETcpSocket*c){
|
||||||
@ -145,6 +34,14 @@ void Node::acceptError_(ETcpSocket*c){
|
|||||||
delete c;
|
delete c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Node::isBroadcaster()const{
|
||||||
|
return fBroadcaster;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::setBroadcaster(bool newValue){
|
||||||
|
fBroadcaster = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
QList<ETcpSocket*>* Node::getClients(){
|
QList<ETcpSocket*>* Node::getClients(){
|
||||||
return &clients;
|
return &clients;
|
||||||
}
|
}
|
||||||
@ -152,11 +49,18 @@ QList<ETcpSocket*>* Node::getClients(){
|
|||||||
void Node::newConnection_(){
|
void Node::newConnection_(){
|
||||||
ETcpSocket *newClient=new ETcpSocket(nextPendingConnection());
|
ETcpSocket *newClient=new ETcpSocket(nextPendingConnection());
|
||||||
clients.push_back(newClient);
|
clients.push_back(newClient);
|
||||||
connect(newClient,SIGNAL(Disconnected(ETcpSocket*)),this,SLOT(acceptError_(ETcpSocket*)));
|
connect(newClient, SIGNAL(Disconnected(ETcpSocket*)),
|
||||||
connect(newClient,SIGNAL(Message(ETcpSocket*)),this,SLOT(readData(ETcpSocket*)));
|
this, SLOT(acceptError_(ETcpSocket*)));
|
||||||
|
connect(newClient, SIGNAL(Message(ETcpSocket*)), this, SLOT(readData(ETcpSocket*)));
|
||||||
|
connect(newClient, SIGNAL(synced()), this, SLOT(synced()));
|
||||||
|
|
||||||
emit ClientConnected(newClient);
|
emit ClientConnected(newClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Node::synced(){
|
||||||
|
emit NodeSynced(static_cast<ETcpSocket*>(this->sender()));
|
||||||
|
}
|
||||||
|
|
||||||
void Node::readData(ETcpSocket *c){
|
void Node::readData(ETcpSocket *c){
|
||||||
emit Message(c);
|
emit Message(c);
|
||||||
}
|
}
|
||||||
@ -211,6 +115,5 @@ Node::~Node(){
|
|||||||
this->close();
|
this->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
141
sync/node.h
141
sync/node.h
@ -2,104 +2,101 @@
|
|||||||
#define NODE_H
|
#define NODE_H
|
||||||
#include <QTcpServer>
|
#include <QTcpServer>
|
||||||
#include "ETcpSocket.h"
|
#include "ETcpSocket.h"
|
||||||
#include "song.h"
|
#include <QTimer>
|
||||||
#include "config.h"
|
#include "basepackage.h"
|
||||||
|
#include "syncpackage.h"
|
||||||
namespace syncLib {
|
|
||||||
|
|
||||||
typedef unsigned char Type;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The TypePackage enum
|
* @brief The Node class is tcp server class
|
||||||
* t_void = this package empty and not valid.
|
|
||||||
* t_play = play current audio file.
|
|
||||||
* t_song_h = the header of playing audio file.
|
|
||||||
* t_song = the package with this type is necessary for translite media data on network.
|
|
||||||
* t_sync = the infomation about sync playning media file on network.
|
|
||||||
* t_close = the information about close channel.
|
|
||||||
* t_stop = the package with type 'stop' necessary for stoping playning media files.
|
|
||||||
* t_what = request for information about the node
|
|
||||||
* t_brodcaster = information about the node
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum TypePackage{
|
|
||||||
t_void = 0x00,
|
|
||||||
t_play = 0x01,
|
|
||||||
t_song_h = 0x02,
|
|
||||||
t_song = 0x04,
|
|
||||||
t_sync = 0x08,
|
|
||||||
t_close = 0x10,
|
|
||||||
t_stop = 0x20,
|
|
||||||
t_what = 0x40,
|
|
||||||
t_brodcaster = 0x80
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The package class. Package for translite media data on network
|
|
||||||
*
|
|
||||||
* parse map:
|
|
||||||
* 1 byle - type
|
|
||||||
* data
|
|
||||||
*/
|
*/
|
||||||
class package
|
|
||||||
{
|
|
||||||
|
|
||||||
private:
|
|
||||||
Type type;
|
|
||||||
Song source;
|
|
||||||
SongHeader header;
|
|
||||||
Syncer playdata;
|
|
||||||
public:
|
|
||||||
package();
|
|
||||||
package(QByteArray &array);
|
|
||||||
~package();
|
|
||||||
/**
|
|
||||||
* @brief getHeader
|
|
||||||
* @return Header of the song
|
|
||||||
*/
|
|
||||||
const SongHeader& getHeader() const;
|
|
||||||
/**
|
|
||||||
* @brief getSong
|
|
||||||
* @return Song
|
|
||||||
*/
|
|
||||||
const Song& getSong() const;
|
|
||||||
/**
|
|
||||||
* @brief getPlayTime
|
|
||||||
* @return time of playning media data
|
|
||||||
*/
|
|
||||||
const Syncer &getPlayData() const;
|
|
||||||
const Type& getType() const;
|
|
||||||
bool isValid() const;
|
|
||||||
void clear();
|
|
||||||
QByteArray parseTo();
|
|
||||||
bool parseFrom(QByteArray& array);
|
|
||||||
friend class Sync;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Node:public QTcpServer{
|
class Node:public QTcpServer{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
QTimer *timer;
|
||||||
|
int index;
|
||||||
protected:
|
protected:
|
||||||
QList<ETcpSocket*> clients;
|
QList<ETcpSocket*> clients;
|
||||||
|
bool fBroadcaster;
|
||||||
|
int step;
|
||||||
private slots:
|
private slots:
|
||||||
|
void synced();
|
||||||
void acceptError_(ETcpSocket*);
|
void acceptError_(ETcpSocket*);
|
||||||
void newConnection_();
|
void newConnection_();
|
||||||
void readData(ETcpSocket*_client);
|
void readData(ETcpSocket*_client);
|
||||||
public:
|
public:
|
||||||
Node(const QString &addres = DEFAULT_ADRESS, int port = DEFAULT_PORT);
|
Node(const QString &addres = DEFAULT_ADRESS, int port = DEFAULT_PORT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief isBroadcaster
|
||||||
|
* @return true if this node is server
|
||||||
|
*/
|
||||||
|
bool isBroadcaster()const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief setBroadcaster set new state for this node
|
||||||
|
*/
|
||||||
|
void setBroadcaster(bool newValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief WriteAll send package to all connected clients
|
||||||
|
*/
|
||||||
void WriteAll(const QByteArray&);
|
void WriteAll(const QByteArray&);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief disconnectClient disconet a client
|
||||||
|
*/
|
||||||
void disconnectClient(ETcpSocket*);
|
void disconnectClient(ETcpSocket*);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getClients
|
||||||
|
* @return list of all connected clients
|
||||||
|
*/
|
||||||
QList<ETcpSocket*>* getClients();
|
QList<ETcpSocket*>* getClients();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief addNode add new client for network
|
||||||
|
* @param node if of node
|
||||||
|
* @param port port of node
|
||||||
|
* @return true if all done
|
||||||
|
*/
|
||||||
bool addNode(const QString &node, int port);
|
bool addNode(const QString &node, int port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief addNode a connected node
|
||||||
|
* @param node tcp socket
|
||||||
|
* @return true if all done
|
||||||
|
*/
|
||||||
bool addNode(ETcpSocket* node);
|
bool addNode(ETcpSocket* node);
|
||||||
|
|
||||||
~Node();
|
~Node();
|
||||||
signals:
|
signals:
|
||||||
|
/**
|
||||||
|
* @brief Error signal when a error detected
|
||||||
|
*/
|
||||||
void Error(QString);
|
void Error(QString);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Message signal when accepted a mewssage from other node
|
||||||
|
*/
|
||||||
void Message(ETcpSocket*);
|
void Message(ETcpSocket*);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ClientDisconnected - signal when node disconected from this node
|
||||||
|
*/
|
||||||
void ClientDisconnected(ETcpSocket*);
|
void ClientDisconnected(ETcpSocket*);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ClientConnected signal when connected a new node
|
||||||
|
*/
|
||||||
void ClientConnected(ETcpSocket*);
|
void ClientConnected(ETcpSocket*);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief NodeSynced emited when socket synced
|
||||||
|
*/
|
||||||
|
void NodeSynced(ETcpSocket*);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // NODE_H
|
#endif // NODE_H
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
#include <QMediaPlaylist>
|
#include <QMediaPlaylist>
|
||||||
#include "song.h"
|
#include "song.h"
|
||||||
|
|
||||||
using namespace syncLib;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The PlayList class
|
* @brief The PlayList class
|
||||||
* palyList with songs info
|
* palyList with songs info
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
namespace syncLib{
|
|
||||||
|
|
||||||
static const QStringList ValidSongs = {".mp3", ".wav", ".ogg"};
|
static const QStringList ValidSongs = {".mp3", ".wav", ".ogg"};
|
||||||
SongHeader::SongHeader()
|
SongHeader::SongHeader()
|
||||||
{
|
{
|
||||||
@ -161,8 +159,8 @@ QMediaContent SongStorage::toMedia()const{
|
|||||||
return QMediaContent(url);
|
return QMediaContent(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SongStorage::toSong(Song&)const{
|
bool SongStorage::toSong(Song& song)const{
|
||||||
Song song(*((SongHeader*)this));
|
song = (*((SongHeader*)this));
|
||||||
|
|
||||||
QFile f(url.toLocalFile());
|
QFile f(url.toLocalFile());
|
||||||
|
|
||||||
@ -230,4 +228,3 @@ QDataStream& operator >> (QDataStream& stream, Song& song){
|
|||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
#include "chronotime.h"
|
#include "chronotime.h"
|
||||||
#include <QMediaContent>
|
#include <QMediaContent>
|
||||||
|
|
||||||
namespace syncLib {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The Syncer struct
|
* @brief The Syncer struct
|
||||||
*
|
*
|
||||||
@ -18,6 +16,11 @@ struct Syncer
|
|||||||
* @brief seek - wher is play media file
|
* @brief seek - wher is play media file
|
||||||
*/
|
*/
|
||||||
milliseconds seek;
|
milliseconds seek;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief timeOn - when play this media file
|
||||||
|
*/
|
||||||
|
milliseconds timeOn;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,5 +100,4 @@ public:
|
|||||||
friend class MySql;
|
friend class MySql;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
#endif // SONG_H
|
#endif // SONG_H
|
||||||
|
214
sync/sync.cpp
214
sync/sync.cpp
@ -10,8 +10,6 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace syncLib{
|
|
||||||
|
|
||||||
Sync::Sync(const QString &address, int port, const QString &datadir):
|
Sync::Sync(const QString &address, int port, const QString &datadir):
|
||||||
node(nullptr),
|
node(nullptr),
|
||||||
player(nullptr)
|
player(nullptr)
|
||||||
@ -26,27 +24,25 @@ Sync::Sync(const QString &address, int port, const QString &datadir):
|
|||||||
|
|
||||||
player->setPlaylist(playList->getList());
|
player->setPlaylist(playList->getList());
|
||||||
|
|
||||||
|
|
||||||
fbroadcaster = false;
|
|
||||||
resyncCount = 0;
|
|
||||||
lastSyncTime = 0;
|
|
||||||
ping = 0;
|
|
||||||
|
|
||||||
sql = new MySql(datadir);
|
sql = new MySql(datadir);
|
||||||
|
|
||||||
connect(node, SIGNAL(Message(ETcpSocket*)), SLOT(packageRender(ETcpSocket*)));
|
connect(node, SIGNAL(Message(ETcpSocket*)), SLOT(packageRender(ETcpSocket*)));
|
||||||
connect(&deepScaner, SIGNAL(scaned(QList<ETcpSocket*>*)), SLOT(deepScaned(QList<ETcpSocket*>*)));
|
connect(&deepScaner, SIGNAL(scaned(QList<ETcpSocket*>*)), SLOT(deepScaned(QList<ETcpSocket*>*)));
|
||||||
connect(player, SIGNAL(positionChanged(qint64)), SIGNAL(seekChanged(qint64)));
|
connect(player, SIGNAL(positionChanged(qint64)), SIGNAL(seekChanged(qint64)));
|
||||||
connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(endPlay(QMediaPlayer::State)));
|
connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(endPlay(QMediaPlayer::State)));
|
||||||
|
connect(node, SIGNAL(NodeSynced(ETcpSocket*)), SLOT(clientSynced(ETcpSocket*)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MySql* Sync::getSqlApi(){
|
MySql* Sync::getSqlApi(){
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sync::setSingle(const QMediaContent& media){
|
bool Sync::setSingle(const SongStorage& media){
|
||||||
playList->clear();
|
playList->clear();
|
||||||
playList->addMedia(media);
|
if(!playList->addMedia(media)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
emit currentPlayListChanged();
|
emit currentPlayListChanged();
|
||||||
return true;
|
return true;
|
||||||
@ -71,9 +67,9 @@ const QString& Sync::getPlayListName() const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Sync::play(bool fbroadcast){
|
bool Sync::play(bool fbroadcast){
|
||||||
fbroadcaster = fbroadcast;
|
node->setBroadcaster(fbroadcast);
|
||||||
|
|
||||||
if(fbroadcaster){
|
if(fbroadcast){
|
||||||
player->play();
|
player->play();
|
||||||
sync();
|
sync();
|
||||||
}else{
|
}else{
|
||||||
@ -95,7 +91,9 @@ bool Sync::play(const SongStorage &song, bool fbroadcast){
|
|||||||
}
|
}
|
||||||
|
|
||||||
playList->clear();
|
playList->clear();
|
||||||
playList->addMedia(song);
|
if(!playList->addMedia(song)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return play(fbroadcast);
|
return play(fbroadcast);
|
||||||
}
|
}
|
||||||
@ -126,9 +124,9 @@ bool Sync::play(const Song &song, bool fbroadcast){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMediaContent savedSong;
|
SongStorage savedSong;
|
||||||
if(!sql->find(static_cast<const SongHeader&>(song), savedSong) && sql->save(song) > -1 &&
|
if(!sql->find(static_cast<const SongHeader&>(song), savedSong) && sql->save(song) > -1 &&
|
||||||
!sql->find((SongHeader&)song, savedSong)){
|
!sql->find(static_cast<const SongHeader&>(song), savedSong)){
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -136,19 +134,6 @@ bool Sync::play(const Song &song, bool fbroadcast){
|
|||||||
return play(savedSong, fbroadcast);
|
return play(savedSong, fbroadcast);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sync::play(const QMediaContent& media, bool fbroadcast){
|
|
||||||
|
|
||||||
if(media.isNull()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!setSingle(media)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Sync::play(fbroadcast);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Sync::play(int id_song, bool fbroadcast){
|
bool Sync::play(int id_song, bool fbroadcast){
|
||||||
|
|
||||||
if(id_song < 0){
|
if(id_song < 0){
|
||||||
@ -209,40 +194,62 @@ void Sync::stop(){
|
|||||||
|
|
||||||
void Sync::jump(const qint64 seek){
|
void Sync::jump(const qint64 seek){
|
||||||
player->setPosition(seek);
|
player->setPosition(seek);
|
||||||
|
sync();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sync::isReadyToSync()const{
|
bool Sync::isReadyToSync()const{
|
||||||
return !fbroadcaster && player->isSeekable()
|
return !node->isBroadcaster() && player->isSeekable()
|
||||||
&& (player->state() == QMediaPlayer::PlayingState);
|
&& (player->state() == QMediaPlayer::PlayingState);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sync::sync(const Syncer &sync, milliseconds ping){
|
bool Sync::sync(const Syncer &sync){
|
||||||
if(!isReadyToSync()){
|
milliseconds now = sync.timeOn - ChronoTime::now();
|
||||||
|
if(!isReadyToSync() || now < 0 || now > SYNC_TIME){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
player->setPosition(sync.seek + ping);
|
|
||||||
|
// QTimer::singleShot(now, [=](){
|
||||||
|
// player->setPosition(sync.seek);
|
||||||
|
|
||||||
|
// player->syncEnd();
|
||||||
|
// } );
|
||||||
|
|
||||||
|
while (ChronoTime::now() < sync.timeOn) { }
|
||||||
|
player->setPosition(sync.seek);
|
||||||
player->syncEnd();
|
player->syncEnd();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @todo thi nead send a hedaer
|
|
||||||
*/
|
|
||||||
void Sync::sync(){
|
void Sync::sync(){
|
||||||
|
|
||||||
if(fbroadcaster)
|
if(node->isBroadcaster()) {
|
||||||
QTimer::singleShot(SYNC_TIME, [=]() {
|
for(ETcpSocket *i: *node->getClients()){
|
||||||
|
sync(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sync::sync(ETcpSocket* socket){
|
||||||
|
|
||||||
|
if(node->isBroadcaster()) {
|
||||||
|
|
||||||
|
if(!socket->isSynced()){
|
||||||
|
socket->sync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
package pac;
|
||||||
|
if(!createPackage(t_sync, pac, socket->getTime())){
|
||||||
|
CreatePackageExaption();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
node->WriteAll(pac.parseTo());
|
||||||
|
}
|
||||||
|
|
||||||
package pac;
|
|
||||||
if(!createPackage(t_sync, pac)){
|
|
||||||
CreatePackageExaption();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
node->WriteAll(pac.parseTo());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sync::addNode(const QString ip, int port){
|
bool Sync::addNode(const QString ip, int port){
|
||||||
@ -267,6 +274,10 @@ bool Sync::listen(ETcpSocket *server){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!server->isValid()){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(!server->getSource()->isOpen() && server->getSource()->open(QIODevice::ReadWrite)){
|
if(!server->getSource()->isOpen() && server->getSource()->open(QIODevice::ReadWrite)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -279,28 +290,28 @@ bool Sync::listen(ETcpSocket *server){
|
|||||||
return server->Write(pac.parseTo());
|
return server->Write(pac.parseTo());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sync::createPackage(Type type, package &pac){
|
bool Sync::createPackage(Type type, package &pac, milliseconds time){
|
||||||
|
|
||||||
pac.clear();
|
pac.clear();
|
||||||
|
|
||||||
pac.type = type;
|
pac.type = type;
|
||||||
|
|
||||||
if(type & TypePackage::t_sync){
|
bool isbroadcaster = node->isBroadcaster();
|
||||||
if(fbroadcaster)
|
|
||||||
pac.playdata.seek = player->position();
|
if(type & TypePackage::t_sync && isbroadcaster){
|
||||||
else
|
pac.playdata.seek = player->position() + SYNC_TIME;
|
||||||
lastSyncTime = ChronoTime::now();
|
pac.playdata.timeOn = ChronoTime::now(time) + SYNC_TIME;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type & TypePackage::t_song_h && fbroadcaster){
|
if(type & TypePackage::t_song_h && isbroadcaster ){
|
||||||
if(playList->getList()->currentIndex() < 0)
|
if(playList->getList()->currentIndex() < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pac.header = *playList->currentHeader();
|
pac.header = *playList->currentHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(type & TypePackage::t_song && fbroadcaster){
|
if(type & TypePackage::t_song && isbroadcaster){
|
||||||
if(playList->getList()->currentIndex() < 0)
|
if(playList->getList()->currentIndex() < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -309,7 +320,7 @@ bool Sync::createPackage(Type type, package &pac){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fbroadcaster)
|
if(isbroadcaster)
|
||||||
pac.type = TypePackage(pac.type | t_brodcaster);
|
pac.type = TypePackage(pac.type | t_brodcaster);
|
||||||
|
|
||||||
return pac.isValid();
|
return pac.isValid();
|
||||||
@ -321,7 +332,6 @@ void Sync::packageRender(ETcpSocket *socket){
|
|||||||
while((array = socket->topStack())){
|
while((array = socket->topStack())){
|
||||||
package pkg;
|
package pkg;
|
||||||
if(!pkg.parseFrom((*array))){
|
if(!pkg.parseFrom((*array))){
|
||||||
throw BadAnswerExaption();
|
|
||||||
socket->nextItem();
|
socket->nextItem();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -339,44 +349,22 @@ void Sync::packageRender(ETcpSocket *socket){
|
|||||||
emit networkStateChange();
|
emit networkStateChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pkg.getType() & t_brodcaster){
|
if(pkg.getType() & t_brodcaster && !node->isBroadcaster()){
|
||||||
|
|
||||||
// if requst from server
|
// if requst from server
|
||||||
|
|
||||||
// calc ping for sync
|
if(pkg.getType() & t_pause){
|
||||||
bool fFromRequst = false;
|
pause(true);
|
||||||
if(lastSyncTime){
|
|
||||||
ping = ChronoTime::now() - lastSyncTime;
|
|
||||||
lastSyncTime = 0;
|
|
||||||
fFromRequst = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pkg.getType() & t_sync &&
|
if(pkg.getType() & t_sync && !sync(pkg.getPlayData())){
|
||||||
!sync(pkg.getPlayData(), (fFromRequst)? ping: ping/2)){
|
|
||||||
|
|
||||||
QTimer::singleShot(RESYNC_TIME, [=]() {
|
package answer;
|
||||||
package pac;
|
if(!createPackage(t_sync, answer)){
|
||||||
|
CreatePackageExaption();
|
||||||
if(resyncCount < MAX_RESYNC_COUNT){
|
socket->nextItem();
|
||||||
|
}
|
||||||
if(!createPackage(t_sync, pac)){
|
socket->Write(answer.parseTo());
|
||||||
throw CreatePackageExaption();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
resyncCount++;
|
|
||||||
|
|
||||||
}else{
|
|
||||||
resyncCount = 0;
|
|
||||||
throw SyncCountError();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
node->WriteAll(pac.parseTo());
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (pkg.getType() & t_sync){
|
|
||||||
resyncCount = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pkg.getType() & t_play && !play(pkg.getHeader(), false) && !play(pkg.getSong(), false)){
|
if(pkg.getType() & t_play && !play(pkg.getHeader(), false) && !play(pkg.getSong(), false)){
|
||||||
@ -388,7 +376,6 @@ void Sync::packageRender(ETcpSocket *socket){
|
|||||||
|
|
||||||
package answer;
|
package answer;
|
||||||
if(!createPackage(requestType | t_play, answer)){
|
if(!createPackage(requestType | t_play, answer)){
|
||||||
throw CreatePackageExaption();
|
|
||||||
socket->nextItem();
|
socket->nextItem();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -398,18 +385,17 @@ void Sync::packageRender(ETcpSocket *socket){
|
|||||||
|
|
||||||
package answer;
|
package answer;
|
||||||
if(!createPackage(t_sync, answer)){
|
if(!createPackage(t_sync, answer)){
|
||||||
throw CreatePackageExaption();
|
|
||||||
socket->nextItem();
|
socket->nextItem();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
socket->Write(answer.parseTo());
|
socket->Write(answer.parseTo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(pkg.getType() & t_close){
|
if(pkg.getType() & t_close){
|
||||||
socket->getSource()->close();
|
socket->getSource()->close();
|
||||||
node->getClients()->removeOne(socket);
|
node->getClients()->removeOne(socket);
|
||||||
|
servers.removeOne(socket);
|
||||||
|
emit networkStateChange();
|
||||||
delete socket;
|
delete socket;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -417,37 +403,34 @@ void Sync::packageRender(ETcpSocket *socket){
|
|||||||
if(pkg.getType() & t_what){
|
if(pkg.getType() & t_what){
|
||||||
package answer;
|
package answer;
|
||||||
if(!createPackage(t_void, answer)){
|
if(!createPackage(t_void, answer)){
|
||||||
throw CreatePackageExaption();
|
|
||||||
socket->nextItem();
|
socket->nextItem();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
socket->Write(answer.parseTo());
|
socket->Write(answer.parseTo());
|
||||||
}
|
}
|
||||||
|
|
||||||
}else{
|
} else if (node->isBroadcaster()) {
|
||||||
|
// if requst from client
|
||||||
|
|
||||||
// if requst from client
|
if(pkg.getType() & t_sync){
|
||||||
if(pkg.getType() & t_play & t_sync){
|
if(socket->isSynced()){
|
||||||
if(playList->getList()->currentIndex() < 0){
|
sync(socket);
|
||||||
throw SyncError();
|
} else {
|
||||||
socket->nextItem();
|
socket->sync();
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
package answer;
|
|
||||||
if(!createPackage(pkg.getType() & ~t_what & ~t_stop & ~t_brodcaster, answer)){
|
|
||||||
throw CreatePackageExaption();
|
|
||||||
socket->nextItem();
|
socket->nextItem();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
socket->Write(answer.parseTo());
|
|
||||||
|
package answer;
|
||||||
|
if(createPackage(pkg.getType() & ~t_sync & ~t_pause & ~t_what & ~t_close & ~t_brodcaster, answer)){
|
||||||
|
socket->Write(answer.parseTo());
|
||||||
|
}
|
||||||
|
|
||||||
if(pkg.getType() & t_close){
|
if(pkg.getType() & t_close){
|
||||||
socket->getSource()->close();
|
socket->getSource()->close();
|
||||||
node->getClients()->removeOne(socket);
|
node->getClients()->removeOne(socket);
|
||||||
delete socket;
|
delete socket;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -459,7 +442,6 @@ void Sync::packageRender(ETcpSocket *socket){
|
|||||||
void Sync::rescan(bool deep){
|
void Sync::rescan(bool deep){
|
||||||
package pac;
|
package pac;
|
||||||
if(!createPackage(t_what, pac)){
|
if(!createPackage(t_what, pac)){
|
||||||
throw CreatePackageExaption();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
node->WriteAll(pac.parseTo());
|
node->WriteAll(pac.parseTo());
|
||||||
@ -473,7 +455,6 @@ void Sync::rescan(bool deep){
|
|||||||
void Sync::deepScaned(QList<ETcpSocket *> * list){
|
void Sync::deepScaned(QList<ETcpSocket *> * list){
|
||||||
package pac;
|
package pac;
|
||||||
if(!createPackage(t_what, pac)){
|
if(!createPackage(t_what, pac)){
|
||||||
throw CreatePackageExaption();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QByteArray array = pac.parseTo();
|
QByteArray array = pac.parseTo();
|
||||||
@ -487,7 +468,7 @@ void Sync::endPlay(QMediaPlayer::State state){
|
|||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case QMediaPlayer::StoppedState:
|
case QMediaPlayer::StoppedState:
|
||||||
fbroadcaster = false;
|
node->setBroadcaster(false);
|
||||||
break;
|
break;
|
||||||
case QMediaPlayer::PlayingState:
|
case QMediaPlayer::PlayingState:
|
||||||
sync();
|
sync();
|
||||||
@ -495,8 +476,6 @@ void Sync::endPlay(QMediaPlayer::State state){
|
|||||||
|
|
||||||
case QMediaPlayer::PausedState:
|
case QMediaPlayer::PausedState:
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emit playStateChanged();
|
emit playStateChanged();
|
||||||
@ -511,17 +490,17 @@ bool Sync::setValume(unsigned int valume){
|
|||||||
if(valume > 100 || !player->isSynced())
|
if(valume > 100 || !player->isSynced())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
player->setVolume(valume);
|
player->setVolume(static_cast<int>(valume));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Sync::getValume() const{
|
unsigned int Sync::getValume() const{
|
||||||
return player->volume();
|
return static_cast<unsigned int>(player->volume());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Sync::seek() const{
|
unsigned int Sync::seek() const{
|
||||||
return player->position();
|
return static_cast<unsigned int>(player->position());
|
||||||
}
|
}
|
||||||
|
|
||||||
const QList<SongStorage>* Sync::getPlayList() const{
|
const QList<SongStorage>* Sync::getPlayList() const{
|
||||||
@ -554,8 +533,8 @@ bool Sync::updatePlayList(const QString &_playList){
|
|||||||
if(!playList->size())
|
if(!playList->size())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(fbroadcaster){
|
if(node->isBroadcaster()){
|
||||||
play(fbroadcaster);
|
play(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -584,6 +563,10 @@ QMediaPlayer::State Sync::playState()const{
|
|||||||
return player->state();
|
return player->state();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sync::clientSynced(ETcpSocket* socket){
|
||||||
|
sync(socket);
|
||||||
|
}
|
||||||
|
|
||||||
Sync::~Sync(){
|
Sync::~Sync(){
|
||||||
delete node;
|
delete node;
|
||||||
delete player;
|
delete player;
|
||||||
@ -593,6 +576,5 @@ Sync::~Sync(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
28
sync/sync.h
28
sync/sync.h
@ -10,8 +10,6 @@
|
|||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "playlist.h"
|
#include "playlist.h"
|
||||||
|
|
||||||
namespace syncLib {
|
|
||||||
|
|
||||||
typedef std::chrono::time_point<std::chrono::high_resolution_clock> Clock;
|
typedef std::chrono::time_point<std::chrono::high_resolution_clock> Clock;
|
||||||
|
|
||||||
class Node;
|
class Node;
|
||||||
@ -30,10 +28,6 @@ private:
|
|||||||
PlayList *playList;
|
PlayList *playList;
|
||||||
QString lastUsedPlayList;
|
QString lastUsedPlayList;
|
||||||
QList<ETcpSocket*> servers;
|
QList<ETcpSocket*> servers;
|
||||||
bool fbroadcaster;
|
|
||||||
int resyncCount;
|
|
||||||
int lastSyncTime;
|
|
||||||
int ping;
|
|
||||||
LocalScanner deepScaner;
|
LocalScanner deepScaner;
|
||||||
MySql *sql;
|
MySql *sql;
|
||||||
int port;
|
int port;
|
||||||
@ -50,15 +44,17 @@ private:
|
|||||||
* @param pac - the resulting value
|
* @param pac - the resulting value
|
||||||
* @return true if everything's done
|
* @return true if everything's done
|
||||||
*/
|
*/
|
||||||
bool createPackage(Type type , package& pac);
|
bool createPackage(Type type , package& pac, milliseconds time = 0);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
|
void clientSynced(ETcpSocket*);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief setSingle set singl or temp playlist
|
* @brief setSingle set singl or temp playlist
|
||||||
* @return true if all done
|
* @return true if all done
|
||||||
*/
|
*/
|
||||||
bool setSingle(const QMediaContent& media);
|
bool setSingle(const SongStorage &media);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief updateSongs use method update avelable songs from sql database
|
* @brief updateSongs use method update avelable songs from sql database
|
||||||
@ -115,14 +111,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool play(bool fbroadcast = true);
|
bool play(bool fbroadcast = true);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Play song in this device, if device has not supported playning media data this method throw MediaExcrption.
|
|
||||||
* @param header of song
|
|
||||||
* @param fbroadcast - server broadcasting sound.
|
|
||||||
* @return true if all done else false.
|
|
||||||
*/
|
|
||||||
bool play(const QMediaContent &media, bool fbroadcast = true);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Play song in this device, if device has not supported playning media data this method throw MediaExcrption.
|
* @brief Play song in this device, if device has not supported playning media data this method throw MediaExcrption.
|
||||||
* @param header of song
|
* @param header of song
|
||||||
@ -179,7 +167,7 @@ public:
|
|||||||
* @brief sync with server
|
* @brief sync with server
|
||||||
* @param sync - data of sync
|
* @param sync - data of sync
|
||||||
*/
|
*/
|
||||||
bool sync(const Syncer& sync, milliseconds ping);
|
bool sync(const Syncer& sync);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief isReadyToSync
|
* @brief isReadyToSync
|
||||||
@ -192,6 +180,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void sync();
|
void sync();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief sync with clients
|
||||||
|
*/
|
||||||
|
void sync(ETcpSocket *socket);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief addNode add new connect
|
* @brief addNode add new connect
|
||||||
* @param ip of connection
|
* @param ip of connection
|
||||||
@ -345,7 +338,6 @@ signals:
|
|||||||
void playStateChanged();
|
void playStateChanged();
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // SYNC_H
|
#endif // SYNC_H
|
||||||
|
113
sync/syncpackage.cpp
Normal file
113
sync/syncpackage.cpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#include "syncpackage.h"
|
||||||
|
#include <QDataStream>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
SyncPackage::SyncPackage()
|
||||||
|
{
|
||||||
|
type = TypeSyncPackage::t_voidSync;
|
||||||
|
firstByte = sourceBytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SyncPackage::isValid() const{
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case TypeSyncPackage::t_voidSync:
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case TypeSyncPackage::t_Header:
|
||||||
|
return firstByte >= 0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return firstByte >= 0 && sourceBytes != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncPackage::clear(){
|
||||||
|
type = TypeSyncPackage::t_voidSync;
|
||||||
|
firstByte = 0;
|
||||||
|
sourceBytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray SyncPackage::parseTo(){
|
||||||
|
QByteArray temp;
|
||||||
|
QDataStream stream(&temp, QIODevice::WriteOnly);
|
||||||
|
temp.clear();
|
||||||
|
if(isValid()){
|
||||||
|
stream << static_cast<unsigned char>(type);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
|
||||||
|
case TypeSyncPackage::t_End:
|
||||||
|
stream << firstByte;
|
||||||
|
stream << sourceBytes;
|
||||||
|
stream << nativeTime;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
stream << firstByte;
|
||||||
|
stream << sourceBytes;
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qDebug() << "package synk is not valid!!!";
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SyncPackage::parseFrom(QByteArray &array){
|
||||||
|
type = TypeSyncPackage::t_voidSync;
|
||||||
|
QDataStream stream(&array, QIODevice::ReadOnly);
|
||||||
|
|
||||||
|
unsigned char temp_type;
|
||||||
|
stream >> temp_type;
|
||||||
|
type = static_cast<TypeSyncPackage> (temp_type);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
|
||||||
|
case TypeSyncPackage::t_End:
|
||||||
|
stream >> firstByte;
|
||||||
|
stream >> sourceBytes;
|
||||||
|
stream >> nativeTime;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
stream >> firstByte;
|
||||||
|
stream >> sourceBytes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeSyncPackage SyncPackage::getType()const {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
char SyncPackage::getIndex()const {
|
||||||
|
return firstByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
const milliseconds& SyncPackage::getNative()const {
|
||||||
|
return nativeTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
const milliseconds& SyncPackage::getTime()const {
|
||||||
|
return sourceBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
const milliseconds& SyncPackage::getPing()const {
|
||||||
|
return sourceBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
char SyncPackage::getPrecision()const {
|
||||||
|
return firstByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SyncPackage::isSended()const {
|
||||||
|
return type == TypeSyncPackage::t_Responce && firstByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncPackage::~SyncPackage(){}
|
100
sync/syncpackage.h
Normal file
100
sync/syncpackage.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#ifndef SYNCPACKAGE_H
|
||||||
|
#define SYNCPACKAGE_H
|
||||||
|
|
||||||
|
#include "chronotime.h"
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
|
class ETcpSocket;
|
||||||
|
|
||||||
|
enum TypeSyncPackage{
|
||||||
|
t_voidSync = 0x00,
|
||||||
|
t_Header = 0x01,
|
||||||
|
t_Responce = 0x02,
|
||||||
|
t_Source = 0x04,
|
||||||
|
t_End = 0x08
|
||||||
|
};
|
||||||
|
|
||||||
|
class SyncPackage
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
TypeSyncPackage type;
|
||||||
|
qint8 firstByte;
|
||||||
|
milliseconds ping;
|
||||||
|
milliseconds nativeTime;
|
||||||
|
milliseconds sourceBytes;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SyncPackage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getType
|
||||||
|
* @return type of package
|
||||||
|
*/
|
||||||
|
TypeSyncPackage getType() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getIndex
|
||||||
|
* @return return index
|
||||||
|
*/
|
||||||
|
char getIndex()const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getDelay
|
||||||
|
* @return return delay
|
||||||
|
*/
|
||||||
|
const milliseconds& getNative()const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getTime
|
||||||
|
* @return time
|
||||||
|
*/
|
||||||
|
const milliseconds& getTime()const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getPing
|
||||||
|
* @return ping
|
||||||
|
*/
|
||||||
|
const milliseconds& getPing()const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getPrecision
|
||||||
|
* @return precision
|
||||||
|
*/
|
||||||
|
char getPrecision()const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief isSended
|
||||||
|
* @return true if package sended
|
||||||
|
*/
|
||||||
|
bool isSended()const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief isValid
|
||||||
|
* @return true if package is valid
|
||||||
|
*/
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief clear all date of package
|
||||||
|
*/
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief parseTo parse this package to byte array
|
||||||
|
* @return byte array
|
||||||
|
*/
|
||||||
|
QByteArray parseTo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief parseFrom create a package from bytes
|
||||||
|
* @param array of bytes
|
||||||
|
* @return true if package valid
|
||||||
|
*/
|
||||||
|
bool parseFrom(QByteArray& array);
|
||||||
|
|
||||||
|
~SyncPackage();
|
||||||
|
friend class ETcpSocket;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SYNCPACKAGE_H
|
11
testLocalTimer/main.cpp
Normal file
11
testLocalTimer/main.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "mainwindow.h"
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
MainWindow w;
|
||||||
|
w.show();
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
39
testLocalTimer/mainwindow.cpp
Normal file
39
testLocalTimer/mainwindow.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "mainwindow.h"
|
||||||
|
#include "ui_mainwindow.h"
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
|
QMainWindow(parent),
|
||||||
|
ui(new Ui::MainWindow) {
|
||||||
|
ui->setupUi(this);
|
||||||
|
timer.setInterval(0);
|
||||||
|
color = Qt::white;
|
||||||
|
connect(&timer, &QTimer::timeout, this, &MainWindow::handleTick);
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::keyPressEvent(QKeyEvent * key) {
|
||||||
|
|
||||||
|
if (key->key() == Qt::Key_Space) {
|
||||||
|
if (timer.isActive()) {
|
||||||
|
timer.stop();
|
||||||
|
} else {
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow() {
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::handleTick() {
|
||||||
|
|
||||||
|
auto time = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
|
||||||
|
ui->msec->setText(QString::number(time));
|
||||||
|
}
|
28
testLocalTimer/mainwindow.h
Normal file
28
testLocalTimer/mainwindow.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef MAINWINDOW_H
|
||||||
|
#define MAINWINDOW_H
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class MainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainWindow : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MainWindow(QWidget *parent = nullptr);
|
||||||
|
void keyPressEvent(QKeyEvent*);
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTimer timer;
|
||||||
|
QColor color;
|
||||||
|
Ui::MainWindow *ui;
|
||||||
|
private slots:
|
||||||
|
void handleTick();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MAINWINDOW_H
|
66
testLocalTimer/mainwindow.ui
Normal file
66
testLocalTimer/mainwindow.ui
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MainWindow</class>
|
||||||
|
<widget class="QMainWindow" name="MainWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MainWindow</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralWidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="msec">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">font: 48pt "Ubuntu";</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenuBar" name="menuBar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QToolBar" name="mainToolBar">
|
||||||
|
<attribute name="toolBarArea">
|
||||||
|
<enum>TopToolBarArea</enum>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="toolBarBreak">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusBar"/>
|
||||||
|
</widget>
|
||||||
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
38
testLocalTimer/testLocalTimer.pro
Normal file
38
testLocalTimer/testLocalTimer.pro
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#-------------------------------------------------
|
||||||
|
#
|
||||||
|
# Project created by QtCreator 2018-08-16T20:39:30
|
||||||
|
#
|
||||||
|
#-------------------------------------------------
|
||||||
|
|
||||||
|
QT += core gui widgets
|
||||||
|
|
||||||
|
TARGET = testLocalTimer
|
||||||
|
TEMPLATE = app
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
CONFIG += c++11
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
main.cpp \
|
||||||
|
mainwindow.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
mainwindow.h
|
||||||
|
|
||||||
|
FORMS += \
|
||||||
|
mainwindow.ui
|
||||||
|
|
||||||
|
# Default rules for deployment.
|
||||||
|
qnx: target.path = /tmp/$${TARGET}/bin
|
||||||
|
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||||
|
!isEmpty(target.path): INSTALLS += target
|
Loading…
x
Reference in New Issue
Block a user