diff --git a/AlcoParty-Widgets/AlcoParty-Widgets.pro b/AlcoParty-Widgets/AlcoParty-Widgets.pro index fdb9d7c..0dbbdfe 100644 --- a/AlcoParty-Widgets/AlcoParty-Widgets.pro +++ b/AlcoParty-Widgets/AlcoParty-Widgets.pro @@ -32,7 +32,8 @@ SOURCES += \ ../sync/song.cpp \ ../sync/sync.cpp \ servermodel.cpp \ - songmodel.cpp + songmodel.cpp \ + ../sync/chronotime.cpp HEADERS += \ mainwindow.h \ @@ -44,7 +45,8 @@ HEADERS += \ ../sync/song.h \ ../sync/sync.h \ servermodel.h \ - songmodel.h + songmodel.h \ + ../sync/chronotime.h FORMS += \ mainwindow.ui diff --git a/sync/ETcpSocket.cpp b/sync/ETcpSocket.cpp index 043e123..79ed8a8 100755 --- a/sync/ETcpSocket.cpp +++ b/sync/ETcpSocket.cpp @@ -1,6 +1,5 @@ #include "ETcpSocket.h" #include "exaptions.h" -#include "config.h" ETcpSocket::ETcpSocket() { @@ -23,7 +22,10 @@ ETcpSocket::ETcpSocket(const QString& address, int port){ } void ETcpSocket::init(){ - array=new QByteArray; + array = new QByteArray; + fSynced = false; + differenceTime = 0; + 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))); @@ -59,11 +61,77 @@ void ETcpSocket::stateChanged_(QAbstractSocket::SocketState socketState){ void ETcpSocket::readReady_(){ bool sizewrite=array->isEmpty(); - //while(source->bytesAvailable()) array->append(source->readAll()); QDataStream stream(array,QIODevice::ReadOnly); - if(sizewrite) - stream>>size; + if(sizewrite){ + stream >> size; + switch (size) { + case CALIBRATION_SENDER:{ + milliseconds ms; + stream >> ms; + + milliseconds range = ChronoTime::now() - ms; + + QByteArray cArray; + QDataStream stream(&cArray,QIODevice::ReadWrite); + + if(range < MIN_DIFFERENCE){ + stream << CALIBRATION_RECEIVER_DONE; + fSynced = true; + + }else{ + stream << CALIBRATION_RECEIVER; + stream << range; + + } + + source->write(cArray); + return; + } + + + case CALIBRATION_RECEIVER:{ + ping = ChronoTime::now() - lastTime; + milliseconds ms; + stream >> ms; + + differenceTime += ms + ping / 2; + + QByteArray cArray; + QDataStream stream(&cArray,QIODevice::ReadWrite); + stream << CALIBRATION_SENDER; + stream << milliseconds(ChronoTime::now() + differenceTime); + + lastTime = ChronoTime::now(); + source->write(cArray); + return; + + } + + case CALIBRATION_RECEIVER_DONE:{ + + QByteArray cArray; + QDataStream stream(&cArray,QIODevice::ReadWrite); + stream << CALIBRATION_SENDER_DONE; + + stream << milliseconds(-differenceTime); + fSynced = true; + + source->write(cArray); + return; + + } + + case CALIBRATION_SENDER_DONE:{ + + stream >> differenceTime; + + return; + + } + + } + } #ifdef QT_DEBUG qDebug()<<"messae size:"<size(); @@ -77,7 +145,6 @@ void ETcpSocket::readReady_(){ }else{ emit donwload(array->size(),size); } - // emit ReadReady(this); } QString ETcpSocket::name() const{ @@ -112,12 +179,21 @@ QString ETcpSocket::toStringTcp(){ return source->peerAddress().toString(); } +milliseconds ETcpSocket::getDifferenceTime() const{ + return differenceTime; +} + +bool ETcpSocket::isSynced()const{ + return fSynced; +} + bool ETcpSocket::Write(const QByteArray&data){ if(source->state()==QTcpSocket::ConnectedState){ QByteArray array; QDataStream stream(&array,QIODevice::ReadWrite); - stream<seek(0); stream<write(cArray); + } + +} + ETcpSocket::~ETcpSocket() { for(QByteArray*i:ReadyStack){ diff --git a/sync/ETcpSocket.h b/sync/ETcpSocket.h index 344cbb7..786eead 100755 --- a/sync/ETcpSocket.h +++ b/sync/ETcpSocket.h @@ -4,6 +4,14 @@ #include #include #include +#include "chronotime.h" + +#define CALIBRATION_SENDER qint32(-1) +#define CALIBRATION_RECEIVER qint32(-2) +#define CALIBRATION_SENDER_DONE qint32(-3) +#define CALIBRATION_RECEIVER_DONE qint32(-4) + + /** * @brief The ETcpSocket class @@ -25,6 +33,8 @@ * } * */ + + class ETcpSocket:public QObject { Q_OBJECT @@ -35,6 +45,17 @@ private: qint32 size; QList ReadyStack; void init(); + /** + * @brief differenceTime - local time difference in milliseconds + * on milliseconds + */ + milliseconds differenceTime; + /** + * @brief fSynced - whether a time difference was found. + */ + bool fSynced; + milliseconds lastTime; + milliseconds ping; private slots: void connected_(); @@ -70,6 +91,25 @@ public: * @return true if all done else false. */ bool Write(const QByteArray&); + + /** + * @brief getDifferenceTime + * @return Difference Time of remoute node. + */ + milliseconds getDifferenceTime()const; + + /** + * @brief isSynced + * @return + */ + bool isSynced()const; + + /** + * @brief calibration - will calculate the difference in time between the connected node + * and the current node. + */ + void calibration(); + ~ETcpSocket(); public slots: /** @@ -126,6 +166,7 @@ signals: */ void StateChanged(ETcpSocket*,QAbstractSocket::SocketState socketState); + }; #endif // CLIENT_H diff --git a/sync/chronotime.cpp b/sync/chronotime.cpp new file mode 100644 index 0000000..4486e4c --- /dev/null +++ b/sync/chronotime.cpp @@ -0,0 +1,31 @@ +#include "chronotime.h" +#include + +ChronoTime::ChronoTime() +{ + +} + +/* + * information about chrono + * https://stackoverflow.com/questions/31255486/c-how-do-i-convert-a-stdchronotime-point-to-long-and-back + */ + +milliseconds ChronoTime::now(){ + auto tim = std::chrono::system_clock::now(); + auto mc = std::chrono::time_point_cast(tim); + auto epoh = mc.time_since_epoch(); +#ifdef QT_DEBUG + qDebug() << epoh.count(); +#endif + return epoh.count(); +} + +Clock ChronoTime::from(const milliseconds& mc){ + std::chrono::milliseconds dur(mc); + return Clock(dur); +} + +milliseconds ChronoTime::abs(milliseconds number){ + return (number << 1) >> 1; +} diff --git a/sync/chronotime.h b/sync/chronotime.h new file mode 100644 index 0000000..b851892 --- /dev/null +++ b/sync/chronotime.h @@ -0,0 +1,35 @@ +#ifndef CHRONOTIME_H +#define CHRONOTIME_H +#include +#include "config.h" + +/** + * @brief Time_point on nanosecunds (uint64_t) + */ +typedef long long milliseconds; +typedef std::chrono::time_point Clock; + +class ChronoTime +{ +public: + ChronoTime(); + /** + * @brief now - get now time on microsecunds + * @return - count of microsecunds + */ + static milliseconds now(); + /** + * @brief from cast to chrono secunds + * @param mcrs microseconds of uint_64 + * @return microseconds of chrono + */ + static Clock from(const milliseconds &mcrs); + + /** + * @brief abs + * @return module of numver + */ + static milliseconds abs(milliseconds number); +}; + +#endif // CHRONOTIME_H diff --git a/sync/config.h b/sync/config.h index 6e169d2..d4b74ca 100644 --- a/sync/config.h +++ b/sync/config.h @@ -20,6 +20,6 @@ #define DEEP_SCANER_INTERVAL 10000 // 10 sec // sync -#define MIN_DIFFERENCE 100 // millisec +#define MIN_DIFFERENCE 10 // millisec #endif // CONFIG_H diff --git a/sync/exaptions.h b/sync/exaptions.h index 92c095a..ad77203 100644 --- a/sync/exaptions.h +++ b/sync/exaptions.h @@ -71,12 +71,4 @@ public: } }; -class feedbackError:public std::exception -{ -public: - QString what(){ - return QObject::tr("Could not create synchronization confirmation packet."); - } -}; - #endif // EXAPTIONS_H diff --git a/sync/song.h b/sync/song.h index e520645..e6f9521 100644 --- a/sync/song.h +++ b/sync/song.h @@ -3,12 +3,7 @@ #include #include #include -#include "config.h" - -/** - * @brief Time_point on nanosecunds (uint64_t) - */ -typedef quint64 milliseconds; +#include "chronotime.h" namespace syncLib { @@ -23,7 +18,7 @@ struct Syncer */ milliseconds seek; /** - * @brief run when is play media file (int) + * @brief run when is play media file (milliseconds) */ milliseconds run; }; diff --git a/sync/sync.cpp b/sync/sync.cpp index 799c7dd..41da848 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -41,10 +41,6 @@ Sync::Sync(const QString address, int port, const QString &datadir): connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(endPlay(QMediaPlayer::State))); } -int Sync::abs(int number) const{ - return (number << 1) >> 1; -} - bool Sync::findHeader(const Song &song){ for(SongHeader & header: playList){ @@ -179,26 +175,6 @@ bool Sync::load(const SongHeader &song,Song &result){ return true; } -/* - * information about chrono - * https://stackoverflow.com/questions/31255486/c-how-do-i-convert-a-stdchronotime-point-to-long-and-back - */ - -milliseconds Sync::now(){ - auto tim = std::chrono::system_clock::now(); - auto mc = std::chrono::time_point_cast(tim); - auto epoh = mc.time_since_epoch(); -#ifdef QT_DEBUG - qDebug() << epoh.count(); -#endif - return epoh.count(); -} - -Clock Sync::from(const milliseconds& mc){ - std::chrono::milliseconds dur(mc); - return Clock(dur); -} - bool Sync::play(const SongHeader &header, const Syncer *syncdata){ if(!header.isValid()){ @@ -296,13 +272,16 @@ void Sync::jump(const qint64 seek){ } bool Sync::sync(const Syncer &sync){ - milliseconds sync_time = sync.run - now(); + milliseconds sync_time = sync.run - ChronoTime::now(); if(sync_time > MAX_SYNC_TIME && sync_time <= 0) return false; - Clock run_time = from(sync.run); + + Clock run_time = ChronoTime::from(sync.run); + do { std::this_thread::yield(); } while (std::chrono::high_resolution_clock::now() < run_time); + player->setPosition(sync.seek); return true; } @@ -348,14 +327,14 @@ bool Sync::createPackage(Type type, package &pac){ if(type & TypePackage::t_sync && fbroadcaster){ - pac.playdata.run = now() + SYNC_TIME; + pac.playdata.run = ChronoTime::now() + SYNC_TIME; pac.playdata.seek = player->position() + SYNC_TIME; } if( type & TypePackage::t_feedback && !fbroadcaster){ - pac.playdata.run = now(); + pac.playdata.run = ChronoTime::now(); pac.playdata.seek = player->position(); } @@ -467,7 +446,7 @@ void Sync::packageRender(ETcpSocket *socket){ return ; } - unsigned int diff = abs(static_cast(player->position() - (pkg.getPlayData().seek + (now() - pkg.getPlayData().run)))); + unsigned int diff = ChronoTime::abs(player->position() - (pkg.getPlayData().seek + (ChronoTime::now() - pkg.getPlayData().run))); #ifdef QT_DEBUG qDebug() << "diff " << socket->name() <<": " << diff; diff --git a/sync/sync.h b/sync/sync.h index e48d863..677cda3 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -13,7 +13,6 @@ class QSqlQuery; class QBuffer; namespace syncLib { -typedef std::chrono::time_point Clock; class Node; @@ -37,11 +36,6 @@ private: LocalScanner deepScaner; int port; QString dataBaseName; - /** - * @brief abs - * @return module of numver - */ - int abs(int number)const; /** * @brief findHeader set curent song if playList have playng song @@ -87,17 +81,7 @@ private: * @return song drom local database. */ Song fromDataBase(const int id); - /** - * @brief now - get now time on microsecunds - * @return - count of microsecunds - */ - milliseconds now(); - /** - * @brief from cast to chrono secunds - * @param mcrs microseconds of uint_64 - * @return microseconds of chrono - */ - Clock from(const milliseconds &mcrs); + /** * @brief createPackage - Create a package that shows current state of the node * @param type - Type of an answer