add limits to places where offsets to avoid some syntax problems. Rename grooveplayer class to avoid conflict with official libgroove class. Add admin event. Write start of event loop that picks initial song.

This commit is contained in:
Kevin Whitaker
2017-02-01 22:13:40 -05:00
parent a38258a883
commit 685d1828ad
3 changed files with 50 additions and 23 deletions

View File

@@ -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))
{

View File

@@ -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;

View File

@@ -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();
}