diff --git a/src/GroovePlayer.cpp b/src/GroovePlayer.cpp index 7fcba4c287b305f16c479b9249bdf74ac696af67..a53c4f597f29d2777a71fc5aea314130060b0a53 100644 --- a/src/GroovePlayer.cpp +++ b/src/GroovePlayer.cpp @@ -27,10 +27,11 @@ #include <Wt/WLogger> #include <Wt/Dbo/Transaction> #include <groovefingerprinter/fingerprinter.h> +#include <grooveplayer/player.h> -std::filesystem::path GroovePlayer::musicScanDir = ""; +std::filesystem::path GroovePlayerMgr::musicScanDir = ""; -GroovePlayer::GroovePlayer(std::string dbFile) : sqliteConnection(dbFile) +GroovePlayerMgr::GroovePlayerMgr (std::string dbFile) : sqliteConnection(dbFile) { sqlSession.setConnection(this->sqliteConnection); sqlSession.mapClass<User>("user"); @@ -50,7 +51,7 @@ GroovePlayer::GroovePlayer(std::string dbFile) : sqliteConnection(dbFile) grooveEvents = new std::thread(grooveEventLoop); } -std::list<const AudioTrack*> GroovePlayer::getNextVoteBatch() +std::list<const AudioTrack*> GroovePlayerMgr::getNextVoteBatch() { /** * This method will attempt to pick 3 tracks that will be up for selection next. @@ -82,13 +83,13 @@ std::list<const AudioTrack*> GroovePlayer::getNextVoteBatch() if(trackAlbumCount > 0 && computerSlightOfHand > 3) { //Pick item from album - Wt::Dbo::ptr<AudioTrack> eligibleTrack = getInstance()->sqlSession.find<AudioTrack>().where("album = ?").offset(rand() % trackAlbumCount).bind(getCurrentTrack()->trackAlbumName); + Wt::Dbo::ptr<AudioTrack> eligibleTrack = getInstance()->sqlSession.find<AudioTrack>().where("album = ?").limit(1).offset(rand() % trackAlbumCount).bind(getCurrentTrack()->trackAlbumName); selectedTracks.push_back(eligibleTrack.get()); } else if(trackArtistCount > 0) { //Pick item from artist - Wt::Dbo::ptr<AudioTrack> eligibleTrack = getInstance()->sqlSession.find<AudioTrack>().where("artist = ?").offset(rand() % trackArtistCount).bind(getCurrentTrack()->trackArtistName); + Wt::Dbo::ptr<AudioTrack> eligibleTrack = getInstance()->sqlSession.find<AudioTrack>().where("artist = ?").limit(1).offset(rand() % trackArtistCount).bind(getCurrentTrack()->trackArtistName); selectedTracks.push_back(eligibleTrack.get()); } @@ -97,7 +98,7 @@ std::list<const AudioTrack*> GroovePlayer::getNextVoteBatch() if(trackGenreCount > 0) { //Pick item from genre - Wt::Dbo::ptr<AudioTrack> eligibleTrack = getInstance()->sqlSession.find<AudioTrack>().where("genre = ?").offset(rand() % trackGenreCount).bind(getCurrentTrack()->trackGenre); + Wt::Dbo::ptr<AudioTrack> eligibleTrack = getInstance()->sqlSession.find<AudioTrack>().where("genre = ?").limit(1).offset(rand() % trackGenreCount).bind(getCurrentTrack()->trackGenre); selectedTracks.push_back(eligibleTrack.get()); } @@ -111,35 +112,61 @@ std::list<const AudioTrack*> GroovePlayer::getNextVoteBatch() else if(trackNotGenreCount > 0) { //Pick from other genre - Wt::Dbo::ptr<AudioTrack> eligibleTrack = getInstance()->sqlSession.find<AudioTrack>().where("genre != ?").offset(rand() % trackNotGenreCount).bind(getCurrentTrack()->trackGenre); + Wt::Dbo::ptr<AudioTrack> eligibleTrack = getInstance()->sqlSession.find<AudioTrack>().where("genre != ?").limit(1).offset(rand() % trackNotGenreCount).bind(getCurrentTrack()->trackGenre); selectedTracks.push_back(eligibleTrack.get()); } else { //Pick randomly - Wt::Dbo::ptr<AudioTrack> eligibleTrack = getInstance()->sqlSession.find<AudioTrack>().offset(rand() % trackCount); + Wt::Dbo::ptr<AudioTrack> eligibleTrack = getInstance()->sqlSession.find<AudioTrack>().limit(1).offset(rand() % trackCount); selectedTracks.push_back(eligibleTrack.get()); } return selectedTracks; } -void GroovePlayer::grooveEventLoop() +void GroovePlayerMgr::grooveEventLoop() { /** - * On first boot, random track that has been played before will start(or random if no track has been played before). + * On first boot, random track that has been voted before will start(or random if no track has been played before). * When voting ends, if no vote was cast, the first will be picked 60% of the time with second being 30% of the time and third being picked 10% of the time. * Exception is if third track is a request, then it is picked. If another song is voted over this, it will be put in back of request queue. */ + + Wt::Dbo::Transaction transaction(getInstance()->sqlSession); + + //Wait until at least one track is in DB. + if(getInstance()->sqlSession.query<int>("select count(fingerprint) from tracks") < 1) + { + while(getInstance()->sqlSession.query<int>("select count(fingerprint) from tracks") < 1){} + } + + //Pick initial track and boostrap player. + int tracksPlayedBefore = getInstance()->sqlSession.query<int>("select count(fingerprint) from tracks as t join actions on (actions.action = 3 or actions.action = 2) and actions.track_id = t.id"); + const AudioTrack* selectedTrack; + if (tracksPlayedBefore > 0) + { + selectedTrack = getInstance()->sqlSession.query<Wt::Dbo::ptr<AudioTrack>>("select t from tracks as t join actions on (actions.action = 3 or actions.action = 2) and actions.track_id = t.id").limit(1).offset(rand() % tracksPlayedBefore).resultValue().get(); + } + else + { + int trackCount = getInstance()->sqlSession.query<int>("select count(fingerprint) from tracks"); + selectedTrack = getInstance()->sqlSession.find<AudioTrack>().limit(1).offset(rand() % trackCount).resultValue().get(); + } + struct GroovePlaylist* playlist = groove_playlist_create(); + struct GroovePlayer* player = groove_player_create(); + if(!player) {return;} + + //TODO } -GroovePlayer::PlayerEvents GroovePlayer::getNextPlayerEvent() +GroovePlayerMgr::PlayerEvents GroovePlayerMgr::getNextPlayerEvent() { //TODO } -Wt::Dbo::ptr<AudioTrack> GroovePlayer::getCurrentTrack() +Wt::Dbo::ptr<AudioTrack> GroovePlayerMgr::getCurrentTrack() { Wt::Dbo::Transaction transaction(getInstance()->sqlSession); Wt::Dbo::ptr<AudioTrack> track = getInstance()->sqlSession.find<AudioTrack>().where("path = ?").bind(currentItem->file->filename); @@ -147,7 +174,7 @@ Wt::Dbo::ptr<AudioTrack> GroovePlayer::getCurrentTrack() } -bool GroovePlayer::addFileToTrackDBIfTagged(std::filesystem::path file) +bool GroovePlayerMgr::addFileToTrackDBIfTagged(std::filesystem::path file) { //Now check if tags exist and put into DB. struct GrooveFile* gfile = groove_file_open(file.c_str()); @@ -202,7 +229,7 @@ bool GroovePlayer::addFileToTrackDBIfTagged(std::filesystem::path file) return true; } -void GroovePlayer::removeOrphanedTracks() +void GroovePlayerMgr::removeOrphanedTracks() { Wt::Dbo::Transaction transaction(getInstance()->sqlSession); Wt::Dbo::collection<Wt::Dbo::ptr<AudioTrack>> tracks = getInstance()->sqlSession.find<AudioTrack>(); @@ -219,7 +246,7 @@ void GroovePlayer::removeOrphanedTracks() -void GroovePlayer::grooveAudioScannerLoop() +void GroovePlayerMgr::grooveAudioScannerLoop() { if(!std::filesystem::exists(musicScanDir)) { diff --git a/src/GroovePlayer.h b/src/GroovePlayer.h index 71939d382d01ddac153452cc65d44a7dffd632b7..57845e5161e7a7801960beb2a1094e34d2a1fe39 100644 --- a/src/GroovePlayer.h +++ b/src/GroovePlayer.h @@ -32,21 +32,21 @@ namespace std { namespace filesystem = experimental::filesystem; } -class GroovePlayer +class GroovePlayerMgr { public: static std::filesystem::path musicScanDir; - static GroovePlayer* getInstance() { - static GroovePlayer instance("music.db"); + static GroovePlayerMgr* getInstance() { + static GroovePlayerMgr instance("music.db"); musicScanDir = std::filesystem::path("music"); return &instance; }; - GroovePlayer(GroovePlayer const&) = delete; - void operator=(GroovePlayer const&) = delete; + GroovePlayerMgr ( GroovePlayerMgr const&) = delete; + void operator=( GroovePlayerMgr const&) = delete; private: - enum PlayerEvents {NOTHING, GROOVE_NOWPLAYING, VOTING_ENDED, VOTE_CAST, PLAYING_PAUSED, PLAYING_RESUMED, SKIP_REQUESTED, SKIP_VOTE_CAST, SKIP_VOTING_ENDED}; + enum PlayerEvents {NOTHING, GROOVE_NOWPLAYING, VOTING_ENDED, VOTE_CAST, PLAYING_PAUSED, PLAYING_RESUMED, SKIP_REQUESTED, SKIP_VOTE_CAST, SKIP_VOTING_ENDED, ADMIN_FORCE_SKIP}; - GroovePlayer(std::string dbFile); + GroovePlayerMgr (std::string dbFile); Wt::Dbo::backend::Sqlite3 sqliteConnection; Wt::Dbo::Session sqlSession; diff --git a/src/main.cpp b/src/main.cpp index 62d3171dc68297b11d9f2bb205bf00ba6dc8a5ff..6ddfe8c76de6a47236cca6e99bfc27ba0fe9c4c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,7 +17,7 @@ int main ( int argc, char** argv ) server.addEntryPoint(Wt::Application, createApplication); if(server.start()) { - GroovePlayer::getInstance(); + GroovePlayerMgr::getInstance(); int sig = Wt::WServer::waitForShutdown(argv[0]); server.stop(); }