mirror of
https://github.com/QuasarApp/SoundBand.git
synced 2025-04-26 07:14:31 +00:00
Merge pull request #62 from QuasarApp/default_qtPlayList
create song storage class
This commit is contained in:
commit
03bbae91fa
@ -10,7 +10,7 @@ Item {
|
||||
|
||||
property int currentSongId: 0
|
||||
property string currentSongName: qsTr("Song is not selected")
|
||||
property bool playState: false
|
||||
property bool playState: syncEngine.playState === 1;
|
||||
|
||||
|
||||
function changeSong(id, name){
|
||||
@ -84,7 +84,6 @@ Item {
|
||||
|
||||
onClicked: {
|
||||
syncEngine.pause(playState);
|
||||
playState = !playState;
|
||||
}
|
||||
|
||||
}
|
||||
@ -123,7 +122,7 @@ Item {
|
||||
anchors.right: parent.right;
|
||||
anchors.rightMargin: Utils.dp(Screen.pixelDensity, 5)
|
||||
onClicked: {
|
||||
state = ++state % 4;
|
||||
state = ++state % 5;
|
||||
syncEngine.setRepeat(state)
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,8 @@ SOURCES += main.cpp \
|
||||
playlistmodel.cpp \
|
||||
serverlistmodel.cpp \
|
||||
playlistsmodel.cpp \
|
||||
currentplaylistmodel.cpp
|
||||
currentplaylistmodel.cpp \
|
||||
../sync/playlist.cpp
|
||||
|
||||
|
||||
RESOURCES += qml.qrc
|
||||
@ -69,5 +70,6 @@ HEADERS += \
|
||||
playlistmodel.h \
|
||||
serverlistmodel.h \
|
||||
playlistsmodel.h \
|
||||
currentplaylistmodel.h
|
||||
currentplaylistmodel.h \
|
||||
../sync/playlist.h
|
||||
|
||||
|
@ -17,7 +17,7 @@ class CurrentPlayListModel : public QAbstractListModel
|
||||
|
||||
private:
|
||||
SyncEngine * syncEngine;
|
||||
const QList<syncLib::SongHeader> *playList;
|
||||
const QList<syncLib::SongStorage> *playList;
|
||||
int itemCount;
|
||||
|
||||
private slots:
|
||||
|
@ -94,7 +94,7 @@ QVariant PlayListModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
bool PlayListModel::select(int id){
|
||||
|
||||
for(QList<syncLib::SongHeader>::Iterator i = playList.begin(); i < playList.end(); i++){
|
||||
for(QList<syncLib::SongStorage>::Iterator i = playList.begin(); i < playList.end(); i++){
|
||||
if(i->id == id){
|
||||
|
||||
if((i->isSelected = !i->isSelected)){
|
||||
@ -114,7 +114,7 @@ bool PlayListModel::select(int id){
|
||||
QList<int> PlayListModel::getSelected(){
|
||||
QList<int> result;
|
||||
|
||||
for(QList<syncLib::SongHeader>::Iterator i = playList.begin(); i < playList.end(); i++){
|
||||
for(QList<syncLib::SongStorage>::Iterator i = playList.begin(); i < playList.end(); i++){
|
||||
if(i->isSelected){
|
||||
result.push_back(i->id);
|
||||
}
|
||||
@ -124,7 +124,7 @@ QList<int> PlayListModel::getSelected(){
|
||||
|
||||
bool PlayListModel::isSelected(int id){
|
||||
|
||||
for(QList<syncLib::SongHeader>::Iterator i = playList.begin(); i < playList.end(); i++){
|
||||
for(QList<syncLib::SongStorage>::Iterator i = playList.begin(); i < playList.end(); i++){
|
||||
if(i->id == id){
|
||||
return i->isSelected;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ class PlayListModel : public QAbstractListModel
|
||||
|
||||
private:
|
||||
SyncEngine * syncEngine;
|
||||
QList<syncLib::SongHeader> playList;
|
||||
QList<syncLib::SongStorage> playList;
|
||||
QString playListName;
|
||||
int itemCount;
|
||||
|
||||
|
@ -8,9 +8,11 @@ SyncEngine::SyncEngine()
|
||||
sqlApi = sync->getSqlApi();
|
||||
|
||||
connect(sync, SIGNAL(networkStateChange()), this, SIGNAL(serversCountChanged()));
|
||||
connect(sync, SIGNAL(currentPlayListChanged()), this, SIGNAL(currentPlayListNameChanged()));
|
||||
connect(sync, SIGNAL(currentPlayListChanged()), this, SIGNAL(currentPlayListCountChanged()));
|
||||
connect(sync, SIGNAL(seekChanged(qint64)), this, SLOT(seekChanged(qint64)));
|
||||
connect(sync, SIGNAL(currentSongChanged()), this, SIGNAL(currentSongChanged()));
|
||||
connect(sync, SIGNAL(playStateChanged()), this, SIGNAL(playStateChanged()));
|
||||
|
||||
}
|
||||
|
||||
@ -42,7 +44,7 @@ bool SyncEngine::init(){
|
||||
return true;
|
||||
}
|
||||
|
||||
const QList<syncLib::SongHeader>* SyncEngine::currentPlayList() const{
|
||||
const QList<syncLib::SongStorage>* SyncEngine::currentPlayList() const{
|
||||
|
||||
return sync->getPlayList();
|
||||
}
|
||||
@ -140,7 +142,7 @@ int SyncEngine::repeat()const{
|
||||
}
|
||||
|
||||
void SyncEngine::setRepeat(int flag){
|
||||
sync->setRepeat((syncLib::Repeat)flag);
|
||||
sync->setRepeat((QMediaPlaylist::PlaybackMode)flag);
|
||||
}
|
||||
|
||||
bool SyncEngine::setPlayList(const QString& name){
|
||||
@ -157,7 +159,7 @@ bool SyncEngine::setPlayList(const QString& name){
|
||||
|
||||
}
|
||||
|
||||
bool SyncEngine::getPlayList(QList<syncLib::SongHeader> &playList, const QString &name){
|
||||
bool SyncEngine::getPlayList(QList<SongStorage> &playList, const QString &name){
|
||||
return sqlApi->updateAvailableSongs(playList, name, true);
|
||||
}
|
||||
|
||||
@ -251,6 +253,10 @@ bool SyncEngine::removeFromPlayList(int id, const QString &playList){
|
||||
|
||||
}
|
||||
|
||||
int SyncEngine::playState()const{
|
||||
return sync->playState();
|
||||
}
|
||||
|
||||
SyncEngine::~SyncEngine(){
|
||||
disconnect(sync, SIGNAL(networkStateChange()), this, SIGNAL(serversCountChanged()));
|
||||
delete sync;
|
||||
|
@ -16,6 +16,7 @@ class SyncEngine : public QObject
|
||||
Q_PROPERTY(double pos READ pos WRITE setPos NOTIFY posChanged)
|
||||
Q_PROPERTY(int repeat READ repeat WRITE setRepeat NOTIFY repeatChanged)
|
||||
Q_PROPERTY(QString currentPlayListName READ currentPlayListName NOTIFY currentPlayListNameChanged)
|
||||
Q_PROPERTY(int playState READ playState NOTIFY playStateChanged)
|
||||
|
||||
|
||||
private:
|
||||
@ -74,7 +75,7 @@ public slots:
|
||||
* @brief currentPlayList
|
||||
* @return return current Play List
|
||||
*/
|
||||
const QList<syncLib::SongHeader> *currentPlayList() const;
|
||||
const QList<SongStorage> *currentPlayList() const;
|
||||
|
||||
/**
|
||||
* @brief currentPlayListName
|
||||
@ -138,7 +139,7 @@ public slots:
|
||||
* @param name - name of selected playList
|
||||
* @return
|
||||
*/
|
||||
bool getPlayList(QList<syncLib::SongHeader> &playList, const QString& name);
|
||||
bool getPlayList(QList<SongStorage> &playList, const QString& name);
|
||||
|
||||
/**
|
||||
* @brief lastError - message of last error
|
||||
@ -222,6 +223,17 @@ public slots:
|
||||
*/
|
||||
bool removeFromPlayList(int id, const QString& playList);
|
||||
|
||||
/**
|
||||
* @brief playState
|
||||
* @return playState current song ( )
|
||||
* @value 0 is no repeat
|
||||
* @value 1 is single repeat
|
||||
* @value 2 is single playlist
|
||||
* @value 3 is repeat playlist
|
||||
* @value 4 is random play
|
||||
*/
|
||||
int playState()const;
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
@ -278,6 +290,12 @@ signals:
|
||||
*/
|
||||
void currentPlayListNameChanged();
|
||||
|
||||
/**
|
||||
* @brief playStateChanged
|
||||
* emited when state of playing song changed
|
||||
*/
|
||||
void playStateChanged();
|
||||
|
||||
};
|
||||
|
||||
#endif // SYNCENGINE_H
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
// general otions
|
||||
#define CURRENT_PLAYLIST_KEY "currentPlayList"
|
||||
#define MAIN_FOLDER_KEY "songsfolder"
|
||||
#define MAIN_FOLDER "soundBand"
|
||||
|
||||
|
||||
// LIB VERSION
|
||||
#define MAJOR_VERSION 0
|
||||
|
181
sync/mysql.cpp
181
sync/mysql.cpp
@ -2,6 +2,8 @@
|
||||
#include <QSqlQuery>
|
||||
#include <QtSql>
|
||||
#include "exaptions.h"
|
||||
#include <QSettings>
|
||||
#include "playlist.h"
|
||||
|
||||
namespace syncLib{
|
||||
|
||||
@ -44,6 +46,8 @@ bool MySql::exec(QSqlQuery *sq,const QString& sqlFile){
|
||||
void MySql::initDB(const QString &database){
|
||||
if(db) return;
|
||||
dataBaseName = database;
|
||||
QSettings settings;
|
||||
songDir = settings.value(MAIN_FOLDER_KEY, QDir::homePath() + "/soundBand").toString();
|
||||
db = new QSqlDatabase();
|
||||
*db = QSqlDatabase::addDatabase("QSQLITE", database);
|
||||
QDir d(QString("./%0").arg(dataBaseName));
|
||||
@ -51,23 +55,11 @@ void MySql::initDB(const QString &database){
|
||||
if(db->open()){
|
||||
qyery = new QSqlQuery(*db);
|
||||
|
||||
// /*
|
||||
// *https://stackoverflow.com/questions/40863216/sqlite-why-is-foreign-key-constraint-not-working-here
|
||||
// */
|
||||
|
||||
// QString qyer = QString("PRAGMA foreign_keys = ON");
|
||||
// if(!qyery->exec(qyer)){
|
||||
// sqlErrorLog(qyer);
|
||||
// throw InitDBError();
|
||||
// delete db;
|
||||
// return;
|
||||
// }
|
||||
|
||||
QString qyer = QString("CREATE TABLE IF NOT EXISTS songs("
|
||||
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"name VARCHAR(100), "
|
||||
"size INT NOT NULL, "
|
||||
"data BLOB NOT NULL "
|
||||
"data TEXT NOT NULL "
|
||||
")");
|
||||
if(!qyery->exec(qyer)){
|
||||
sqlErrorLog(qyer);
|
||||
@ -127,15 +119,95 @@ void MySql::initDB(const QString &database){
|
||||
}
|
||||
}
|
||||
|
||||
bool MySql::find(const QMediaContent &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;
|
||||
|
||||
if(!updateAvailableSongs(songs)){
|
||||
return false;
|
||||
}
|
||||
|
||||
for(SongStorage &i: songs){
|
||||
if((SongHeader&)i == song){
|
||||
response = i.toMedia();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MySql::setSoundDir(const QString &str){
|
||||
songDir = str;
|
||||
QSettings().setValue(MAIN_FOLDER_KEY, songDir);
|
||||
}
|
||||
|
||||
bool MySql::saveToStorage(QUrl &url, const Song &song) const{
|
||||
if(!song.isValid()){
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile file(songDir + "/" + song.name);
|
||||
|
||||
if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
|
||||
return false;
|
||||
}
|
||||
|
||||
file.write(song.source.data(), song.source.length());
|
||||
file.close();
|
||||
|
||||
url = QUrl::fromLocalFile(songDir + "/" + song.name);
|
||||
|
||||
return url.isValid();
|
||||
|
||||
}
|
||||
|
||||
void MySql::sqlErrorLog(const QString &qyery)const{
|
||||
#ifdef QT_DEBUG
|
||||
qDebug()<< qyery << ": fail:\n " <<this->qyery->lastError();
|
||||
#endif
|
||||
}
|
||||
|
||||
int MySql::save(const Song &song){
|
||||
QString qyer = QString("SELECT id from songs where name='%0' and size=%1").arg(song.name,
|
||||
QString::number(song.size));
|
||||
int MySql::save(const SongStorage &song){
|
||||
|
||||
QString qyer = QString("SELECT id from songs where name='%0' and size=%1").
|
||||
arg(song.name, QString::number(song.size));
|
||||
|
||||
if(!qyery->exec(qyer)){
|
||||
sqlErrorLog(qyer);
|
||||
return -1;
|
||||
@ -145,16 +217,12 @@ int MySql::save(const Song &song){
|
||||
return qyery->value(0).toInt();
|
||||
}
|
||||
|
||||
qyer = QString("INSERT INTO songs (name,size,data) VALUES"
|
||||
"('%0',%1,:val)").arg(song.name,
|
||||
QString::number(song.size));
|
||||
if(!qyery->prepare(qyer)){
|
||||
sqlErrorLog(qyer + " prepare error");
|
||||
return -1;
|
||||
}
|
||||
qyer = QString("INSERT INTO songs (name,size,data) VALUES "
|
||||
"('%0',%1,'%2')").arg(song.name,
|
||||
QString::number(song.size),
|
||||
song.url.path());
|
||||
|
||||
qyery->bindValue(":val",song.source);
|
||||
if(!qyery->exec()){
|
||||
if(!qyery->exec(qyer)){
|
||||
sqlErrorLog(qyer);
|
||||
return -1;
|
||||
}
|
||||
@ -169,18 +237,28 @@ int MySql::save(const Song &song){
|
||||
return result;
|
||||
}
|
||||
|
||||
int MySql::save(const QString &url){
|
||||
QFile f(QUrl(url).toLocalFile());
|
||||
if(!f.open(QIODevice::ReadOnly)){
|
||||
int MySql::save(const Song &song){
|
||||
|
||||
|
||||
QUrl url;
|
||||
if(!saveToStorage(url, song)){
|
||||
return false;
|
||||
}
|
||||
|
||||
return save(SongStorage(url));
|
||||
|
||||
|
||||
}
|
||||
|
||||
int MySql::save(const QString &url){
|
||||
|
||||
QUrl qurl = QUrl(url);
|
||||
|
||||
if(!qurl.isValid()){
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
|
||||
SongStorage song(qurl);
|
||||
|
||||
if(!song.isNameValid()){
|
||||
return -1;
|
||||
@ -190,8 +268,7 @@ int MySql::save(const QString &url){
|
||||
|
||||
}
|
||||
|
||||
bool MySql::load(const SongHeader &song,Song &result){
|
||||
result.clear();
|
||||
bool MySql::load(const SongHeader &song, SongStorage &result){
|
||||
if(song.id > -1){
|
||||
QString qyer = QString("SELECT * from songs where id=%0").arg(song.id);
|
||||
if(!qyery->exec(qyer)){
|
||||
@ -213,17 +290,17 @@ bool MySql::load(const SongHeader &song,Song &result){
|
||||
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;
|
||||
result.url = QUrl::fromLocalFile(qyery->value(3).toString());
|
||||
return result.isValid();
|
||||
}
|
||||
|
||||
bool MySql::updateAvailableSongs(QList<SongHeader>& list, const QString& playList, bool forEditing){
|
||||
bool MySql::updateAvailableSongs(QList<SongStorage>& list, const QString& playList, bool forEditing){
|
||||
QString qyer;
|
||||
|
||||
if(playList.isEmpty() || playList == ALL_SONGS_LIST || forEditing){
|
||||
qyer = QString("SELECT id,name,size from songs");
|
||||
qyer = QString("SELECT * from songs");
|
||||
}else{
|
||||
qyer = QString("SELECT id,name,size from songs where "
|
||||
qyer = QString("SELECT * from songs where "
|
||||
"id in (select song from playlistsdata where "
|
||||
"playlist='%0')").arg(playList);
|
||||
}
|
||||
@ -236,11 +313,13 @@ bool MySql::updateAvailableSongs(QList<SongHeader>& list, const QString& playLis
|
||||
list.clear();
|
||||
|
||||
while(qyery->next()){
|
||||
SongHeader song;
|
||||
SongStorage song;
|
||||
song.isSelected = !forEditing || playList == ALL_SONGS_LIST;
|
||||
song.id = qyery->value(0).toInt();
|
||||
song.name = qyery->value(1).toString();
|
||||
song.size = qyery->value(2).toInt();
|
||||
song.url = QUrl::fromLocalFile(qyery->value(3).toString());
|
||||
|
||||
list.push_back(song);
|
||||
}
|
||||
|
||||
@ -255,7 +334,7 @@ bool MySql::updateAvailableSongs(QList<SongHeader>& list, const QString& playLis
|
||||
}
|
||||
|
||||
while(qyery->next()){
|
||||
for(SongHeader& item:list){
|
||||
for(SongStorage& item:list){
|
||||
int id = qyery->value(0).toInt();
|
||||
if(item.id == id){
|
||||
item.isSelected = true;
|
||||
@ -265,19 +344,21 @@ bool MySql::updateAvailableSongs(QList<SongHeader>& list, const QString& playLis
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySql::updateAvailableSongs(QStringList& list, const QString& playList){
|
||||
bool MySql::updateAvailableSongs(PlayList& list, const QString& playList, bool forEditing){
|
||||
|
||||
QList<SongHeader> tempList;
|
||||
QList<SongStorage> tempList;
|
||||
list.clear();
|
||||
|
||||
if(!updateAvailableSongs(tempList, playList))
|
||||
if(!updateAvailableSongs(tempList, playList, forEditing))
|
||||
return false;
|
||||
|
||||
for(SongHeader &header : tempList){
|
||||
list.push_back(header.name);
|
||||
for(SongStorage &header : tempList){
|
||||
if(!list.addMedia(header)){
|
||||
this->removeSong(header);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
60
sync/mysql.h
60
sync/mysql.h
@ -1,7 +1,7 @@
|
||||
#ifndef MYSQL_H
|
||||
#define MYSQL_H
|
||||
#include <QString>
|
||||
#include "song.h"
|
||||
#include "playlist.h"
|
||||
|
||||
class QSqlDatabase;
|
||||
class QSqlQuery;
|
||||
@ -14,6 +14,7 @@ private:
|
||||
QSqlDatabase *db;
|
||||
QSqlQuery *qyery;
|
||||
QString dataBaseName;
|
||||
QString songDir;
|
||||
|
||||
/**
|
||||
* @brief sqlErrorLog show sql error
|
||||
@ -21,6 +22,14 @@ private:
|
||||
*/
|
||||
void sqlErrorLog(const QString& qyery) const;
|
||||
|
||||
/**
|
||||
* @brief saveToStorage save song as file into hdd
|
||||
* @param url - url of song after save
|
||||
* @param song - saved song
|
||||
* @return true if all done
|
||||
*/
|
||||
bool saveToStorage(QUrl& url, const Song& song)const;
|
||||
|
||||
public:
|
||||
MySql(const QString& databasename);
|
||||
/**
|
||||
@ -28,13 +37,56 @@ public:
|
||||
*/
|
||||
void initDB(const QString& database = DATABASE_NAME );
|
||||
|
||||
/**
|
||||
* @brief find - find song
|
||||
* @param song - song header
|
||||
* @param response Media Content of finded song
|
||||
* @return true if song finded
|
||||
*/
|
||||
bool find(const SongHeader& song, QMediaContent& 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
|
||||
* @param str
|
||||
*/
|
||||
void setSoundDir(const QString& str);
|
||||
|
||||
/**
|
||||
* @brief findSong
|
||||
* @param song
|
||||
*/
|
||||
bool findSong(const SongHeader &song);
|
||||
|
||||
/**
|
||||
* @brief load song of database;
|
||||
* @brief song -
|
||||
* @brief result - the resulting value;
|
||||
* @return true if everything's done
|
||||
*/
|
||||
bool load(const SongHeader &song, Song &result);
|
||||
bool load(const SongHeader &song, SongStorage &result);
|
||||
|
||||
/**
|
||||
* @brief save media data into local database.
|
||||
* @param song savining media data.
|
||||
* @return id of song saved on local database.
|
||||
*/
|
||||
int save(const SongStorage &song);
|
||||
|
||||
/**
|
||||
* @brief save media data into local database.
|
||||
@ -62,7 +114,7 @@ public:
|
||||
* @param forEdit - flag for editing play list. If this flag = true then return all available songs with corect flag 'isSelect'
|
||||
* @return true if all done
|
||||
*/
|
||||
bool updateAvailableSongs(QList<SongHeader>& list, const QString &playList = "", bool forEditing = false);
|
||||
bool updateAvailableSongs(QList<SongStorage>& list, const QString &playList = "", bool forEditing = false);
|
||||
|
||||
/**
|
||||
* @brief updateAvelableSongs will update the list of participants of songs.
|
||||
@ -70,7 +122,7 @@ public:
|
||||
* @param playList - play list of songs (string).
|
||||
* @return true if all done
|
||||
*/
|
||||
bool updateAvailableSongs(QStringList& list, const QString &playList = "");
|
||||
bool updateAvailableSongs(PlayList& list, const QString &playList = "", bool forEditing = false);
|
||||
|
||||
/**
|
||||
* @brief removeSong - remove song from local database.
|
||||
|
@ -12,24 +12,6 @@ Player::Player(const QString &bufferFile, QObject *parent, Flags flags):
|
||||
bufferVolume = 0;
|
||||
}
|
||||
|
||||
bool Player::setMediaFromBytes(const QByteArray &array){
|
||||
QFile f(buffer);
|
||||
if(!f.open(QIODevice::WriteOnly | QIODevice::Truncate)){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(array.length() != f.write(array.data(),array.length())){
|
||||
|
||||
f.close();
|
||||
return false;
|
||||
}
|
||||
f.close();
|
||||
|
||||
setMedia(QUrl::fromLocalFile(QDir("./").absoluteFilePath(buffer)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Player::syncBegin(){
|
||||
|
||||
bufferVolume = volume();
|
||||
|
@ -21,13 +21,6 @@ public:
|
||||
|
||||
Player(const QString& bufferFile, QObject *parent = Q_NULLPTR, Flags flags = Flags());
|
||||
|
||||
/**
|
||||
* @brief setMediaFromBytes
|
||||
* @param array of song data
|
||||
* @return true if all done
|
||||
*/
|
||||
bool setMediaFromBytes(const QByteArray& array);
|
||||
|
||||
/**
|
||||
* @brief syncBegin - palyer waiting for sunced.
|
||||
*/
|
||||
|
93
sync/playlist.cpp
Normal file
93
sync/playlist.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include "playlist.h"
|
||||
|
||||
PlayList::PlayList()
|
||||
{
|
||||
playListInfo.clear();
|
||||
playList = new QMediaPlaylist();
|
||||
}
|
||||
|
||||
QList<SongStorage>* PlayList::getInfo(){
|
||||
return &playListInfo;
|
||||
}
|
||||
|
||||
QMediaPlaylist* PlayList::getList(){
|
||||
return playList;
|
||||
}
|
||||
|
||||
void PlayList::clear(){
|
||||
playList->clear();
|
||||
playListInfo.clear();
|
||||
}
|
||||
|
||||
bool PlayList::addMedia(const SongStorage &song){
|
||||
if(!song.isValid())
|
||||
return false;
|
||||
|
||||
if(!playList->addMedia(song.toMedia()))
|
||||
return false;
|
||||
|
||||
playListInfo.push_back(song);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayList::next()const{
|
||||
playList->next();
|
||||
}
|
||||
|
||||
void PlayList::prev()const{
|
||||
playList->previous();
|
||||
}
|
||||
|
||||
bool PlayList::isValid()const{
|
||||
return playListInfo.size() == playList->mediaCount();
|
||||
}
|
||||
|
||||
bool PlayList::isEmpty()const{
|
||||
return playList->isEmpty() && playListInfo.isEmpty();
|
||||
}
|
||||
|
||||
const SongHeader *PlayList::currentHeader()const{
|
||||
if(playList->isEmpty() || playList->currentIndex() < 0)
|
||||
return nullptr;
|
||||
|
||||
return static_cast<const SongHeader*>(&playListInfo[playList->currentIndex()]);
|
||||
}
|
||||
|
||||
const SongStorage *PlayList::currentSong()const{
|
||||
if(playList->isEmpty() || playList->currentIndex() < 0)
|
||||
return nullptr;
|
||||
|
||||
return &playListInfo[playList->currentIndex()];
|
||||
}
|
||||
|
||||
int PlayList::size()const{
|
||||
return playList->mediaCount();
|
||||
}
|
||||
|
||||
int PlayList::find(const SongHeader &header)const{
|
||||
for(int i = 0; i < playList->mediaCount(); ++i) {
|
||||
if(header == playList->media(i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool PlayList::selectSong(int index){
|
||||
if(playList->mediaCount() <= index || index < 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
playList->setCurrentIndex(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PlayList::selectSong(const SongHeader &header){
|
||||
return selectSong(find(header));
|
||||
}
|
||||
|
||||
|
||||
|
||||
PlayList::~PlayList(){
|
||||
delete playList;
|
||||
}
|
113
sync/playlist.h
Normal file
113
sync/playlist.h
Normal file
@ -0,0 +1,113 @@
|
||||
#ifndef PLAYLIST_H
|
||||
#define PLAYLIST_H
|
||||
#include <QMediaPlaylist>
|
||||
#include "song.h"
|
||||
|
||||
using namespace syncLib;
|
||||
|
||||
/**
|
||||
* @brief The PlayList class
|
||||
* palyList with songs info
|
||||
*/
|
||||
class PlayList
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* @brief playList media play list
|
||||
*/
|
||||
QMediaPlaylist *playList;
|
||||
|
||||
/**
|
||||
* @brief playListInfo - info from databas
|
||||
*/
|
||||
QList<SongStorage> playListInfo;
|
||||
public:
|
||||
PlayList();
|
||||
|
||||
/**
|
||||
* @brief getInfo
|
||||
* @return info from database about songs
|
||||
*/
|
||||
QList<SongStorage>* getInfo();
|
||||
|
||||
/**
|
||||
* @brief clear this play list
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* @brief addMedia media content into playList
|
||||
* @param song - media content
|
||||
* @return true if all done
|
||||
*/
|
||||
bool addMedia(const SongStorage& song);
|
||||
|
||||
/**
|
||||
* @brief next
|
||||
*/
|
||||
void next()const;
|
||||
|
||||
/**
|
||||
* @brief prev
|
||||
*/
|
||||
void prev()const;
|
||||
|
||||
/**
|
||||
* @brief isValid
|
||||
* @return true if this object valid
|
||||
*/
|
||||
bool isValid()const;
|
||||
|
||||
/**
|
||||
* @brief isEmpty
|
||||
* @return true if playlist empty
|
||||
*/
|
||||
bool isEmpty()const;
|
||||
|
||||
/**
|
||||
* @brief getlist
|
||||
* @return return pointer to media content
|
||||
*/
|
||||
QMediaPlaylist* getList();
|
||||
|
||||
/**
|
||||
* @brief currentHeader
|
||||
* @return header of curent song
|
||||
*/
|
||||
const SongHeader* currentHeader()const;
|
||||
|
||||
/**
|
||||
* @brief currentStorage
|
||||
* @return header of curent song
|
||||
*/
|
||||
const SongStorage* currentSong()const;
|
||||
|
||||
/**
|
||||
* @brief size
|
||||
* @return count of media items of playlist
|
||||
*/
|
||||
int size()const;
|
||||
|
||||
/**
|
||||
* @brief find
|
||||
* @return index of finded media
|
||||
*/
|
||||
int find(const SongHeader& header)const;
|
||||
|
||||
/**
|
||||
* @brief selectSong
|
||||
* @return true if song selected
|
||||
*/
|
||||
bool selectSong(int index);
|
||||
|
||||
/**
|
||||
* @brief selectSong
|
||||
* @param header of selecting song
|
||||
* @return if song selected return true;
|
||||
*/
|
||||
bool selectSong(const SongHeader& header);
|
||||
|
||||
~PlayList();
|
||||
};
|
||||
|
||||
#endif // PLAYLIST_H
|
159
sync/song.cpp
159
sync/song.cpp
@ -1,5 +1,8 @@
|
||||
#include "song.h"
|
||||
#include <QStringList>
|
||||
#include <QRegularExpression>
|
||||
#include <QFile>
|
||||
|
||||
namespace syncLib{
|
||||
|
||||
static const QStringList ValidSongs = {".mp3", ".wav", ".ogg"};
|
||||
@ -11,6 +14,31 @@ SongHeader::SongHeader()
|
||||
this->size = 0;
|
||||
}
|
||||
|
||||
bool SongHeader::getName(QString & name, const QUrl &url) const {
|
||||
if(url.isLocalFile() && url.isValid()){
|
||||
name = url.fileName();
|
||||
name = name.right(name.lastIndexOf(QRegularExpression("[\\\/]")));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
bool SongHeader::getSize(int & size, const QUrl &url) const {
|
||||
if(url.isLocalFile() && url.isValid()){
|
||||
QFile f(url.toLocalFile());
|
||||
if(!f.exists()){
|
||||
return false;
|
||||
}
|
||||
size = f.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
SongHeader& SongHeader::operator =(const SongHeader& right){
|
||||
this->id = right.id;
|
||||
this->name = right.name;
|
||||
@ -18,15 +46,35 @@ SongHeader& SongHeader::operator =(const SongHeader& right){
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool SongHeader::operator ==(const SongHeader& right){
|
||||
SongHeader& SongHeader::operator =(const QMediaContent& right){
|
||||
this->id = -1;
|
||||
if(!getName(name, right.canonicalUrl())){
|
||||
name.clear();
|
||||
}
|
||||
|
||||
if(!getSize(this->size, right.canonicalUrl())){
|
||||
this->size = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool SongHeader::operator ==(const SongHeader& right)const{
|
||||
return this->name == right.name && this->size == right.size;
|
||||
}
|
||||
|
||||
unsigned int SongHeader::getSize() const{
|
||||
QByteArray size;
|
||||
QDataStream stream(size);
|
||||
stream << id << name << this->size;
|
||||
return size.size();
|
||||
bool SongHeader::operator ==(const QMediaContent& right)const{
|
||||
QString name;
|
||||
if(!getName(name, right.canonicalUrl())){
|
||||
return false;
|
||||
}
|
||||
|
||||
int size;;
|
||||
if(!getSize(size, right.canonicalUrl())){
|
||||
return false;
|
||||
}
|
||||
|
||||
return this->name == name && this->size == size;
|
||||
}
|
||||
|
||||
bool SongHeader::isNameValid() const{
|
||||
@ -45,14 +93,6 @@ bool SongHeader::isValid() const{
|
||||
|
||||
SongHeader::~SongHeader(){}
|
||||
|
||||
|
||||
|
||||
Song::Song():
|
||||
SongHeader()
|
||||
{
|
||||
source.clear();
|
||||
}
|
||||
|
||||
QDataStream& operator << (QDataStream& stream, const SongHeader& song){
|
||||
stream << song.id;
|
||||
stream << song.name;
|
||||
@ -66,6 +106,93 @@ QDataStream& operator >> (QDataStream& stream, SongHeader& song){
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
SongStorage::SongStorage():
|
||||
SongHeader()
|
||||
{
|
||||
url.clear();
|
||||
}
|
||||
|
||||
SongStorage::SongStorage(const SongHeader& from)
|
||||
:SongStorage::SongStorage()
|
||||
{
|
||||
this->id = from.id;
|
||||
this->name = from.name;
|
||||
this->size = from.size;
|
||||
}
|
||||
|
||||
SongStorage::SongStorage(const QUrl& from)
|
||||
:SongStorage::SongStorage()
|
||||
{
|
||||
if(!from.isValid() || !from.isLocalFile()){
|
||||
return;
|
||||
}
|
||||
|
||||
QFile f(from.toLocalFile());
|
||||
this->size = f.size();
|
||||
f.close();
|
||||
|
||||
this->id = -1;
|
||||
url = from;
|
||||
if(!getName(name, from)){
|
||||
name.clear();
|
||||
}
|
||||
}
|
||||
|
||||
SongStorage::SongStorage(const QMediaContent& from)
|
||||
:SongStorage::SongStorage(from.canonicalUrl())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const QUrl& SongStorage::getSource()const{
|
||||
return url;
|
||||
}
|
||||
|
||||
bool SongStorage::isValid() const{
|
||||
return SongHeader::isValid() && url.isValid() && QFile(url.toLocalFile()).exists();
|
||||
}
|
||||
|
||||
SongStorage::~SongStorage(){
|
||||
url.clear();
|
||||
}
|
||||
|
||||
QMediaContent SongStorage::toMedia()const{
|
||||
return QMediaContent(url);
|
||||
}
|
||||
|
||||
bool SongStorage::toSong(Song&)const{
|
||||
Song song(*((SongHeader*)this));
|
||||
|
||||
QFile f(url.toLocalFile());
|
||||
|
||||
if(!f.open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
song.source = f.readAll();
|
||||
|
||||
f.close();
|
||||
return song.isValid();
|
||||
}
|
||||
|
||||
QDataStream& operator << (QDataStream& stream,const SongStorage& song){
|
||||
stream << static_cast<const SongHeader&>(song);
|
||||
stream << song.url;
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream& operator >> (QDataStream& stream, SongStorage& song){
|
||||
stream >> static_cast<SongHeader&>(song);
|
||||
stream >> song.url;
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
Song::Song():
|
||||
SongHeader()
|
||||
{
|
||||
source.clear();
|
||||
}
|
||||
|
||||
Song::Song(const SongHeader& from)
|
||||
:Song::Song()
|
||||
{
|
||||
@ -78,10 +205,6 @@ void Song::clear(){
|
||||
source.clear();
|
||||
}
|
||||
|
||||
unsigned int Song::getSize() const{
|
||||
return SongHeader::getSize() + source.size();
|
||||
}
|
||||
|
||||
const QByteArray& Song::getSource()const{
|
||||
return source;
|
||||
}
|
||||
|
39
sync/song.h
39
sync/song.h
@ -4,6 +4,7 @@
|
||||
#include <QByteArray>
|
||||
#include <QDataStream>
|
||||
#include "chronotime.h"
|
||||
#include <QMediaContent>
|
||||
|
||||
namespace syncLib {
|
||||
|
||||
@ -24,7 +25,9 @@ struct Syncer
|
||||
* (id,size and name)
|
||||
*/
|
||||
class SongHeader{
|
||||
|
||||
protected:
|
||||
bool getName(QString &name, const QUrl& url)const;
|
||||
bool getSize(int &size, const QUrl& url)const;
|
||||
public:
|
||||
bool isSelected;
|
||||
int id;
|
||||
@ -32,8 +35,10 @@ public:
|
||||
int size;
|
||||
SongHeader();
|
||||
SongHeader& operator = (const SongHeader& right);
|
||||
bool operator == (const SongHeader& right);
|
||||
virtual unsigned int getSize() const;
|
||||
SongHeader& operator = (const QMediaContent& right);
|
||||
|
||||
bool operator == (const SongHeader& right)const;
|
||||
bool operator == (const QMediaContent& right)const;
|
||||
bool isNameValid() const;
|
||||
virtual bool isValid() const;
|
||||
virtual ~SongHeader();
|
||||
@ -53,7 +58,7 @@ public:
|
||||
* @brief The Song class
|
||||
* into this calss added mediadata of playable media file.
|
||||
*/
|
||||
class Song : public SongHeader{
|
||||
class Song : public SongHeader {
|
||||
private:
|
||||
QByteArray source;
|
||||
public:
|
||||
@ -61,12 +66,36 @@ public:
|
||||
Song(const SongHeader& from);
|
||||
void clear();
|
||||
const QByteArray& getSource()const;
|
||||
unsigned int getSize() const;
|
||||
bool isValid() const;
|
||||
~Song();
|
||||
friend QDataStream& operator << (QDataStream& stream, const Song& song);
|
||||
friend QDataStream& operator >> (QDataStream& stream, Song& song);
|
||||
friend class MySql;
|
||||
friend class SongStorage;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The SongStorage class
|
||||
* header with url to song source
|
||||
*/
|
||||
class SongStorage : public SongHeader {
|
||||
private:
|
||||
QUrl url;
|
||||
public:
|
||||
SongStorage();
|
||||
SongStorage(const SongHeader& from);
|
||||
SongStorage(const QUrl& url);
|
||||
SongStorage(const QMediaContent& media);
|
||||
const QUrl& getSource()const;
|
||||
bool toSong(Song &)const;
|
||||
QMediaContent toMedia()const;
|
||||
bool isValid() const;
|
||||
~SongStorage();
|
||||
friend QDataStream& operator << (QDataStream& stream, const SongStorage& song);
|
||||
friend QDataStream& operator >> (QDataStream& stream, SongStorage& song);
|
||||
friend class MySql;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // SONG_H
|
||||
|
206
sync/sync.cpp
206
sync/sync.cpp
@ -22,11 +22,14 @@ Sync::Sync(const QString &address, int port, const QString &datadir):
|
||||
if(!player->isAvailable()){
|
||||
throw MediaException();
|
||||
}
|
||||
playList = new PlayList;
|
||||
|
||||
player->setPlaylist(playList->getList());
|
||||
|
||||
|
||||
fbroadcaster = false;
|
||||
resyncCount = 0;
|
||||
lastSyncTime = 0;
|
||||
currentSongIndex = 0;
|
||||
ping = 0;
|
||||
|
||||
sql = new MySql(datadir);
|
||||
@ -41,7 +44,15 @@ MySql* Sync::getSqlApi(){
|
||||
return sql;
|
||||
}
|
||||
|
||||
bool Sync::updateSongs(QList<SongHeader>& list, const QString& playList){
|
||||
bool Sync::setSingle(const QMediaContent& media){
|
||||
playList->clear();
|
||||
playList->addMedia(media);
|
||||
|
||||
emit currentPlayListChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sync::updateSongs(PlayList& list, const QString& playList){
|
||||
if(!sql->updateAvailableSongs(list, playList)){
|
||||
return false;
|
||||
}
|
||||
@ -59,28 +70,54 @@ const QString& Sync::getPlayListName() const{
|
||||
return lastUsedPlayList;
|
||||
}
|
||||
|
||||
bool Sync::findHeader(const Song &song){
|
||||
bool Sync::play(bool fbroadcast){
|
||||
fbroadcaster = fbroadcast;
|
||||
|
||||
for(int i = 0; i < playList.size(); i++){
|
||||
if(playList[i] == static_cast<SongHeader>(song)){
|
||||
currentSongIndex = i;
|
||||
return true;
|
||||
}
|
||||
if(fbroadcaster){
|
||||
player->play();
|
||||
sync();
|
||||
}else{
|
||||
player->syncBegin();
|
||||
}
|
||||
emit currentSongChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sync::play(const SongStorage &song, bool fbroadcast){
|
||||
|
||||
if(!song.isValid()){
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
if(playList->selectSong(song)){
|
||||
return play(fbroadcast);
|
||||
}
|
||||
|
||||
playList->clear();
|
||||
playList->addMedia(song);
|
||||
|
||||
return play(fbroadcast);
|
||||
}
|
||||
|
||||
bool Sync::play(const SongHeader &header, bool fbroadcast){
|
||||
|
||||
Song song;
|
||||
if(!header.isValid()){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(playList->selectSong(header)){
|
||||
return play(fbroadcast);
|
||||
}
|
||||
|
||||
SongStorage song;
|
||||
SongHeader newheader = header;
|
||||
newheader.id = -1;
|
||||
if(!sql->load(newheader, song)){
|
||||
return false;
|
||||
}
|
||||
|
||||
return Sync::play(song, fbroadcast);
|
||||
return play(song, fbroadcast);
|
||||
}
|
||||
|
||||
bool Sync::play(const Song &song, bool fbroadcast){
|
||||
@ -89,27 +126,27 @@ bool Sync::play(const Song &song, bool fbroadcast){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!player->setMediaFromBytes(song.getSource())){
|
||||
return false;
|
||||
}
|
||||
|
||||
fbroadcaster = fbroadcast;
|
||||
|
||||
if(!findHeader(song) && sql->save(song) > -1 &&
|
||||
updateSongs(playList) && !findHeader(song)){
|
||||
QMediaContent savedSong;
|
||||
if(!sql->find(static_cast<const SongHeader&>(song), savedSong) && sql->save(song) > -1 &&
|
||||
!sql->find((SongHeader&)song, savedSong)){
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fbroadcaster){
|
||||
player->play();
|
||||
sync();
|
||||
}else{
|
||||
player->syncBegin();
|
||||
return play(savedSong, fbroadcast);
|
||||
}
|
||||
|
||||
bool Sync::play(const QMediaContent& media, bool fbroadcast){
|
||||
|
||||
if(media.isNull()){
|
||||
return false;
|
||||
}
|
||||
|
||||
emit currentSongChanged();
|
||||
return true;
|
||||
if(!setSingle(media)){
|
||||
return false;
|
||||
}
|
||||
|
||||
return Sync::play(fbroadcast);
|
||||
}
|
||||
|
||||
bool Sync::play(int id_song, bool fbroadcast){
|
||||
@ -119,9 +156,12 @@ bool Sync::play(int id_song, bool fbroadcast){
|
||||
}
|
||||
|
||||
SongHeader header;
|
||||
SongStorage song;
|
||||
header.id = id_song;
|
||||
Song song;
|
||||
sql->load(header, song);
|
||||
|
||||
if(!sql->load(header, song)){
|
||||
return false;
|
||||
}
|
||||
|
||||
return Sync::play(song, fbroadcast);
|
||||
}
|
||||
@ -135,22 +175,21 @@ bool Sync::play(QString url){
|
||||
return Sync::play(id);
|
||||
}
|
||||
|
||||
Repeat Sync::repeat()const{
|
||||
return _repeat;
|
||||
QMediaPlaylist::PlaybackMode Sync::repeat()const{
|
||||
return playList->getList()->playbackMode();
|
||||
}
|
||||
|
||||
void Sync::setRepeat(Repeat flag){
|
||||
_repeat = flag;
|
||||
void Sync::setRepeat(QMediaPlaylist::PlaybackMode flag){
|
||||
playList->getList()->setPlaybackMode(flag);
|
||||
}
|
||||
|
||||
bool Sync::pause(bool state){
|
||||
|
||||
if(!fbroadcaster){
|
||||
|
||||
if(playList.isEmpty())
|
||||
if(player->state() == QMediaPlayer::StoppedState){
|
||||
if(playList->isEmpty())
|
||||
return false;
|
||||
|
||||
return play(playList[0]);
|
||||
return play();
|
||||
}
|
||||
|
||||
if(state){
|
||||
@ -189,6 +228,9 @@ bool Sync::sync(const Syncer &sync, milliseconds ping){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo thi nead send a hedaer
|
||||
*/
|
||||
void Sync::sync(){
|
||||
|
||||
if(fbroadcaster)
|
||||
@ -196,7 +238,7 @@ void Sync::sync(){
|
||||
|
||||
package pac;
|
||||
if(!createPackage(t_sync, pac)){
|
||||
throw CreatePackageExaption();
|
||||
CreatePackageExaption();
|
||||
return;
|
||||
}
|
||||
node->WriteAll(pac.parseTo());
|
||||
@ -252,18 +294,17 @@ bool Sync::createPackage(Type type, package &pac){
|
||||
}
|
||||
|
||||
if(type & TypePackage::t_song_h && fbroadcaster){
|
||||
if(currentSongIndex < 0)
|
||||
if(playList->getList()->currentIndex() < 0)
|
||||
return false;
|
||||
|
||||
pac.header = playList[currentSongIndex];
|
||||
|
||||
pac.header = *playList->currentHeader();
|
||||
}
|
||||
|
||||
if(type & TypePackage::t_song && fbroadcaster){
|
||||
if(currentSongIndex < 0)
|
||||
if(playList->getList()->currentIndex() < 0)
|
||||
return false;
|
||||
|
||||
if(!sql->load(playList[currentSongIndex], pac.source))
|
||||
if(!playList->currentSong()->toSong(pac.source))
|
||||
return false;
|
||||
|
||||
}
|
||||
@ -387,7 +428,7 @@ void Sync::packageRender(ETcpSocket *socket){
|
||||
|
||||
// if requst from client
|
||||
if(pkg.getType() & t_play & t_sync){
|
||||
if(currentSongIndex < 0){
|
||||
if(playList->getList()->currentIndex() < 0){
|
||||
throw SyncError();
|
||||
socket->nextItem();
|
||||
continue;
|
||||
@ -443,32 +484,27 @@ void Sync::deepScaned(QList<ETcpSocket *> * list){
|
||||
}
|
||||
|
||||
void Sync::endPlay(QMediaPlayer::State state){
|
||||
if(state == QMediaPlayer::StoppedState){
|
||||
|
||||
switch (_repeat) {
|
||||
case allPlayListRandom:
|
||||
next(true);
|
||||
break;
|
||||
|
||||
case allPlayList:
|
||||
next(false);
|
||||
break;
|
||||
|
||||
case oneMusic:
|
||||
play(playList[currentSongIndex]);
|
||||
break;
|
||||
|
||||
default:
|
||||
currentSongIndex = -1;
|
||||
fbroadcaster = false;
|
||||
break;
|
||||
}
|
||||
switch (state) {
|
||||
case QMediaPlayer::StoppedState:
|
||||
fbroadcaster = false;
|
||||
break;
|
||||
case QMediaPlayer::PlayingState:
|
||||
sync();
|
||||
break;
|
||||
|
||||
case QMediaPlayer::PausedState:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
emit playStateChanged();
|
||||
}
|
||||
|
||||
QString Sync::getVersion(){
|
||||
return QString(tr("Version") + "%0.%1.%2").arg(MAJOR_VERSION).arg(MINOR_VERSION).arg(REVISION_VERSION);
|
||||
return QString(tr("Version") + "%0.%1.%2").
|
||||
arg(MAJOR_VERSION).arg(MINOR_VERSION).arg(REVISION_VERSION);
|
||||
}
|
||||
|
||||
bool Sync::setValume(unsigned int valume){
|
||||
@ -488,19 +524,16 @@ unsigned int Sync::seek() const{
|
||||
return player->position();
|
||||
}
|
||||
|
||||
const QList<SongHeader>* Sync::getPlayList() const{
|
||||
return &playList;
|
||||
const QList<SongStorage>* Sync::getPlayList() const{
|
||||
return playList->getInfo();
|
||||
}
|
||||
|
||||
int Sync::getCurrentSongIndex()const{
|
||||
return currentSongIndex;
|
||||
return playList->getList()->currentIndex();
|
||||
}
|
||||
|
||||
const SongHeader* Sync::getCurrentSong() const{
|
||||
if(currentSongIndex < 0 || currentSongIndex >= playList.size()){
|
||||
return nullptr;
|
||||
}
|
||||
return &playList[currentSongIndex];
|
||||
const SongStorage* Sync::getCurrentSong() const{
|
||||
return playList->currentSong();
|
||||
}
|
||||
|
||||
qint64 Sync::getEndPoint() const {
|
||||
@ -509,48 +542,53 @@ qint64 Sync::getEndPoint() const {
|
||||
|
||||
int Sync::addNewSong(const QString &url){
|
||||
int result = sql->save(url);
|
||||
updateSongs(playList);
|
||||
updateSongs(*playList);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Sync::updatePlayList(const QString &_playList){
|
||||
if(!updateSongs(playList, _playList)){
|
||||
if(!updateSongs(*playList, _playList)){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!playList.size())
|
||||
if(!playList->size())
|
||||
return false;
|
||||
|
||||
if(fbroadcaster){
|
||||
play(playList.first());
|
||||
play(fbroadcaster);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool Sync::next(bool random){
|
||||
if(playList.isEmpty())
|
||||
bool Sync::next(){
|
||||
if(playList->isEmpty())
|
||||
return false;
|
||||
|
||||
currentSongIndex = (currentSongIndex + ((random)? rand() % 10000:1)) % playList.size();
|
||||
return play(playList[currentSongIndex]);
|
||||
playList->next();
|
||||
emit currentSongChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sync::prev(){
|
||||
if(playList.isEmpty())
|
||||
if(playList->isEmpty())
|
||||
return false;
|
||||
|
||||
--currentSongIndex;
|
||||
if(currentSongIndex < 0)
|
||||
currentSongIndex = playList.size() - 1;
|
||||
return play(playList[currentSongIndex]);
|
||||
playList->prev();
|
||||
emit currentSongChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
QMediaPlayer::State Sync::playState()const{
|
||||
return player->state();
|
||||
}
|
||||
|
||||
Sync::~Sync(){
|
||||
delete node;
|
||||
delete player;
|
||||
delete sql;
|
||||
delete playList;
|
||||
servers.clear();
|
||||
|
||||
}
|
||||
|
68
sync/sync.h
68
sync/sync.h
@ -6,7 +6,9 @@
|
||||
#include <chrono>
|
||||
#include "config.h"
|
||||
#include "mysql.h"
|
||||
#include <QMediaPlaylist>
|
||||
#include "player.h"
|
||||
#include "playlist.h"
|
||||
|
||||
namespace syncLib {
|
||||
|
||||
@ -14,8 +16,6 @@ typedef std::chrono::time_point<std::chrono::high_resolution_clock> Clock;
|
||||
|
||||
class Node;
|
||||
|
||||
enum Repeat{noRepeat, oneMusic, allPlayList, allPlayListRandom};
|
||||
|
||||
|
||||
/**
|
||||
* @brief The Sync class is main class of this library.
|
||||
@ -27,9 +27,8 @@ class Sync : public QObject
|
||||
private:
|
||||
Node *node;
|
||||
Player *player;
|
||||
QList<SongHeader> playList;
|
||||
PlayList *playList;
|
||||
QString lastUsedPlayList;
|
||||
int currentSongIndex;
|
||||
QList<ETcpSocket*> servers;
|
||||
bool fbroadcaster;
|
||||
int resyncCount;
|
||||
@ -38,13 +37,6 @@ private:
|
||||
LocalScanner deepScaner;
|
||||
MySql *sql;
|
||||
int port;
|
||||
Repeat _repeat;
|
||||
|
||||
/**
|
||||
* @brief findHeader set current song if playList have playng song
|
||||
* @return true if all done
|
||||
*/
|
||||
bool findHeader(const Song& song);
|
||||
|
||||
/**
|
||||
* @brief rescan - search for existing servers
|
||||
@ -62,11 +54,17 @@ private:
|
||||
|
||||
private slots:
|
||||
|
||||
/**
|
||||
* @brief setSingle set singl or temp playlist
|
||||
* @return true if all done
|
||||
*/
|
||||
bool setSingle(const QMediaContent& media);
|
||||
|
||||
/**
|
||||
* @brief updateSongs use method update avelable songs from sql database
|
||||
* @return true if all done
|
||||
*/
|
||||
bool updateSongs(QList<SongHeader> &list, const QString &playList = "");
|
||||
bool updateSongs(PlayList &list, const QString &playList = "");
|
||||
|
||||
/**
|
||||
* @brief packageRender - the handler of all messages received.
|
||||
@ -96,13 +94,13 @@ public:
|
||||
* @brief repeat
|
||||
* @return flag of repeat
|
||||
*/
|
||||
Repeat repeat()const;
|
||||
QMediaPlaylist::PlaybackMode repeat()const;
|
||||
|
||||
/**
|
||||
* @brief setRepeat
|
||||
* @param flag new flag of repeat
|
||||
*/
|
||||
void setRepeat(Repeat flag);
|
||||
void setRepeat(QMediaPlaylist::PlaybackMode flag);
|
||||
|
||||
/**
|
||||
* @brief getSqlApi
|
||||
@ -110,6 +108,21 @@ public:
|
||||
*/
|
||||
MySql* getSqlApi();
|
||||
|
||||
/**
|
||||
* @brief Play song in this device, if device has not supported playning media data this method throw MediaExcrption.
|
||||
* @param fbroadcast - server broadcasting sound.
|
||||
* @return true if all done else false.
|
||||
*/
|
||||
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.
|
||||
* @param header of song
|
||||
@ -117,6 +130,15 @@ public:
|
||||
* @return true if all done else false.
|
||||
*/
|
||||
bool play(const SongHeader &header, 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 SongStorage &song, bool fbroadcast = true);
|
||||
|
||||
/**
|
||||
* @brief Play song in this device, if device has not supported playning media data this method throw MediaExcrption.
|
||||
* @param song playning media data.
|
||||
@ -228,7 +250,7 @@ public:
|
||||
* @brief getPlayList
|
||||
* @return list of available songs
|
||||
*/
|
||||
const QList<SongHeader> *getPlayList() const;
|
||||
const QList<SongStorage> *getPlayList() const;
|
||||
|
||||
/**
|
||||
* @brief SongHeader::getCurrentSongIndex
|
||||
@ -240,7 +262,7 @@ public:
|
||||
* @brief getCurrentSong
|
||||
* @return playing song.
|
||||
*/
|
||||
const SongHeader *getCurrentSong() const;
|
||||
const SongStorage *getCurrentSong() const;
|
||||
|
||||
/**
|
||||
* @brief getEndPoint
|
||||
@ -266,7 +288,7 @@ public:
|
||||
* @brief next
|
||||
* @return true if all done;
|
||||
*/
|
||||
bool next(bool random = false);
|
||||
bool next();
|
||||
|
||||
/**
|
||||
* @brief prev
|
||||
@ -274,6 +296,12 @@ public:
|
||||
*/
|
||||
bool prev();
|
||||
|
||||
/**
|
||||
* @brief playState
|
||||
* @return state of media data
|
||||
*/
|
||||
QMediaPlayer::State playState()const;
|
||||
|
||||
Sync(const QString &address = DEFAULT_ADRESS, int port = DEFAULT_PORT, const QString& datadir = DATABASE_NAME);
|
||||
~Sync();
|
||||
|
||||
@ -310,6 +338,12 @@ signals:
|
||||
*/
|
||||
void currentSongChanged();
|
||||
|
||||
/**
|
||||
* @brief playStateChanged
|
||||
* emited when state of playing song changed
|
||||
*/
|
||||
void playStateChanged();
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user