SoundBand/Sync/sync.cpp

581 lines
12 KiB
C++
Raw Normal View History

2017-10-29 14:47:36 +03:00
#include "sync.h"
2017-11-09 23:09:59 +03:00
#include <QtSql>
#include <QMultimedia>
#include <QSqlQuery>
2017-11-11 14:03:14 +03:00
#include "exaptions.h"
2017-12-17 02:05:07 +03:00
#include "chronotime.h"
2018-03-11 14:38:08 +03:00
#include "cmath"
2017-11-06 01:33:16 +03:00
2017-11-09 23:09:59 +03:00
#ifdef QT_DEBUG
#include <QDebug>
#endif
2018-01-19 15:03:07 +03:00
Sync::Sync(const QString &address, int port, const QString &datadir):
2017-11-27 02:01:47 +03:00
node(nullptr),
2018-02-10 20:52:21 +03:00
player(nullptr)
2017-11-27 02:01:47 +03:00
{
node = new Node(address , this->port = port);
2017-11-27 22:59:59 +03:00
2018-09-30 17:38:38 +03:00
player = new Player(nullptr, QMediaPlayer::LowLatency);
2017-11-11 14:03:14 +03:00
if(!player->isAvailable()){
throw MediaException();
}
2018-04-02 01:03:27 +03:00
playList = new PlayList;
player->setPlaylist(playList->getList());
2017-11-27 02:01:47 +03:00
2017-12-24 22:04:40 +03:00
sql = new MySql(datadir);
2017-11-27 02:01:47 +03:00
2017-12-03 23:08:43 +03:00
connect(node, SIGNAL(Message(ETcpSocket*)), SLOT(packageRender(ETcpSocket*)));
connect(&deepScaner, SIGNAL(scaned(QList<ETcpSocket*>*)), SLOT(deepScaned(QList<ETcpSocket*>*)));
connect(player, SIGNAL(positionChanged(qint64)), SIGNAL(seekChanged(qint64)));
connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(endPlay(QMediaPlayer::State)));
2018-08-16 09:13:18 +03:00
connect(node, SIGNAL(NodeSynced(ETcpSocket*)), SLOT(clientSynced(ETcpSocket*)));
2017-12-03 23:08:43 +03:00
}
2018-01-19 15:03:07 +03:00
MySql* Sync::getSqlApi(){
return sql;
}
2018-08-16 09:13:18 +03:00
bool Sync::setSingle(const SongStorage& media){
2018-04-05 21:54:49 +03:00
playList->clear();
2018-08-16 09:13:18 +03:00
if(!playList->addMedia(media)) {
return false;
}
2018-04-05 21:54:49 +03:00
emit currentPlayListChanged();
return true;
}
2018-03-29 22:02:03 +03:00
bool Sync::updateSongs(PlayList& list, const QString& playList){
2018-03-06 22:10:46 +03:00
if(!sql->updateAvailableSongs(list, playList)){
return false;
}
2018-03-08 16:08:40 +03:00
if(lastUsedPlayList != playList){
lastUsedPlayList = playList;
emit selectedNewPlatList();
}
2018-03-10 12:19:18 +03:00
emit currentPlayListChanged();
2018-03-06 22:10:46 +03:00
return true;
}
2018-03-11 14:38:08 +03:00
const QString& Sync::getPlayListName() const{
return lastUsedPlayList;
}
2018-03-29 00:23:53 +03:00
bool Sync::play(bool fbroadcast){
2018-08-16 09:13:18 +03:00
node->setBroadcaster(fbroadcast);
2017-12-03 23:08:43 +03:00
2018-08-16 09:13:18 +03:00
if(fbroadcast){
2018-03-29 00:23:53 +03:00
player->play();
sync();
}else{
player->syncBegin();
2017-12-03 23:08:43 +03:00
}
2018-03-29 00:23:53 +03:00
emit currentSongChanged();
2017-12-03 23:08:43 +03:00
2018-03-29 00:23:53 +03:00
return true;
2017-11-09 23:09:59 +03:00
}
2018-04-02 01:03:27 +03:00
bool Sync::play(const SongStorage &song, bool fbroadcast){
if(!song.isValid()){
return false;
}
2018-04-05 21:54:49 +03:00
if(playList->selectSong(song)){
return play(fbroadcast);
}
2018-04-02 01:03:27 +03:00
playList->clear();
2018-08-16 09:13:18 +03:00
if(!playList->addMedia(song)){
return false;
}
2018-04-02 01:03:27 +03:00
return play(fbroadcast);
}
2018-01-09 22:14:54 +03:00
bool Sync::play(const SongHeader &header, bool fbroadcast){
2017-12-02 14:35:39 +03:00
2018-03-29 00:23:53 +03:00
if(!header.isValid()){
return false;
}
2018-04-05 21:54:49 +03:00
if(playList->selectSong(header)){
return play(fbroadcast);
}
2018-03-29 00:23:53 +03:00
SongStorage song;
2017-12-24 22:04:40 +03:00
SongHeader newheader = header;
newheader.id = -1;
2018-01-09 22:14:54 +03:00
if(!sql->load(newheader, song)){
2017-11-20 00:37:12 +03:00
return false;
}
2017-12-05 21:25:55 +03:00
2018-04-02 01:03:27 +03:00
return play(song, fbroadcast);
2017-11-20 00:37:12 +03:00
}
2018-01-09 22:14:54 +03:00
bool Sync::play(const Song &song, bool fbroadcast){
2017-12-02 14:35:39 +03:00
if(!song.isValid()){
return false;
}
2018-08-16 09:13:18 +03:00
SongStorage savedSong;
2018-03-29 00:23:53 +03:00
if(!sql->find(static_cast<const SongHeader&>(song), savedSong) && sql->save(song) > -1 &&
2018-08-16 09:13:18 +03:00
!sql->find(static_cast<const SongHeader&>(song), savedSong)){
2018-03-29 00:23:53 +03:00
2017-12-13 22:40:29 +03:00
return false;
}
2017-11-27 02:01:47 +03:00
2018-03-29 00:23:53 +03:00
return play(savedSong, fbroadcast);
}
2018-01-14 15:29:42 +03:00
2018-01-09 22:14:54 +03:00
bool Sync::play(int id_song, bool fbroadcast){
2017-11-11 20:35:30 +03:00
2018-01-19 16:48:22 +03:00
if(id_song < 0){
return false;
}
2017-12-24 22:04:40 +03:00
SongHeader header;
2018-03-29 00:23:53 +03:00
SongStorage song;
2018-04-02 01:03:27 +03:00
header.id = id_song;
if(!sql->load(header, song)){
return false;
}
2017-12-24 22:04:40 +03:00
2018-01-09 22:14:54 +03:00
return Sync::play(song, fbroadcast);
2017-11-11 20:35:30 +03:00
}
2017-11-24 21:17:41 +03:00
bool Sync::play(QString url){
2017-12-06 12:10:04 +03:00
int id = addNewSong(url);
if(id < 0){
2017-11-11 20:35:30 +03:00
return false;
}
2017-12-03 23:08:43 +03:00
2017-12-06 12:10:04 +03:00
return Sync::play(id);
2017-11-11 20:35:30 +03:00
}
2018-03-29 00:23:53 +03:00
QMediaPlaylist::PlaybackMode Sync::repeat()const{
2018-03-29 22:02:03 +03:00
return playList->getList()->playbackMode();
2018-03-11 14:38:08 +03:00
}
2018-03-29 00:23:53 +03:00
void Sync::setRepeat(QMediaPlaylist::PlaybackMode flag){
2018-03-29 22:02:03 +03:00
playList->getList()->setPlaybackMode(flag);
2018-03-11 14:38:08 +03:00
}
2018-01-09 22:14:54 +03:00
bool Sync::pause(bool state){
2018-04-05 21:54:49 +03:00
if(player->state() == QMediaPlayer::StoppedState){
2018-03-29 00:23:53 +03:00
if(playList->isEmpty())
2018-03-11 14:38:08 +03:00
return false;
2018-03-29 00:23:53 +03:00
return play();
2018-03-11 14:38:08 +03:00
}
2018-01-09 22:14:54 +03:00
2017-12-03 17:22:59 +03:00
if(state){
player->pause();
}else{
player->play();
2018-01-09 22:14:54 +03:00
sync();
2017-12-03 17:22:59 +03:00
}
2018-01-09 22:14:54 +03:00
return true;
2017-11-11 20:35:30 +03:00
}
void Sync::stop(){
player->stop();
}
2017-12-03 23:08:43 +03:00
void Sync::jump(const qint64 seek){
2017-11-11 20:35:30 +03:00
player->setPosition(seek);
2018-08-16 09:13:18 +03:00
sync();
2017-11-11 14:03:14 +03:00
}
2018-01-14 15:29:42 +03:00
bool Sync::isReadyToSync()const{
2018-08-16 09:13:18 +03:00
return !node->isBroadcaster() && player->isSeekable()
2018-01-14 15:29:42 +03:00
&& (player->state() == QMediaPlayer::PlayingState);
}
2018-08-16 09:13:18 +03:00
bool Sync::sync(const Syncer &sync){
milliseconds now = sync.timeOn - ChronoTime::now();
2018-08-16 10:19:42 +03:00
if(!isReadyToSync() || now < 0 || now > SYNC_TIME){
2018-01-09 17:59:15 +03:00
return false;
}
2018-08-16 09:13:18 +03:00
2018-08-16 10:19:42 +03:00
// QTimer::singleShot(now, [=](){
// player->setPosition(sync.seek);
2018-08-16 09:13:18 +03:00
2018-08-16 10:19:42 +03:00
// player->syncEnd();
// } );
2018-08-16 20:58:59 +03:00
while (ChronoTime::now() < sync.timeOn) { }
2018-08-16 10:19:42 +03:00
player->setPosition(sync.seek);
player->syncEnd();
2018-01-14 15:29:42 +03:00
return true;
2017-12-17 14:27:21 +03:00
2018-01-09 22:14:54 +03:00
}
2017-12-17 14:27:21 +03:00
2018-01-09 22:14:54 +03:00
void Sync::sync(){
2017-12-17 14:27:21 +03:00
2018-08-16 09:13:18 +03:00
if(node->isBroadcaster()) {
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());
}
2018-01-09 17:59:15 +03:00
2017-11-20 00:37:12 +03:00
}
2017-11-27 19:43:11 +03:00
bool Sync::addNode(const QString ip, int port){
if(!node->addNode(ip, port))
return false;
rescan();
return true;
}
void Sync::scan(){
rescan(true);
}
const QList<ETcpSocket*>& Sync::getServersList() const{
return servers;
}
bool Sync::listen(ETcpSocket *server){
if(!server){
return false;
}
2018-08-16 09:13:18 +03:00
if(!server->isValid()){
return false;
}
2017-11-27 19:43:11 +03:00
if(!server->getSource()->isOpen() && server->getSource()->open(QIODevice::ReadWrite)){
return false;
}
package pac;
2018-01-09 22:14:54 +03:00
if(!createPackage(t_play, pac)){
2017-11-27 19:43:11 +03:00
return false;
}
return server->Write(pac.parseTo());
}
2018-08-16 09:13:18 +03:00
bool Sync::createPackage(Type type, package &pac, milliseconds time){
2018-01-09 22:14:54 +03:00
2017-11-20 00:37:12 +03:00
pac.clear();
2017-11-21 16:44:55 +03:00
pac.type = type;
2017-11-20 00:37:12 +03:00
2018-08-16 09:13:18 +03:00
bool isbroadcaster = node->isBroadcaster();
2018-08-16 10:48:39 +03:00
if(type & TypePackage::t_sync && isbroadcaster){
2018-08-16 09:13:18 +03:00
pac.playdata.seek = player->position() + SYNC_TIME;
pac.playdata.timeOn = ChronoTime::now(time) + SYNC_TIME;
2017-11-20 00:37:12 +03:00
2017-11-21 16:44:55 +03:00
}
2018-08-16 09:13:18 +03:00
if(type & TypePackage::t_song_h && isbroadcaster ){
2018-03-29 22:02:03 +03:00
if(playList->getList()->currentIndex() < 0)
2017-11-20 00:37:12 +03:00
return false;
2018-04-02 01:03:27 +03:00
pac.header = *playList->currentHeader();
2017-11-21 16:44:55 +03:00
}
2018-08-16 09:13:18 +03:00
if(type & TypePackage::t_song && isbroadcaster){
2018-03-29 22:02:03 +03:00
if(playList->getList()->currentIndex() < 0)
2017-11-20 00:37:12 +03:00
return false;
2018-04-02 01:03:27 +03:00
if(!playList->currentSong()->toSong(pac.source))
2017-11-20 00:37:12 +03:00
return false;
}
2017-11-24 21:17:41 +03:00
2018-08-16 09:13:18 +03:00
if(isbroadcaster)
2017-11-22 20:05:53 +03:00
pac.type = TypePackage(pac.type | t_brodcaster);
2017-11-21 16:44:55 +03:00
2017-11-20 00:37:12 +03:00
return pac.isValid();
}
2017-11-22 20:05:53 +03:00
void Sync::packageRender(ETcpSocket *socket){
QByteArray *array;
while((array = socket->topStack())){
2017-11-24 21:17:41 +03:00
package pkg;
if(!pkg.parseFrom((*array))){
2017-12-16 16:15:25 +03:00
socket->nextItem();
2017-11-24 21:17:41 +03:00
continue;
}
2017-11-22 20:05:53 +03:00
// package answer;
2017-11-24 21:17:41 +03:00
// scaning servers
2017-11-22 20:05:53 +03:00
2017-11-24 21:17:41 +03:00
if(pkg.getType() & t_brodcaster && servers.indexOf(socket) == -1){
servers.append(socket);
2017-12-03 17:22:59 +03:00
emit networkStateChange();
2017-11-24 21:17:41 +03:00
}
if(!(pkg.getType() & t_brodcaster) && servers.indexOf(socket) != -1){
servers.removeOne(socket);
2017-12-03 17:22:59 +03:00
emit networkStateChange();
2017-11-24 21:17:41 +03:00
}
2017-11-22 20:05:53 +03:00
2018-08-16 09:13:18 +03:00
if(pkg.getType() & t_brodcaster && !node->isBroadcaster()){
2017-11-24 21:17:41 +03:00
// if requst from server
2018-01-14 15:49:26 +03:00
2018-08-16 09:13:18 +03:00
if(pkg.getType() & t_pause){
pause(true);
2018-01-14 15:49:26 +03:00
}
2018-08-16 09:13:18 +03:00
if(pkg.getType() & t_sync && !sync(pkg.getPlayData())){
2018-01-14 15:29:42 +03:00
2018-08-16 09:13:18 +03:00
package answer;
if(!createPackage(t_sync, answer)){
CreatePackageExaption();
socket->nextItem();
}
socket->Write(answer.parseTo());
2017-11-24 21:17:41 +03:00
}
2018-01-09 22:14:54 +03:00
if(pkg.getType() & t_play && !play(pkg.getHeader(), false) && !play(pkg.getSong(), false)){
2017-12-02 14:35:39 +03:00
Type requestType = t_song_h;
2017-11-24 21:17:41 +03:00
2017-12-02 14:35:39 +03:00
if(pkg.getType() & t_song_h)
requestType = t_song;
package answer;
2018-01-09 22:14:54 +03:00
if(!createPackage(requestType | t_play, answer)){
2017-12-16 16:15:25 +03:00
socket->nextItem();
continue;
2017-11-24 21:17:41 +03:00
}
2018-01-10 11:20:19 +03:00
socket->Write(answer.parseTo());
}
2018-01-14 15:29:42 +03:00
else if(pkg.getType() & t_play){
2018-01-11 23:01:47 +03:00
2018-01-10 11:20:19 +03:00
package answer;
if(!createPackage(t_sync, answer)){
socket->nextItem();
continue;
}
2017-12-02 14:35:39 +03:00
socket->Write(answer.parseTo());
2017-11-24 21:17:41 +03:00
}
if(pkg.getType() & t_close){
socket->getSource()->close();
node->getClients()->removeOne(socket);
2018-08-16 09:13:18 +03:00
servers.removeOne(socket);
emit networkStateChange();
2017-11-24 21:17:41 +03:00
delete socket;
2017-12-16 16:15:25 +03:00
return;
2017-11-24 21:17:41 +03:00
}
if(pkg.getType() & t_what){
package answer;
if(!createPackage(t_void, answer)){
2017-12-16 16:15:25 +03:00
socket->nextItem();
continue;
2017-11-24 21:17:41 +03:00
}
socket->Write(answer.parseTo());
}
2018-08-16 09:13:18 +03:00
} else if (node->isBroadcaster()) {
// if requst from client
2017-12-02 14:35:39 +03:00
2018-08-16 09:13:18 +03:00
if(pkg.getType() & t_sync){
if(socket->isSynced()){
sync(socket);
} else {
socket->sync();
2017-11-24 21:17:41 +03:00
}
2018-08-16 09:13:18 +03:00
socket->nextItem();
continue;
2017-11-24 21:17:41 +03:00
}
package answer;
2018-08-16 09:13:18 +03:00
if(createPackage(pkg.getType() & ~t_sync & ~t_pause & ~t_what & ~t_close & ~t_brodcaster, answer)){
socket->Write(answer.parseTo());
2017-11-24 21:17:41 +03:00
}
if(pkg.getType() & t_close){
socket->getSource()->close();
node->getClients()->removeOne(socket);
delete socket;
}
}
2017-11-22 20:05:53 +03:00
2017-11-26 19:19:43 +03:00
socket->nextItem();
2017-11-22 20:05:53 +03:00
}
}
2017-11-22 22:34:55 +03:00
void Sync::rescan(bool deep){
2017-11-22 20:05:53 +03:00
package pac;
2018-03-04 23:19:15 +03:00
if(!createPackage(t_what, pac)){
2017-11-22 20:05:53 +03:00
return;
}
node->WriteAll(pac.parseTo());
2017-11-22 22:34:55 +03:00
if(deep){
deepScaner.setInterval(DEEP_SCANER_INTERVAL);
2017-11-27 19:43:11 +03:00
deepScaner.scane(port);
2017-11-22 22:34:55 +03:00
}
}
void Sync::deepScaned(QList<ETcpSocket *> * list){
package pac;
2018-01-10 19:24:09 +03:00
if(!createPackage(t_what, pac)){
2017-11-22 22:34:55 +03:00
return;
}
QByteArray array = pac.parseTo();
for(ETcpSocket * i: *list){
2017-12-02 13:22:20 +03:00
node->addNode(i);
2017-11-22 22:34:55 +03:00
i->Write(array);
}
2017-11-22 20:05:53 +03:00
}
2017-12-03 23:08:43 +03:00
void Sync::endPlay(QMediaPlayer::State state){
2018-04-05 21:54:49 +03:00
switch (state) {
case QMediaPlayer::StoppedState:
2018-08-16 09:13:18 +03:00
node->setBroadcaster(false);
2018-04-05 21:54:49 +03:00
break;
case QMediaPlayer::PlayingState:
sync();
break;
case QMediaPlayer::PausedState:
break;
2017-12-03 23:08:43 +03:00
}
2018-04-05 21:54:49 +03:00
emit playStateChanged();
2017-12-03 23:08:43 +03:00
}
2017-11-26 19:19:43 +03:00
QString Sync::getVersion(){
2018-03-29 22:02:03 +03:00
return QString(tr("Version") + "%0.%1.%2").
arg(MAJOR_VERSION).arg(MINOR_VERSION).arg(REVISION_VERSION);
2017-11-26 19:19:43 +03:00
}
2017-12-03 17:22:59 +03:00
bool Sync::setValume(unsigned int valume){
2018-01-09 22:14:54 +03:00
if(valume > 100 || !player->isSynced())
2017-12-03 17:22:59 +03:00
return false;
2018-08-16 09:13:18 +03:00
player->setVolume(static_cast<int>(valume));
2017-12-03 17:22:59 +03:00
return true;
}
unsigned int Sync::getValume() const{
2018-08-16 09:13:18 +03:00
return static_cast<unsigned int>(player->volume());
2017-12-03 17:22:59 +03:00
}
unsigned int Sync::seek() const{
2018-08-16 09:13:18 +03:00
return static_cast<unsigned int>(player->position());
2017-12-03 17:22:59 +03:00
}
2018-03-29 22:02:03 +03:00
const QList<SongStorage>* Sync::getPlayList() const{
return playList->getInfo();
2017-12-03 23:08:43 +03:00
}
2018-03-10 12:19:18 +03:00
int Sync::getCurrentSongIndex()const{
2018-03-29 22:02:03 +03:00
return playList->getList()->currentIndex();
2018-02-10 20:52:21 +03:00
}
2018-03-29 22:02:03 +03:00
const SongStorage* Sync::getCurrentSong() const{
2018-04-02 01:03:27 +03:00
return playList->currentSong();
2017-12-03 23:08:43 +03:00
}
qint64 Sync::getEndPoint() const {
return player->duration();
}
2017-12-24 22:04:40 +03:00
int Sync::addNewSong(const QString &url){
int result = sql->save(url);
2018-04-02 01:03:27 +03:00
updateSongs(*playList);
2017-12-24 22:04:40 +03:00
return result;
}
2018-01-22 18:27:59 +03:00
bool Sync::updatePlayList(const QString &_playList){
2018-04-02 01:03:27 +03:00
if(!updateSongs(*playList, _playList)){
2018-01-22 18:27:59 +03:00
return false;
}
2018-04-02 01:03:27 +03:00
if(!playList->size())
2018-01-22 18:27:59 +03:00
return false;
2018-08-16 09:13:18 +03:00
if(node->isBroadcaster()){
play(true);
2018-01-22 18:27:59 +03:00
}
return true;
}
2018-04-02 01:03:27 +03:00
bool Sync::next(){
if(playList->isEmpty())
2018-03-09 23:38:17 +03:00
return false;
2018-04-02 01:03:27 +03:00
playList->next();
2018-04-05 21:54:49 +03:00
emit currentSongChanged();
2018-04-02 01:03:27 +03:00
return true;
2018-03-09 23:38:17 +03:00
}
bool Sync::prev(){
2018-04-02 01:03:27 +03:00
if(playList->isEmpty())
2018-03-09 23:38:17 +03:00
return false;
2018-04-02 01:03:27 +03:00
playList->prev();
2018-04-05 21:54:49 +03:00
emit currentSongChanged();
2018-04-02 01:03:27 +03:00
return true;
2018-03-09 23:38:17 +03:00
}
2018-04-05 21:54:49 +03:00
QMediaPlayer::State Sync::playState()const{
return player->state();
}
2018-08-16 09:13:18 +03:00
void Sync::clientSynced(ETcpSocket* socket){
sync(socket);
}
2017-11-09 23:09:59 +03:00
Sync::~Sync(){
delete node;
delete player;
2017-12-25 18:48:43 +03:00
delete sql;
2018-03-29 22:02:03 +03:00
delete playList;
2017-11-22 20:05:53 +03:00
servers.clear();
2017-12-06 13:18:30 +03:00
2017-10-29 14:47:36 +03:00
}
2017-11-09 23:09:59 +03:00
2017-11-20 00:37:12 +03:00