From ba2550427443c972beb454eaae06ff835600ef26 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 18 Mar 2018 14:30:48 +0300 Subject: [PATCH 1/6] create song storage class --- sync/song.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++------- sync/song.h | 23 +++++++++++++++++++- 2 files changed, 73 insertions(+), 9 deletions(-) diff --git a/sync/song.cpp b/sync/song.cpp index ed62b58..234e9e7 100644 --- a/sync/song.cpp +++ b/sync/song.cpp @@ -45,14 +45,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 +58,57 @@ 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; +} + +unsigned int SongStorage::getSize() const{ + return SongHeader::getSize(); +} + +const QUrl& SongStorage::getSource()const{ + return url; +} + +QMediaContent SongStorage::toMedia()const{ + return QMediaContent(url); +} + +bool SongStorage::isValid() const{ + + return SongHeader::isValid() && url.isValid(); +} + +SongStorage::~SongStorage(){} + +QDataStream& operator << (QDataStream& stream,const SongStorage& song){ + stream << static_cast(song); + stream << song.url; + return stream; +} + +QDataStream& operator >> (QDataStream& stream, SongStorage& song){ + stream >> static_cast(song); + stream >> song.url; + return stream; +} + +Song::Song(): + SongHeader() +{ + source.clear(); +} + Song::Song(const SongHeader& from) :Song::Song() { diff --git a/sync/song.h b/sync/song.h index eab15b6..eaeb5c5 100644 --- a/sync/song.h +++ b/sync/song.h @@ -4,6 +4,7 @@ #include #include #include "chronotime.h" +#include namespace syncLib { @@ -49,11 +50,31 @@ public: friend QDataStream& operator >> (QDataStream& stream, SongHeader& song); }; +/** + * @brief The SongStorage class + * header with url to song source + */ +class SongStorage : public SongHeader { +private: + QUrl url; +public: + SongStorage(); + SongStorage(const SongHeader& from); + const QUrl& getSource()const; + QMediaContent toMedia()const; + unsigned int getSize() const; + bool isValid() const; + ~SongStorage(); + friend QDataStream& operator << (QDataStream& stream, const SongStorage& song); + friend QDataStream& operator >> (QDataStream& stream, SongStorage& song); + friend class MySql; +}; + /** * @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: From 1ef62656c07db448026ab2ae3ccbb0e1d7e322a1 Mon Sep 17 00:00:00 2001 From: Andrei Date: Sun, 25 Mar 2018 23:01:44 +0300 Subject: [PATCH 2/6] added first change of song database --- sync/config.h | 3 ++ sync/mysql.cpp | 59 +++++++++++++++++++++++------------- sync/mysql.h | 15 ++++++++++ sync/song.cpp | 81 +++++++++++++++++--------------------------------- sync/song.h | 9 +++--- sync/sync.h | 3 +- 6 files changed, 91 insertions(+), 79 deletions(-) diff --git a/sync/config.h b/sync/config.h index f8f81ec..4988bef 100644 --- a/sync/config.h +++ b/sync/config.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 diff --git a/sync/mysql.cpp b/sync/mysql.cpp index f7693ea..3972de0 100644 --- a/sync/mysql.cpp +++ b/sync/mysql.cpp @@ -2,6 +2,7 @@ #include #include #include "exaptions.h" +#include namespace syncLib{ @@ -44,6 +45,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 +54,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,6 +118,31 @@ void MySql::initDB(const QString &database){ } } +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 " <qyery->lastError(); @@ -145,15 +161,16 @@ 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; + QUrl url; + if(!saveToStorage(url, song)){ + return false; } - qyery->bindValue(":val",song.source); + qyer = QString("INSERT INTO songs (name,size,data) VALUES" + "('%0',%1,'%2')").arg(song.name, + QString::number(song.size), + url.path()); + if(!qyery->exec()){ sqlErrorLog(qyer); return -1; @@ -176,7 +193,7 @@ int MySql::save(const QString &url){ } QByteArray bytes = f.readAll(); f.close(); - QString name = url.right(url.lastIndexOf(QRegularExpression("[\\/]"))); // meby [[\\\/]] + QString name = url.right(url.lastIndexOf(QRegularExpression("[\\\/]"))); Song song; song.name = name; song.size = bytes.size(); diff --git a/sync/mysql.h b/sync/mysql.h index 125defa..bd85046 100644 --- a/sync/mysql.h +++ b/sync/mysql.h @@ -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,6 +37,12 @@ public: */ void initDB(const QString& database = DATABASE_NAME ); + /** + * @brief setSoundDir + * @param str + */ + void setSoundDir(const QString& str); + /** * @brief load song of database; * @brief song - diff --git a/sync/song.cpp b/sync/song.cpp index 234e9e7..4911503 100644 --- a/sync/song.cpp +++ b/sync/song.cpp @@ -1,5 +1,7 @@ #include "song.h" #include +#include + namespace syncLib{ static const QStringList ValidSongs = {".mp3", ".wav", ".ogg"}; @@ -11,6 +13,17 @@ 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; + +} + SongHeader& SongHeader::operator =(const SongHeader& right){ this->id = right.id; this->name = right.name; @@ -18,15 +31,25 @@ SongHeader& SongHeader::operator =(const SongHeader& right){ return *this; } +SongHeader& SongHeader::operator =(const QMediaContent& right){ + this->id = -1; + if(!getName(name, right.canonicalUrl())){ + name.clear(); + } + this->size = right.canonicalResource().dataSize(); + return *this; +} + bool SongHeader::operator ==(const SongHeader& right){ 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){ + QString name; + if(!getName(name, right.canonicalUrl())){ + return false; + } + return this->name == name && this->size == right.canonicalResource().dataSize(); } bool SongHeader::isNameValid() const{ @@ -58,50 +81,6 @@ 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; -} - -unsigned int SongStorage::getSize() const{ - return SongHeader::getSize(); -} - -const QUrl& SongStorage::getSource()const{ - return url; -} - -QMediaContent SongStorage::toMedia()const{ - return QMediaContent(url); -} - -bool SongStorage::isValid() const{ - - return SongHeader::isValid() && url.isValid(); -} - -SongStorage::~SongStorage(){} - -QDataStream& operator << (QDataStream& stream,const SongStorage& song){ - stream << static_cast(song); - stream << song.url; - return stream; -} - -QDataStream& operator >> (QDataStream& stream, SongStorage& song){ - stream >> static_cast(song); - stream >> song.url; - return stream; -} Song::Song(): SongHeader() @@ -121,10 +100,6 @@ void Song::clear(){ source.clear(); } -unsigned int Song::getSize() const{ - return SongHeader::getSize() + source.size(); -} - const QByteArray& Song::getSource()const{ return source; } diff --git a/sync/song.h b/sync/song.h index eaeb5c5..bd4acb8 100644 --- a/sync/song.h +++ b/sync/song.h @@ -25,7 +25,8 @@ struct Syncer * (id,size and name) */ class SongHeader{ - +protected: + bool getName(QString &name, const QUrl& url)const; public: bool isSelected; int id; @@ -33,8 +34,10 @@ public: int size; SongHeader(); SongHeader& operator = (const SongHeader& right); + SongHeader& operator = (const QMediaContent& right); + bool operator == (const SongHeader& right); - virtual unsigned int getSize() const; + bool operator == (const QMediaContent& right); bool isNameValid() const; virtual bool isValid() const; virtual ~SongHeader(); @@ -62,7 +65,6 @@ public: SongStorage(const SongHeader& from); const QUrl& getSource()const; QMediaContent toMedia()const; - unsigned int getSize() const; bool isValid() const; ~SongStorage(); friend QDataStream& operator << (QDataStream& stream, const SongStorage& song); @@ -82,7 +84,6 @@ 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); diff --git a/sync/sync.h b/sync/sync.h index 62eb1cd..a3acf93 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -6,6 +6,7 @@ #include #include "config.h" #include "mysql.h" +#include #include "player.h" namespace syncLib { @@ -27,7 +28,7 @@ class Sync : public QObject private: Node *node; Player *player; - QList playList; + QMediaPlaylist playList; QString lastUsedPlayList; int currentSongIndex; QList servers; From ff5a910d33b8ed0ee96ec917f9f8dec3506a63b1 Mon Sep 17 00:00:00 2001 From: Andrei Date: Thu, 29 Mar 2018 00:23:53 +0300 Subject: [PATCH 3/6] medacontent --- SoundBand/playlistmodel.cpp | 6 +- SoundBand/playlistmodel.h | 2 +- SoundBand/syncengine.cpp | 4 +- SoundBand/syncengine.h | 2 +- sync/mysql.cpp | 100 ++++++++++++++++++++++-------- sync/mysql.h | 38 ++++++++++-- sync/player.cpp | 18 ------ sync/player.h | 7 --- sync/song.cpp | 72 ++++++++++++++++++++++ sync/song.h | 5 ++ sync/sync.cpp | 120 +++++++++++++++++------------------- sync/sync.h | 37 ++++++----- 12 files changed, 268 insertions(+), 143 deletions(-) diff --git a/SoundBand/playlistmodel.cpp b/SoundBand/playlistmodel.cpp index 1cf184c..9e03ba8 100644 --- a/SoundBand/playlistmodel.cpp +++ b/SoundBand/playlistmodel.cpp @@ -94,7 +94,7 @@ QVariant PlayListModel::data(const QModelIndex &index, int role) const bool PlayListModel::select(int id){ - for(QList::Iterator i = playList.begin(); i < playList.end(); i++){ + for(QList::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 PlayListModel::getSelected(){ QList result; - for(QList::Iterator i = playList.begin(); i < playList.end(); i++){ + for(QList::Iterator i = playList.begin(); i < playList.end(); i++){ if(i->isSelected){ result.push_back(i->id); } @@ -124,7 +124,7 @@ QList PlayListModel::getSelected(){ bool PlayListModel::isSelected(int id){ - for(QList::Iterator i = playList.begin(); i < playList.end(); i++){ + for(QList::Iterator i = playList.begin(); i < playList.end(); i++){ if(i->id == id){ return i->isSelected; } diff --git a/SoundBand/playlistmodel.h b/SoundBand/playlistmodel.h index 58b7c41..bc8d143 100644 --- a/SoundBand/playlistmodel.h +++ b/SoundBand/playlistmodel.h @@ -16,7 +16,7 @@ class PlayListModel : public QAbstractListModel private: SyncEngine * syncEngine; - QList playList; + QList playList; QString playListName; int itemCount; diff --git a/SoundBand/syncengine.cpp b/SoundBand/syncengine.cpp index 1b4ef08..6e00c9b 100644 --- a/SoundBand/syncengine.cpp +++ b/SoundBand/syncengine.cpp @@ -140,7 +140,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 +157,7 @@ bool SyncEngine::setPlayList(const QString& name){ } -bool SyncEngine::getPlayList(QList &playList, const QString &name){ +bool SyncEngine::getPlayList(QList &playList, const QString &name){ return sqlApi->updateAvailableSongs(playList, name, true); } diff --git a/SoundBand/syncengine.h b/SoundBand/syncengine.h index a89f69f..7f908ab 100644 --- a/SoundBand/syncengine.h +++ b/SoundBand/syncengine.h @@ -138,7 +138,7 @@ public slots: * @param name - name of selected playList * @return */ - bool getPlayList(QList &playList, const QString& name); + bool getPlayList(QList &playList, const QString& name); /** * @brief lastError - message of last error diff --git a/sync/mysql.cpp b/sync/mysql.cpp index 3972de0..736a709 100644 --- a/sync/mysql.cpp +++ b/sync/mysql.cpp @@ -3,6 +3,7 @@ #include #include "exaptions.h" #include +#include namespace syncLib{ @@ -118,6 +119,59 @@ void MySql::initDB(const QString &database){ } } +bool MySql::find(const QMediaContent &song, SongStorage &response){ + QList 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 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 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); @@ -149,7 +203,7 @@ void MySql::sqlErrorLog(const QString &qyery)const{ #endif } -int MySql::save(const Song &song){ +int MySql::save(const Song &song , bool onlyDataBase){ QString qyer = QString("SELECT id from songs where name='%0' and size=%1").arg(song.name, QString::number(song.size)); if(!qyery->exec(qyer)){ @@ -162,7 +216,7 @@ int MySql::save(const Song &song){ } QUrl url; - if(!saveToStorage(url, song)){ + if(!onlyDataBase && !saveToStorage(url, song)){ return false; } @@ -186,29 +240,19 @@ int MySql::save(const Song &song){ return result; } -int MySql::save(const QString &url){ - QFile f(QUrl(url).toLocalFile()); - if(!f.open(QIODevice::ReadOnly)){ - return -1; - } - QByteArray bytes = f.readAll(); - f.close(); - QString name = url.right(url.lastIndexOf(QRegularExpression("[\\\/]"))); - Song song; - song.name = name; - song.size = bytes.size(); - song.source = bytes; +int MySql::save(const QString &url){ + + SongStorage song(QUrl::fromLocalFile(url)); if(!song.isNameValid()){ return -1; } - return save(song); + return save(song, true); } -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)){ @@ -230,17 +274,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(); + result.url = qyery->value(3).toUrl(); return true; } -bool MySql::updateAvailableSongs(QList& list, const QString& playList, bool forEditing){ +bool MySql::updateAvailableSongs(QList& 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); } @@ -253,11 +297,13 @@ bool MySql::updateAvailableSongs(QList& 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 = qyery->value(3).toUrl(); + list.push_back(song); } @@ -272,7 +318,7 @@ bool MySql::updateAvailableSongs(QList& 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; @@ -286,15 +332,15 @@ bool MySql::updateAvailableSongs(QList& list, const QString& playLis return true; } -bool MySql::updateAvailableSongs(QStringList& list, const QString& playList){ +bool MySql::updateAvailableSongs(QMediaPlaylist& list, const QString& playList){ - QList tempList; + QList tempList; if(!updateAvailableSongs(tempList, playList)) return false; - for(SongHeader &header : tempList){ - list.push_back(header.name); + for(SongStorage &header : tempList){ + list.addMedia(header.toMedia()); } return true; diff --git a/sync/mysql.h b/sync/mysql.h index bd85046..a922826 100644 --- a/sync/mysql.h +++ b/sync/mysql.h @@ -37,26 +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 Song &song); + int save(const Song &song, bool onlyDataBase = false); /** * @brief save media file, bud from url. @@ -77,7 +107,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& list, const QString &playList = "", bool forEditing = false); + bool updateAvailableSongs(QList& list, const QString &playList = "", bool forEditing = false); /** * @brief updateAvelableSongs will update the list of participants of songs. @@ -85,7 +115,7 @@ public: * @param playList - play list of songs (string). * @return true if all done */ - bool updateAvailableSongs(QStringList& list, const QString &playList = ""); + bool updateAvailableSongs(QMediaPlaylist &list, const QString &playList = ""); /** * @brief removeSong - remove song from local database. diff --git a/sync/player.cpp b/sync/player.cpp index 1f8494a..05fa849 100644 --- a/sync/player.cpp +++ b/sync/player.cpp @@ -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(); diff --git a/sync/player.h b/sync/player.h index 9af3603..d5077c5 100644 --- a/sync/player.h +++ b/sync/player.h @@ -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. */ diff --git a/sync/song.cpp b/sync/song.cpp index 4911503..2b21672 100644 --- a/sync/song.cpp +++ b/sync/song.cpp @@ -1,6 +1,7 @@ #include "song.h" #include #include +#include namespace syncLib{ @@ -82,6 +83,77 @@ QDataStream& operator >> (QDataStream& stream, SongHeader& song){ } +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; + } + + this->id = -1; + if(!getName(name, from)){ + name.clear(); + } + + this->size = QFile(from.toLocalFile()).size(); +} + +const QUrl& SongStorage::getSource()const{ + return url; +} + +bool SongStorage::isValid() const{ + return SongHeader::isValid() && url.isValid(); +} + +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(song); + stream << song.url; + return stream; +} + +QDataStream& operator >> (QDataStream& stream, SongStorage& song){ + stream >> static_cast(song); + stream >> song.url; + return stream; +} + + Song::Song(): SongHeader() { diff --git a/sync/song.h b/sync/song.h index bd4acb8..b4affae 100644 --- a/sync/song.h +++ b/sync/song.h @@ -63,7 +63,10 @@ private: public: SongStorage(); SongStorage(const SongHeader& from); + SongStorage(const QUrl& url); + const QUrl& getSource()const; + bool toSong(Song &)const; QMediaContent toMedia()const; bool isValid() const; ~SongStorage(); @@ -89,6 +92,8 @@ public: friend QDataStream& operator << (QDataStream& stream, const Song& song); friend QDataStream& operator >> (QDataStream& stream, Song& song); friend class MySql; + friend class SongStorage; + }; } #endif // SONG_H diff --git a/sync/sync.cpp b/sync/sync.cpp index 91df405..74dd4a1 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -23,6 +23,8 @@ Sync::Sync(const QString &address, int port, const QString &datadir): throw MediaException(); } + playList = player->playlist(); + fbroadcaster = false; resyncCount = 0; lastSyncTime = 0; @@ -41,7 +43,7 @@ MySql* Sync::getSqlApi(){ return sql; } -bool Sync::updateSongs(QList& list, const QString& playList){ +bool Sync::updateSongs(QMediaPlaylist& list, const QString& playList){ if(!sql->updateAvailableSongs(list, playList)){ return false; } @@ -59,28 +61,37 @@ 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(song)){ - currentSongIndex = i; - return true; - } + if(fbroadcaster){ + player->play(); + sync(); + }else{ + player->syncBegin(); } + emit currentSongChanged(); - return false; + return true; } bool Sync::play(const SongHeader &header, bool fbroadcast){ - Song song; + if(!header.isValid()){ + return false; + } + + SongStorage song; SongHeader newheader = header; newheader.id = -1; if(!sql->load(newheader, song)){ return false; } - return Sync::play(song, fbroadcast); + playList->clear(); + playList->addMedia(song.toMedia()); + + return play(fbroadcast); } bool Sync::play(const Song &song, bool fbroadcast){ @@ -89,27 +100,26 @@ 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(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; + playList->clear(); + playList->addMedia(media); + + return Sync::play(fbroadcast); } bool Sync::play(int id_song, bool fbroadcast){ @@ -120,7 +130,7 @@ bool Sync::play(int id_song, bool fbroadcast){ SongHeader header; header.id = id_song; - Song song; + SongStorage song; sql->load(header, song); return Sync::play(song, fbroadcast); @@ -135,22 +145,22 @@ bool Sync::play(QString url){ return Sync::play(id); } -Repeat Sync::repeat()const{ - return _repeat; +QMediaPlaylist::PlaybackMode Sync::repeat()const{ + return playList->playbackMode(); } -void Sync::setRepeat(Repeat flag){ - _repeat = flag; +void Sync::setRepeat(QMediaPlaylist::PlaybackMode flag){ + playList->setPlaybackMode(flag); } bool Sync::pause(bool state){ if(!fbroadcaster){ - if(playList.isEmpty()) + if(playList->isEmpty()) return false; - return play(playList[0]); + return play(); } if(state){ @@ -252,18 +262,21 @@ bool Sync::createPackage(Type type, package &pac){ } if(type & TypePackage::t_song_h && fbroadcaster){ - if(currentSongIndex < 0) + if(playList->currentIndex() < 0) return false; - pac.header = playList[currentSongIndex]; + if(!sql->find(playList->currentMedia(), pac.header)){ + return false; + } } if(type & TypePackage::t_song && fbroadcaster){ - if(currentSongIndex < 0) + if(playList->currentIndex() < 0) return false; - if(!sql->load(playList[currentSongIndex], pac.source)) + SongStorage song; + if(!sql->load(playList->currentMedia(), song) && !song.toSong(pac.source)) return false; } @@ -387,7 +400,7 @@ void Sync::packageRender(ETcpSocket *socket){ // if requst from client if(pkg.getType() & t_play & t_sync){ - if(currentSongIndex < 0){ + if(playList->currentIndex() < 0){ throw SyncError(); socket->nextItem(); continue; @@ -443,27 +456,9 @@ void Sync::deepScaned(QList * 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; + if(state == QMediaPlayer::StoppedState && playList->currentIndex() != -1){ fbroadcaster = false; break; - } - } } @@ -488,19 +483,16 @@ unsigned int Sync::seek() const{ return player->position(); } -const QList* Sync::getPlayList() const{ - return &playList; +const QMediaPlaylist* Sync::getPlayList() const{ + return playList; } int Sync::getCurrentSongIndex()const{ - return currentSongIndex; + return playList->currentIndex(); } -const SongHeader* Sync::getCurrentSong() const{ - if(currentSongIndex < 0 || currentSongIndex >= playList.size()){ - return nullptr; - } - return &playList[currentSongIndex]; +const QMediaContent* Sync::getCurrentSong() const{ + return &playList->currentMedia(); } qint64 Sync::getEndPoint() const { diff --git a/sync/sync.h b/sync/sync.h index a3acf93..e3e3670 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -15,8 +15,6 @@ typedef std::chrono::time_point Clock; class Node; -enum Repeat{noRepeat, oneMusic, allPlayList, allPlayListRandom}; - /** * @brief The Sync class is main class of this library. @@ -28,9 +26,8 @@ class Sync : public QObject private: Node *node; Player *player; - QMediaPlaylist playList; + QMediaPlaylist *playList; QString lastUsedPlayList; - int currentSongIndex; QList servers; bool fbroadcaster; int resyncCount; @@ -39,13 +36,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 @@ -67,7 +57,7 @@ private slots: * @brief updateSongs use method update avelable songs from sql database * @return true if all done */ - bool updateSongs(QList &list, const QString &playList = ""); + bool updateSongs(QMediaPlaylist &list, const QString &playList = ""); /** * @brief packageRender - the handler of all messages received. @@ -97,13 +87,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 @@ -111,6 +101,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 @@ -229,7 +234,7 @@ public: * @brief getPlayList * @return list of available songs */ - const QList *getPlayList() const; + const QMediaPlaylist *getPlayList() const; /** * @brief SongHeader::getCurrentSongIndex @@ -241,7 +246,7 @@ public: * @brief getCurrentSong * @return playing song. */ - const SongHeader *getCurrentSong() const; + const QMediaContent *getCurrentSong() const; /** * @brief getEndPoint From 4e7992395144c49dc1d44832909419eab1bf48bb Mon Sep 17 00:00:00 2001 From: Andrei Date: Thu, 29 Mar 2018 22:02:03 +0300 Subject: [PATCH 4/6] second refactor commit --- SoundBand/SoundBand.pro | 6 ++- SoundBand/syncengine.cpp | 4 +- SoundBand/syncengine.h | 4 +- sync/mysql.cpp | 9 ++--- sync/mysql.h | 4 +- sync/playlist.cpp | 55 ++++++++++++++++++++++++++ sync/playlist.h | 84 ++++++++++++++++++++++++++++++++++++++++ sync/song.cpp | 6 +++ sync/song.h | 45 ++++++++++----------- sync/sync.cpp | 41 +++++++++----------- sync/sync.h | 9 +++-- 11 files changed, 206 insertions(+), 61 deletions(-) create mode 100644 sync/playlist.cpp create mode 100644 sync/playlist.h diff --git a/SoundBand/SoundBand.pro b/SoundBand/SoundBand.pro index 0bffc62..c89350c 100644 --- a/SoundBand/SoundBand.pro +++ b/SoundBand/SoundBand.pro @@ -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 diff --git a/SoundBand/syncengine.cpp b/SoundBand/syncengine.cpp index 6e00c9b..d381791 100644 --- a/SoundBand/syncengine.cpp +++ b/SoundBand/syncengine.cpp @@ -42,7 +42,7 @@ bool SyncEngine::init(){ return true; } -const QList* SyncEngine::currentPlayList() const{ +const QList* SyncEngine::currentPlayList() const{ return sync->getPlayList(); } @@ -157,7 +157,7 @@ bool SyncEngine::setPlayList(const QString& name){ } -bool SyncEngine::getPlayList(QList &playList, const QString &name){ +bool SyncEngine::getPlayList(QList &playList, const QString &name){ return sqlApi->updateAvailableSongs(playList, name, true); } diff --git a/SoundBand/syncengine.h b/SoundBand/syncengine.h index 7f908ab..35c53db 100644 --- a/SoundBand/syncengine.h +++ b/SoundBand/syncengine.h @@ -74,7 +74,7 @@ public slots: * @brief currentPlayList * @return return current Play List */ - const QList *currentPlayList() const; + const QList *currentPlayList() const; /** * @brief currentPlayListName @@ -138,7 +138,7 @@ public slots: * @param name - name of selected playList * @return */ - bool getPlayList(QList &playList, const QString& name); + bool getPlayList(QList &playList, const QString& name); /** * @brief lastError - message of last error diff --git a/sync/mysql.cpp b/sync/mysql.cpp index 736a709..16af272 100644 --- a/sync/mysql.cpp +++ b/sync/mysql.cpp @@ -3,7 +3,7 @@ #include #include "exaptions.h" #include -#include +#include "playlist.h" namespace syncLib{ @@ -328,19 +328,18 @@ bool MySql::updateAvailableSongs(QList& list, const QString& playLi } } - return true; } -bool MySql::updateAvailableSongs(QMediaPlaylist& list, const QString& playList){ +bool MySql::updateAvailableSongs(PlayList& list, const QString& playList, bool forEditing){ QList tempList; - if(!updateAvailableSongs(tempList, playList)) + if(!updateAvailableSongs(tempList, playList, forEditing)) return false; for(SongStorage &header : tempList){ - list.addMedia(header.toMedia()); + list.addMedia(header); } return true; diff --git a/sync/mysql.h b/sync/mysql.h index a922826..988f855 100644 --- a/sync/mysql.h +++ b/sync/mysql.h @@ -1,7 +1,7 @@ #ifndef MYSQL_H #define MYSQL_H #include -#include "song.h" +#include "playlist.h" class QSqlDatabase; class QSqlQuery; @@ -115,7 +115,7 @@ public: * @param playList - play list of songs (string). * @return true if all done */ - bool updateAvailableSongs(QMediaPlaylist &list, const QString &playList = ""); + bool updateAvailableSongs(PlayList& list, const QString &playList = "", bool forEditing = false); /** * @brief removeSong - remove song from local database. diff --git a/sync/playlist.cpp b/sync/playlist.cpp new file mode 100644 index 0000000..1f5af77 --- /dev/null +++ b/sync/playlist.cpp @@ -0,0 +1,55 @@ +#include "playlist.h" + +PlayList::PlayList(QMediaPlaylist *playList) +{ + playListInfo.clear(); + this->playList = playList; +} + +QList* 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; +} + +bool PlayList::isValid()const{ + return playListInfo.size() == playList->mediaCount(); +} + +bool PlayList::isEmpty()const{ + return playList->isEmpty() && playListInfo.isEmpty(); +} + +const SongHeader& PlayList::currentHeader()const{ + return static_cast(playListInfo[playList->currentIndex()]); +} + +const SongStorage& PlayList::currentSong()const{ + return playListInfo[playList->currentIndex()]; +} + +int PlayList::size()const{ + return playList->mediaCount(); +} + +PlayList::~PlayList(){ + +} diff --git a/sync/playlist.h b/sync/playlist.h new file mode 100644 index 0000000..c20599f --- /dev/null +++ b/sync/playlist.h @@ -0,0 +1,84 @@ +#ifndef PLAYLIST_H +#define PLAYLIST_H +#include +#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 playListInfo; +public: + PlayList(QMediaPlaylist * playList); + + /** + * @brief getInfo + * @return info from database about songs + */ + QList* 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 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; + + ~PlayList(); +}; + +#endif // PLAYLIST_H diff --git a/sync/song.cpp b/sync/song.cpp index 2b21672..619d09a 100644 --- a/sync/song.cpp +++ b/sync/song.cpp @@ -112,6 +112,12 @@ SongStorage::SongStorage(const QUrl& from) this->size = QFile(from.toLocalFile()).size(); } +SongStorage::SongStorage(const QMediaContent& from) + :SongStorage::SongStorage(from.canonicalUrl()) +{ + +} + const QUrl& SongStorage::getSource()const{ return url; } diff --git a/sync/song.h b/sync/song.h index b4affae..942fa7a 100644 --- a/sync/song.h +++ b/sync/song.h @@ -53,28 +53,6 @@ public: friend QDataStream& operator >> (QDataStream& stream, SongHeader& song); }; -/** - * @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); - - 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; -}; - /** * @brief The Song class * into this calss added mediadata of playable media file. @@ -95,5 +73,28 @@ public: 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 diff --git a/sync/sync.cpp b/sync/sync.cpp index 74dd4a1..a4a4873 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -23,12 +23,11 @@ Sync::Sync(const QString &address, int port, const QString &datadir): throw MediaException(); } - playList = player->playlist(); + playList = new PlayList(player->playlist()); fbroadcaster = false; resyncCount = 0; lastSyncTime = 0; - currentSongIndex = 0; ping = 0; sql = new MySql(datadir); @@ -43,7 +42,7 @@ MySql* Sync::getSqlApi(){ return sql; } -bool Sync::updateSongs(QMediaPlaylist& list, const QString& playList){ +bool Sync::updateSongs(PlayList& list, const QString& playList){ if(!sql->updateAvailableSongs(list, playList)){ return false; } @@ -146,11 +145,11 @@ bool Sync::play(QString url){ } QMediaPlaylist::PlaybackMode Sync::repeat()const{ - return playList->playbackMode(); + return playList->getList()->playbackMode(); } void Sync::setRepeat(QMediaPlaylist::PlaybackMode flag){ - playList->setPlaybackMode(flag); + playList->getList()->setPlaybackMode(flag); } bool Sync::pause(bool state){ @@ -262,21 +261,17 @@ bool Sync::createPackage(Type type, package &pac){ } if(type & TypePackage::t_song_h && fbroadcaster){ - if(playList->currentIndex() < 0) + if(playList->getList()->currentIndex() < 0) return false; - if(!sql->find(playList->currentMedia(), pac.header)){ - return false; - } - + pac.header = playList->currentHeader(); } if(type & TypePackage::t_song && fbroadcaster){ - if(playList->currentIndex() < 0) + if(playList->getList()->currentIndex() < 0) return false; - SongStorage song; - if(!sql->load(playList->currentMedia(), song) && !song.toSong(pac.source)) + if(!playList->currentSong().toSong(pac.source)) return false; } @@ -400,7 +395,7 @@ void Sync::packageRender(ETcpSocket *socket){ // if requst from client if(pkg.getType() & t_play & t_sync){ - if(playList->currentIndex() < 0){ + if(playList->getList()->currentIndex() < 0){ throw SyncError(); socket->nextItem(); continue; @@ -456,14 +451,15 @@ void Sync::deepScaned(QList * list){ } void Sync::endPlay(QMediaPlayer::State state){ - if(state == QMediaPlayer::StoppedState && playList->currentIndex() != -1){ + if(state == QMediaPlayer::StoppedState && + playList->getList()->currentIndex() != -1){ fbroadcaster = false; - break; } } 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){ @@ -483,16 +479,16 @@ unsigned int Sync::seek() const{ return player->position(); } -const QMediaPlaylist* Sync::getPlayList() const{ - return playList; +const QList* Sync::getPlayList() const{ + return playList->getInfo(); } int Sync::getCurrentSongIndex()const{ - return playList->currentIndex(); + return playList->getList()->currentIndex(); } -const QMediaContent* Sync::getCurrentSong() const{ - return &playList->currentMedia(); +const SongStorage* Sync::getCurrentSong() const{ + return &playList->currentSong(); } qint64 Sync::getEndPoint() const { @@ -543,6 +539,7 @@ Sync::~Sync(){ delete node; delete player; delete sql; + delete playList; servers.clear(); } diff --git a/sync/sync.h b/sync/sync.h index e3e3670..982e72b 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -8,6 +8,7 @@ #include "mysql.h" #include #include "player.h" +#include "playlist.h" namespace syncLib { @@ -26,7 +27,7 @@ class Sync : public QObject private: Node *node; Player *player; - QMediaPlaylist *playList; + PlayList *playList; QString lastUsedPlayList; QList servers; bool fbroadcaster; @@ -57,7 +58,7 @@ private slots: * @brief updateSongs use method update avelable songs from sql database * @return true if all done */ - bool updateSongs(QMediaPlaylist &list, const QString &playList = ""); + bool updateSongs(PlayList &list, const QString &playList = ""); /** * @brief packageRender - the handler of all messages received. @@ -234,7 +235,7 @@ public: * @brief getPlayList * @return list of available songs */ - const QMediaPlaylist *getPlayList() const; + const QList *getPlayList() const; /** * @brief SongHeader::getCurrentSongIndex @@ -246,7 +247,7 @@ public: * @brief getCurrentSong * @return playing song. */ - const QMediaContent *getCurrentSong() const; + const SongStorage *getCurrentSong() const; /** * @brief getEndPoint From 65015229e45d97240f5fc0c3ab4afead4ae6bd16 Mon Sep 17 00:00:00 2001 From: Andrei Date: Mon, 2 Apr 2018 01:03:27 +0300 Subject: [PATCH 5/6] fix play song --- SoundBand/currentplaylistmodel.h | 2 +- sync/mysql.cpp | 53 ++++++++++++++++++--------- sync/mysql.h | 9 ++++- sync/playlist.cpp | 28 +++++++++++---- sync/playlist.h | 16 +++++++-- sync/song.cpp | 9 +++-- sync/sync.cpp | 61 ++++++++++++++++++++------------ sync/sync.h | 11 +++++- 8 files changed, 133 insertions(+), 56 deletions(-) diff --git a/SoundBand/currentplaylistmodel.h b/SoundBand/currentplaylistmodel.h index 790ac55..0809d81 100644 --- a/SoundBand/currentplaylistmodel.h +++ b/SoundBand/currentplaylistmodel.h @@ -17,7 +17,7 @@ class CurrentPlayListModel : public QAbstractListModel private: SyncEngine * syncEngine; - const QList *playList; + const QList *playList; int itemCount; private slots: diff --git a/sync/mysql.cpp b/sync/mysql.cpp index 16af272..faaedc1 100644 --- a/sync/mysql.cpp +++ b/sync/mysql.cpp @@ -203,9 +203,11 @@ void MySql::sqlErrorLog(const QString &qyery)const{ #endif } -int MySql::save(const Song &song , bool onlyDataBase){ - 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; @@ -215,17 +217,12 @@ int MySql::save(const Song &song , bool onlyDataBase){ return qyery->value(0).toInt(); } - QUrl url; - if(!onlyDataBase && !saveToStorage(url, song)){ - return false; - } - - qyer = QString("INSERT INTO songs (name,size,data) VALUES" + qyer = QString("INSERT INTO songs (name,size,data) VALUES " "('%0',%1,'%2')").arg(song.name, QString::number(song.size), - url.path()); + song.url.path()); - if(!qyery->exec()){ + if(!qyery->exec(qyer)){ sqlErrorLog(qyer); return -1; } @@ -240,15 +237,34 @@ int MySql::save(const Song &song , bool onlyDataBase){ return result; } +int MySql::save(const Song &song){ + + + QUrl url; + if(!saveToStorage(url, song)){ + return false; + } + + return save(SongStorage(url)); + + +} + int MySql::save(const QString &url){ - SongStorage song(QUrl::fromLocalFile(url)); + QUrl qurl = QUrl(url); + + if(!qurl.isValid()){ + return -1; + } + + SongStorage song(qurl); if(!song.isNameValid()){ return -1; } - return save(song, true); + return save(song); } @@ -274,8 +290,8 @@ bool MySql::load(const SongHeader &song, SongStorage &result){ result.id = qyery->value(0).toInt(); result.name = qyery->value(1).toString(); result.size = qyery->value(2).toInt(); - result.url = qyery->value(3).toUrl(); - return true; + result.url = QUrl::fromLocalFile(qyery->value(3).toString()); + return result.isValid(); } bool MySql::updateAvailableSongs(QList& list, const QString& playList, bool forEditing){ @@ -302,7 +318,7 @@ bool MySql::updateAvailableSongs(QList& list, const QString& playLi song.id = qyery->value(0).toInt(); song.name = qyery->value(1).toString(); song.size = qyery->value(2).toInt(); - song.url = qyery->value(3).toUrl(); + song.url = QUrl::fromLocalFile(qyery->value(3).toString()); list.push_back(song); } @@ -334,12 +350,15 @@ bool MySql::updateAvailableSongs(QList& list, const QString& playLi bool MySql::updateAvailableSongs(PlayList& list, const QString& playList, bool forEditing){ QList tempList; + list.clear(); if(!updateAvailableSongs(tempList, playList, forEditing)) return false; for(SongStorage &header : tempList){ - list.addMedia(header); + if(!list.addMedia(header)){ + this->removeSong(header); + } } return true; diff --git a/sync/mysql.h b/sync/mysql.h index 988f855..e5ab00d 100644 --- a/sync/mysql.h +++ b/sync/mysql.h @@ -86,7 +86,14 @@ public: * @param song savining media data. * @return id of song saved on local database. */ - int save(const Song &song, bool onlyDataBase = false); + int save(const SongStorage &song); + + /** + * @brief save media data into local database. + * @param song savining media data. + * @return id of song saved on local database. + */ + int save(const Song &song); /** * @brief save media file, bud from url. diff --git a/sync/playlist.cpp b/sync/playlist.cpp index 1f5af77..3a405dd 100644 --- a/sync/playlist.cpp +++ b/sync/playlist.cpp @@ -1,9 +1,9 @@ #include "playlist.h" -PlayList::PlayList(QMediaPlaylist *playList) +PlayList::PlayList() { playListInfo.clear(); - this->playList = playList; + playList = new QMediaPlaylist(); } QList* PlayList::getInfo(){ @@ -30,6 +30,14 @@ bool PlayList::addMedia(const SongStorage &song){ return true; } +void PlayList::next()const{ + playList->next(); +} + +void PlayList::prev()const{ + playList->previous(); +} + bool PlayList::isValid()const{ return playListInfo.size() == playList->mediaCount(); } @@ -38,12 +46,18 @@ bool PlayList::isEmpty()const{ return playList->isEmpty() && playListInfo.isEmpty(); } -const SongHeader& PlayList::currentHeader()const{ - return static_cast(playListInfo[playList->currentIndex()]); +const SongHeader *PlayList::currentHeader()const{ + if(playList->isEmpty()) + return nullptr; + + return static_cast(&playListInfo[playList->currentIndex()]); } -const SongStorage& PlayList::currentSong()const{ - return playListInfo[playList->currentIndex()]; +const SongStorage *PlayList::currentSong()const{ + if(playList->isEmpty()) + return nullptr; + + return &playListInfo[playList->currentIndex()]; } int PlayList::size()const{ @@ -51,5 +65,5 @@ int PlayList::size()const{ } PlayList::~PlayList(){ - + delete playList; } diff --git a/sync/playlist.h b/sync/playlist.h index c20599f..c4e0fd7 100644 --- a/sync/playlist.h +++ b/sync/playlist.h @@ -22,7 +22,7 @@ private: */ QList playListInfo; public: - PlayList(QMediaPlaylist * playList); + PlayList(); /** * @brief getInfo @@ -42,6 +42,16 @@ public: */ bool addMedia(const SongStorage& song); + /** + * @brief next + */ + void next()const; + + /** + * @brief prev + */ + void prev()const; + /** * @brief isValid * @return true if this object valid @@ -64,13 +74,13 @@ public: * @brief currentHeader * @return header of curent song */ - const SongHeader& currentHeader()const; + const SongHeader* currentHeader()const; /** * @brief currentStorage * @return header of curent song */ - const SongStorage& currentSong()const; + const SongStorage* currentSong()const; /** * @brief size diff --git a/sync/song.cpp b/sync/song.cpp index 619d09a..c4cce2f 100644 --- a/sync/song.cpp +++ b/sync/song.cpp @@ -104,12 +104,15 @@ SongStorage::SongStorage(const QUrl& from) return; } + QFile f(from.toLocalFile()); + this->size = f.size(); + f.close(); + this->id = -1; + url = from; if(!getName(name, from)){ name.clear(); } - - this->size = QFile(from.toLocalFile()).size(); } SongStorage::SongStorage(const QMediaContent& from) @@ -123,7 +126,7 @@ const QUrl& SongStorage::getSource()const{ } bool SongStorage::isValid() const{ - return SongHeader::isValid() && url.isValid(); + return SongHeader::isValid() && url.isValid() && QFile(url.toLocalFile()).exists(); } SongStorage::~SongStorage(){ diff --git a/sync/sync.cpp b/sync/sync.cpp index a4a4873..b629936 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -22,8 +22,10 @@ Sync::Sync(const QString &address, int port, const QString &datadir): if(!player->isAvailable()){ throw MediaException(); } + playList = new PlayList; + + player->setPlaylist(playList->getList()); - playList = new PlayList(player->playlist()); fbroadcaster = false; resyncCount = 0; @@ -74,6 +76,18 @@ bool Sync::play(bool fbroadcast){ return true; } +bool Sync::play(const SongStorage &song, bool fbroadcast){ + + if(!song.isValid()){ + return false; + } + + playList->clear(); + playList->addMedia(song); + + return play(fbroadcast); +} + bool Sync::play(const SongHeader &header, bool fbroadcast){ if(!header.isValid()){ @@ -87,10 +101,7 @@ bool Sync::play(const SongHeader &header, bool fbroadcast){ return false; } - playList->clear(); - playList->addMedia(song.toMedia()); - - return play(fbroadcast); + return play(song, fbroadcast); } bool Sync::play(const Song &song, bool fbroadcast){ @@ -128,9 +139,12 @@ bool Sync::play(int id_song, bool fbroadcast){ } SongHeader header; - header.id = id_song; SongStorage song; - sql->load(header, song); + header.id = id_song; + + if(!sql->load(header, song)){ + return false; + } return Sync::play(song, fbroadcast); } @@ -198,6 +212,9 @@ bool Sync::sync(const Syncer &sync, milliseconds ping){ } +/** + * @todo thi nead send a hedaer +*/ void Sync::sync(){ if(fbroadcaster) @@ -264,14 +281,14 @@ bool Sync::createPackage(Type type, package &pac){ if(playList->getList()->currentIndex() < 0) return false; - pac.header = playList->currentHeader(); + pac.header = *playList->currentHeader(); } if(type & TypePackage::t_song && fbroadcaster){ if(playList->getList()->currentIndex() < 0) return false; - if(!playList->currentSong().toSong(pac.source)) + if(!playList->currentSong()->toSong(pac.source)) return false; } @@ -488,7 +505,7 @@ int Sync::getCurrentSongIndex()const{ } const SongStorage* Sync::getCurrentSong() const{ - return &playList->currentSong(); + return playList->currentSong(); } qint64 Sync::getEndPoint() const { @@ -497,42 +514,40 @@ 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(); + 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(); + return true; } Sync::~Sync(){ diff --git a/sync/sync.h b/sync/sync.h index 982e72b..d14d130 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -124,6 +124,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. @@ -273,7 +282,7 @@ public: * @brief next * @return true if all done; */ - bool next(bool random = false); + bool next(); /** * @brief prev From a5c22b9ca70e1a23ad66d4599b0be1b0c48dd7d2 Mon Sep 17 00:00:00 2001 From: Andrei Date: Thu, 5 Apr 2018 21:54:49 +0300 Subject: [PATCH 6/6] finaly commit --- SoundBand/Header.qml | 5 ++-- SoundBand/syncengine.cpp | 6 +++++ SoundBand/syncengine.h | 18 +++++++++++++++ sync/playlist.cpp | 28 ++++++++++++++++++++-- sync/playlist.h | 19 +++++++++++++++ sync/song.cpp | 32 +++++++++++++++++++++---- sync/song.h | 5 ++-- sync/sync.cpp | 50 +++++++++++++++++++++++++++++++++------- sync/sync.h | 18 +++++++++++++++ 9 files changed, 162 insertions(+), 19 deletions(-) diff --git a/SoundBand/Header.qml b/SoundBand/Header.qml index 99e1ac9..1014a3e 100644 --- a/SoundBand/Header.qml +++ b/SoundBand/Header.qml @@ -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) } } diff --git a/SoundBand/syncengine.cpp b/SoundBand/syncengine.cpp index d381791..1eb35da 100644 --- a/SoundBand/syncengine.cpp +++ b/SoundBand/syncengine.cpp @@ -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())); } @@ -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; diff --git a/SoundBand/syncengine.h b/SoundBand/syncengine.h index 35c53db..6be2ad1 100644 --- a/SoundBand/syncengine.h +++ b/SoundBand/syncengine.h @@ -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: @@ -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 diff --git a/sync/playlist.cpp b/sync/playlist.cpp index 3a405dd..a44829d 100644 --- a/sync/playlist.cpp +++ b/sync/playlist.cpp @@ -47,14 +47,14 @@ bool PlayList::isEmpty()const{ } const SongHeader *PlayList::currentHeader()const{ - if(playList->isEmpty()) + if(playList->isEmpty() || playList->currentIndex() < 0) return nullptr; return static_cast(&playListInfo[playList->currentIndex()]); } const SongStorage *PlayList::currentSong()const{ - if(playList->isEmpty()) + if(playList->isEmpty() || playList->currentIndex() < 0) return nullptr; return &playListInfo[playList->currentIndex()]; @@ -64,6 +64,30 @@ 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; } diff --git a/sync/playlist.h b/sync/playlist.h index c4e0fd7..256b40b 100644 --- a/sync/playlist.h +++ b/sync/playlist.h @@ -88,6 +88,25 @@ public: */ 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(); }; diff --git a/sync/song.cpp b/sync/song.cpp index c4cce2f..abfc11d 100644 --- a/sync/song.cpp +++ b/sync/song.cpp @@ -25,6 +25,20 @@ bool SongHeader::getName(QString & name, const QUrl &url) const { } +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; @@ -37,20 +51,30 @@ SongHeader& SongHeader::operator =(const QMediaContent& right){ if(!getName(name, right.canonicalUrl())){ name.clear(); } - this->size = right.canonicalResource().dataSize(); + + if(!getSize(this->size, right.canonicalUrl())){ + this->size = 0; + } + return *this; } -bool SongHeader::operator ==(const SongHeader& right){ +bool SongHeader::operator ==(const SongHeader& right)const{ return this->name == right.name && this->size == right.size; } -bool SongHeader::operator ==(const QMediaContent& right){ +bool SongHeader::operator ==(const QMediaContent& right)const{ QString name; if(!getName(name, right.canonicalUrl())){ return false; } - return this->name == name && this->size == right.canonicalResource().dataSize(); + + int size;; + if(!getSize(size, right.canonicalUrl())){ + return false; + } + + return this->name == name && this->size == size; } bool SongHeader::isNameValid() const{ diff --git a/sync/song.h b/sync/song.h index 942fa7a..54aa297 100644 --- a/sync/song.h +++ b/sync/song.h @@ -27,6 +27,7 @@ struct Syncer class SongHeader{ protected: bool getName(QString &name, const QUrl& url)const; + bool getSize(int &size, const QUrl& url)const; public: bool isSelected; int id; @@ -36,8 +37,8 @@ public: SongHeader& operator = (const SongHeader& right); SongHeader& operator = (const QMediaContent& right); - bool operator == (const SongHeader& right); - bool 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(); diff --git a/sync/sync.cpp b/sync/sync.cpp index b629936..2744448 100644 --- a/sync/sync.cpp +++ b/sync/sync.cpp @@ -44,6 +44,14 @@ MySql* Sync::getSqlApi(){ return sql; } +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; @@ -82,6 +90,10 @@ bool Sync::play(const SongStorage &song, bool fbroadcast){ return false; } + if(playList->selectSong(song)){ + return play(fbroadcast); + } + playList->clear(); playList->addMedia(song); @@ -94,6 +106,10 @@ bool Sync::play(const SongHeader &header, bool fbroadcast){ return false; } + if(playList->selectSong(header)){ + return play(fbroadcast); + } + SongStorage song; SongHeader newheader = header; newheader.id = -1; @@ -126,8 +142,9 @@ bool Sync::play(const QMediaContent& media, bool fbroadcast){ return false; } - playList->clear(); - playList->addMedia(media); + if(!setSingle(media)){ + return false; + } return Sync::play(fbroadcast); } @@ -168,8 +185,7 @@ void Sync::setRepeat(QMediaPlaylist::PlaybackMode flag){ bool Sync::pause(bool state){ - if(!fbroadcaster){ - + if(player->state() == QMediaPlayer::StoppedState){ if(playList->isEmpty()) return false; @@ -222,7 +238,7 @@ void Sync::sync(){ package pac; if(!createPackage(t_sync, pac)){ - throw CreatePackageExaption(); + CreatePackageExaption(); return; } node->WriteAll(pac.parseTo()); @@ -468,10 +484,22 @@ void Sync::deepScaned(QList * list){ } void Sync::endPlay(QMediaPlayer::State state){ - if(state == QMediaPlayer::StoppedState && - playList->getList()->currentIndex() != -1){ - fbroadcaster = false; + + switch (state) { + case QMediaPlayer::StoppedState: + fbroadcaster = false; + break; + case QMediaPlayer::PlayingState: + sync(); + break; + + case QMediaPlayer::PausedState: + break; + default: + break; } + + emit playStateChanged(); } QString Sync::getVersion(){ @@ -539,6 +567,7 @@ bool Sync::next(){ return false; playList->next(); + emit currentSongChanged(); return true; } @@ -547,9 +576,14 @@ bool Sync::prev(){ return false; playList->prev(); + emit currentSongChanged(); return true; } +QMediaPlayer::State Sync::playState()const{ + return player->state(); +} + Sync::~Sync(){ delete node; delete player; diff --git a/sync/sync.h b/sync/sync.h index d14d130..9c65010 100644 --- a/sync/sync.h +++ b/sync/sync.h @@ -54,6 +54,12 @@ 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 @@ -290,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(); @@ -326,6 +338,12 @@ signals: */ void currentSongChanged(); + /** + * @brief playStateChanged + * emited when state of playing song changed + */ + void playStateChanged(); + }; }