SoundBand/sync/sync.cpp

227 lines
5.8 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 <QMediaPlayer>
#include <QSqlQuery>
2017-11-11 14:03:14 +03:00
#include "exaptions.h"
2017-11-11 20:35:30 +03:00
#include "time.h"
#include "thread"
2017-10-29 14:47:36 +03:00
2017-11-09 23:09:59 +03:00
#include "config.h"
2017-11-06 01:33:16 +03:00
2017-11-09 23:09:59 +03:00
#ifdef QT_DEBUG
#include <QDebug>
#endif
namespace syncLib{
Sync::Sync(){
node = new Node();
player = new QMediaPlayer(nullptr,QMediaPlayer::LowLatency);
2017-11-11 14:03:14 +03:00
if(!player->isAvailable()){
throw MediaException();
}
2017-11-09 23:09:59 +03:00
}
void Sync::initDB(){
if(db) return;
2017-11-11 20:35:30 +03:00
*db = QSqlDatabase::addDatabase("QSQLITE");
QDir d(QString("./%0").arg(DATABASE_NAME));
db->setDatabaseName(d.absolutePath());
2017-11-09 23:09:59 +03:00
if(db->open()){
2017-11-11 20:35:30 +03:00
qyery = new QSqlQuery(*db);
2017-11-09 23:09:59 +03:00
QString qyer = QString("CREATE TABLE IF NOT EXISTS %0 "
"id int NOT NULL AUTO_INCREMENT,"
"name VARCHAR(100),"
"size INT NOT NULL,"
"data BLOB NOT NULL").arg(DATATABLE_NAME);
qyery->exec(qyer);
}
}
2017-11-11 20:35:30 +03:00
int Sync::save(const Song &song){
2017-11-09 23:09:59 +03:00
QString qyer = QString("INSERT INTO %0 (name, size, data) VALUES"
"(%1,%2, :data)").arg(DATATABLE_NAME,
song.name,
QString::number(song.size));
qyery->prepare(qyer);
qyery->bindValue(":data",song.source);
2017-11-11 20:35:30 +03:00
if(!qyery->exec())
return -1;
if(qyery->exec(QString("SELECT MAAX(id) form %0").arg(DATATABLE_NAME)))
return -1;
return qyery->value(0).toInt();
2017-11-09 23:09:59 +03:00
}
2017-11-20 00:37:12 +03:00
bool Sync::load(const SongHeader &song,Song &result){
result.clear();
if(song.id > -1){
QString qyer = QString("SELECT * from %0 where id=%1").arg(DATATABLE_NAME).arg(song.id);
if(!qyery->exec(qyer)){
return false;
}
}else if(!song.name.isEmpty() && song.size > 0){
QString qyer = QString("SELECT * from %0 where name=%1 and size=%2").arg(DATATABLE_NAME).arg(song.name).arg(song.size);
if(!qyery->exec(qyer)){
return false;
}
}else {
return false;
}
result.id = qyery->value(0).toInt();
result.name = qyery->value(1).toString();
result.size = qyery->value(2).toInt();
result.source = qyery->value(3).toByteArray();
return true;
}
2017-11-12 13:26:37 +03:00
/*
* information about chrono
* https://stackoverflow.com/questions/31255486/c-how-do-i-convert-a-stdchronotime-point-to-long-and-back
*/
2017-11-20 00:37:12 +03:00
milliseconds Sync::now(){
2017-11-12 13:26:37 +03:00
auto tim = std::chrono::system_clock::now();
2017-11-20 00:37:12 +03:00
auto mc = std::chrono::time_point_cast<std::chrono::milliseconds>(tim);
2017-11-12 13:26:37 +03:00
auto epoh = mc.time_since_epoch();
#ifdef QT_DEBUG
qDebug() << epoh.count();
#endif
return epoh.count();
}
2017-11-20 00:37:12 +03:00
Clock Sync::from(const milliseconds& mc){
std::chrono::milliseconds dur(mc);
2017-11-12 13:26:37 +03:00
return Clock(dur);
}
2017-11-20 00:37:12 +03:00
bool Sync::Play(SongHeader &header, Syncer *syncdata){
QString qyer = QString("SELECT * from %0 where name=%1 and size=%2").arg(DATATABLE_NAME).arg(header.name).arg(header.size);
if(!qyery->exec(qyer)){
return false;
}
Song song;
song.id = qyery->value(0).toInt();
song.name = qyery->value(1).toString();
song.size = qyery->value(2).toInt();
song.source = qyery->value(3).toByteArray();
return Sync::Play(song,syncdata);
}
2017-11-12 13:26:37 +03:00
bool Sync::Play(Song& song, Syncer *syncdata){
2017-11-11 14:03:14 +03:00
QBuffer buffer(&song.source);
player->setMedia(QMediaContent(), &buffer);
2017-11-20 00:37:12 +03:00
if(syncdata && !sync(*syncdata)){
return false;
2017-11-11 20:35:30 +03:00
}
2017-11-20 00:37:12 +03:00
fbroadcaster = !bool(syncdata);
2017-11-11 14:03:14 +03:00
player->play();
2017-11-20 00:37:12 +03:00
playList->push_front(static_cast<SongHeader>(song));
2017-11-11 20:35:30 +03:00
return true;
}
2017-11-20 00:37:12 +03:00
bool Sync::Play(int id_song, Syncer *syncdata){
2017-11-11 20:35:30 +03:00
QString qyer = QString("SELECT * from %0 where id=%1").arg(DATATABLE_NAME).arg(id_song);
if(!qyery->exec(qyer)){
return false;
}
Song song;
song.id = qyery->value(0).toInt();
song.name = qyery->value(1).toString();
song.size = qyery->value(2).toInt();
song.source = qyery->value(3).toByteArray();
2017-11-20 00:37:12 +03:00
return Sync::Play(song,syncdata);
2017-11-11 20:35:30 +03:00
}
bool Sync::Play(QString url){
QFile f(url);
if(!f.open(QIODevice::ReadOnly)){
return false;
}
QByteArray bytes = f.readAll();
f.close();
QString name = url.right(url.lastIndexOf(QRegularExpression("[\\/]"))); // meby [[\\\/]]
Song song;
song.name = name;
song.size = bytes.size();
song.source = bytes;
song.id = Sync::save(song);
if(song.id < 0)
return false;
return Sync::Play(song);
}
void Sync::Pause(){
player->pause();
}
void Sync::stop(){
player->stop();
}
void Sync::jump(const int seek){
player->setPosition(seek);
2017-11-11 14:03:14 +03:00
}
2017-11-20 00:37:12 +03:00
bool Sync::sync(const Syncer &sync){
milliseconds sync_time = sync.run - now();
if(sync_time > MAX_SYNC_TIME && sync_time <= 0)
return false;
Clock run_time = from(sync.run);
do {
std::this_thread::yield();
} while (std::chrono::high_resolution_clock::now() < run_time);
player->setPosition(sync.seek);
return true;
}
bool Sync::createPackage(TypePackage type, package &pac){
pac.clear();
if(type & TypePackage::t_close){
pac.type = type;
}else if(type & TypePackage::t_sync){
if(!fbroadcaster)
return false;
pac.type = type;
pac.playdata.run = now() + SYNC_TIME;
pac.playdata.seek = player->position() + SYNC_TIME;
}else if(type & TypePackage::t_song_h){
if(!fbroadcaster || playList->isEmpty())
return false;
pac.type = type;
pac.header = playList->front();
}else if(type & TypePackage::t_song){
if(!fbroadcaster || playList->isEmpty())
return false;
pac.type = type;
if(!load(playList->front(), pac.source))
return false;
}else if(type & TypePackage::t_stop){
pac.type = type;
}else{
return false;
}
return pac.isValid();
}
2017-11-09 23:09:59 +03:00
Sync::~Sync(){
delete node;
delete db;
delete player;
2017-10-29 14:47:36 +03:00
}
2017-11-09 23:09:59 +03:00
}
2017-11-20 00:37:12 +03:00