Stop using pointers from DB as storage mechanism. Start storing copies of the object itself. Use commits after methods are done with transaction to hopefully help with DB issues. Don't use map because it requires too much about the key object I don't need. Add boolean that prevents vote end from being called constantly during it's 3 second window.
This commit is contained in:
@@ -64,7 +64,7 @@ GroovePlayerMgr::GroovePlayerMgr (std::string dbFile) : sqliteConnection(dbFile)
|
||||
//}
|
||||
}
|
||||
|
||||
std::list<const AudioTrack*> GroovePlayerMgr::getNextVoteBatch(Wt::Dbo::Session* session)
|
||||
std::list<AudioTrack> GroovePlayerMgr::getNextVoteBatch(Wt::Dbo::Session* session)
|
||||
{
|
||||
/**
|
||||
* This method will attempt to pick 3 tracks that will be up for selection next.
|
||||
@@ -78,7 +78,7 @@ std::list<const AudioTrack*> GroovePlayerMgr::getNextVoteBatch(Wt::Dbo::Session*
|
||||
* The third track will be replaced by a recent request item if one exists.
|
||||
*/
|
||||
|
||||
std::list<const AudioTrack*> selectedTracks;
|
||||
std::list<AudioTrack> selectedTracks;
|
||||
|
||||
Wt::Dbo::Transaction transaction(*session);
|
||||
//First make sure there are at least 3 tracks to suggest.
|
||||
@@ -90,33 +90,33 @@ std::list<const AudioTrack*> GroovePlayerMgr::getNextVoteBatch(Wt::Dbo::Session*
|
||||
}
|
||||
|
||||
//Determine first track
|
||||
int trackAlbumCount = session->query<int>("select count(fingerprint) from tracks").where("album = ?").bind(getCurrentTrack(session)->trackAlbumName);
|
||||
int trackArtistCount = session->query<int>("select count(fingerprint) from tracks").where("artist = ?").bind(getCurrentTrack(session)->trackArtistName);
|
||||
int trackAlbumCount = session->query<int>("select count(fingerprint) from tracks").where("album = ?").bind(getCurrentTrack(session).trackAlbumName);
|
||||
int trackArtistCount = session->query<int>("select count(fingerprint) from tracks").where("artist = ?").bind(getCurrentTrack(session).trackArtistName);
|
||||
int computerSlightOfHand = rand() % 10 + 1;
|
||||
if(trackAlbumCount > 0 && computerSlightOfHand > 3)
|
||||
{
|
||||
//Pick item from album
|
||||
Wt::Dbo::ptr<AudioTrack> eligibleTrack = session->find<AudioTrack>().where("album = ?").limit(1).offset(rand() % trackAlbumCount).bind(getCurrentTrack(session)->trackAlbumName);
|
||||
selectedTracks.push_back(eligibleTrack.get());
|
||||
Wt::Dbo::ptr<AudioTrack> eligibleTrack = session->find<AudioTrack>().where("album = ?").limit(1).offset(rand() % trackAlbumCount).bind(getCurrentTrack(session).trackAlbumName);
|
||||
selectedTracks.push_back(*eligibleTrack);
|
||||
}
|
||||
else if(trackArtistCount > 0)
|
||||
{
|
||||
//Pick item from artist
|
||||
Wt::Dbo::ptr<AudioTrack> eligibleTrack = session->find<AudioTrack>().where("artist = ?").limit(1).offset(rand() % trackArtistCount).bind(getCurrentTrack(session)->trackArtistName);
|
||||
selectedTracks.push_back(eligibleTrack.get());
|
||||
Wt::Dbo::ptr<AudioTrack> eligibleTrack = session->find<AudioTrack>().where("artist = ?").limit(1).offset(rand() % trackArtistCount).bind(getCurrentTrack(session).trackArtistName);
|
||||
selectedTracks.push_back(*eligibleTrack);
|
||||
}
|
||||
|
||||
//Determine second track
|
||||
int trackGenreCount = session->query<int>("select count(fingerprint) from tracks").where("genre = ?").bind(getCurrentTrack(session)->trackGenre);
|
||||
int trackGenreCount = session->query<int>("select count(fingerprint) from tracks").where("genre = ?").bind(getCurrentTrack(session).trackGenre);
|
||||
if(trackGenreCount > 0)
|
||||
{
|
||||
//Pick item from genre
|
||||
Wt::Dbo::ptr<AudioTrack> eligibleTrack = session->find<AudioTrack>().where("genre = ?").limit(1).offset(rand() % trackGenreCount).bind(getCurrentTrack(session)->trackGenre);
|
||||
selectedTracks.push_back(eligibleTrack.get());
|
||||
Wt::Dbo::ptr<AudioTrack> eligibleTrack = session->find<AudioTrack>().where("genre = ?").limit(1).offset(rand() % trackGenreCount).bind(getCurrentTrack(session).trackGenre);
|
||||
selectedTracks.push_back(*eligibleTrack);
|
||||
}
|
||||
|
||||
//Determine third track
|
||||
int trackNotGenreCount = session->query<int>("select count(fingerprint) from tracks").where("genre != ?").bind(getCurrentTrack(session)->trackGenre);
|
||||
int trackNotGenreCount = session->query<int>("select count(fingerprint) from tracks").where("genre != ?").bind(getCurrentTrack(session).trackGenre);
|
||||
if(requestQueue.size() > 0)
|
||||
{
|
||||
//There's a request. Pick one up front and put as third item.
|
||||
@@ -125,15 +125,17 @@ std::list<const AudioTrack*> GroovePlayerMgr::getNextVoteBatch(Wt::Dbo::Session*
|
||||
else if(trackNotGenreCount > 0)
|
||||
{
|
||||
//Pick from other genre
|
||||
Wt::Dbo::ptr<AudioTrack> eligibleTrack = session->find<AudioTrack>().where("genre != ?").limit(1).offset(rand() % trackNotGenreCount).bind(getCurrentTrack(session)->trackGenre);
|
||||
selectedTracks.push_back(eligibleTrack.get());
|
||||
Wt::Dbo::ptr<AudioTrack> eligibleTrack = session->find<AudioTrack>().where("genre != ?").limit(1).offset(rand() % trackNotGenreCount).bind(getCurrentTrack(session).trackGenre);
|
||||
selectedTracks.push_back(*eligibleTrack);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Pick randomly
|
||||
Wt::Dbo::ptr<AudioTrack> eligibleTrack = session->find<AudioTrack>().limit(1).offset(rand() % trackCount);
|
||||
selectedTracks.push_back(eligibleTrack.get());
|
||||
selectedTracks.push_back(*eligibleTrack);
|
||||
}
|
||||
transaction.commit();
|
||||
Wt::log("info") << "Next set of tracks to vote picked: 1=>[" << (*selectedTracks.begin()).trackName << "] 2=>[" << (*std::next(selectedTracks.begin(),1)).trackName << "] 3=>[" << (*std::next(selectedTracks.begin(),2)).trackName << "]";
|
||||
return selectedTracks;
|
||||
}
|
||||
|
||||
@@ -160,23 +162,24 @@ void GroovePlayerMgr::grooveEventLoop()
|
||||
|
||||
//Pick initial track to bootstrap.
|
||||
int tracksPlayedBefore = 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;
|
||||
AudioTrack selectedTrack;
|
||||
if (tracksPlayedBefore > 0)
|
||||
{
|
||||
selectedTrack = 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();
|
||||
selectedTrack = *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();
|
||||
}
|
||||
else
|
||||
{
|
||||
int trackCount = sqlSession.query<int>("select count(fingerprint) from tracks");
|
||||
selectedTrack = sqlSession.find<AudioTrack>().limit(1).offset(rand() % trackCount).resultValue().get();
|
||||
selectedTrack = *sqlSession.find<AudioTrack>().limit(1).offset(rand() % trackCount).resultValue();
|
||||
}
|
||||
transaction.commit();
|
||||
struct GroovePlaylist* playlist = groove_playlist_create();
|
||||
currentPlaylist = playlist;
|
||||
struct GroovePlayer* player = groove_player_create();
|
||||
if(!player) {return;}
|
||||
currentPlayer = player;
|
||||
|
||||
groove_playlist_insert(playlist, groove_file_open(selectedTrack->trackPath.c_str()),1.0,1.0,nullptr);
|
||||
groove_playlist_insert(playlist, groove_file_open(selectedTrack.trackPath.c_str()),1.0,1.0,nullptr);
|
||||
|
||||
//Now boostrap player with initial data
|
||||
groove_player_attach(player, playlist);
|
||||
@@ -185,7 +188,7 @@ void GroovePlayerMgr::grooveEventLoop()
|
||||
Wt::WApplication* app = Wt::WApplication::instance();
|
||||
if(app != nullptr)
|
||||
{
|
||||
static_cast<WebInterface*>(app)->songChangedFromServer(getCurrentTrack(&sqlSession).get());
|
||||
static_cast<WebInterface*>(app)->songChangedFromServer(getCurrentTrack(&sqlSession));
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -203,51 +206,52 @@ void GroovePlayerMgr::grooveEventLoop()
|
||||
{
|
||||
//Pick new batch of tracks to vote on and inform UI of update.
|
||||
currentVoteBatch = getNextVoteBatch(&sqlSession);
|
||||
currentVoteStatus = std::map<const AudioTrack*, int>();
|
||||
std::for_each(currentVoteBatch.begin(),currentVoteBatch.end(),[&](const AudioTrack* item){
|
||||
currentVoteStatus.insert(std::pair<const AudioTrack*, int>(item,0));
|
||||
});
|
||||
currentVoteStatus = std::list<std::pair<AudioTrack, int>>();
|
||||
for(auto track : currentVoteBatch)
|
||||
{
|
||||
currentVoteStatus.push_back(std::pair<AudioTrack, int>(track,0));
|
||||
}
|
||||
Wt::WServer::instance()->postAll([&]() {
|
||||
Wt::WApplication* app = Wt::WApplication::instance();
|
||||
if(app != nullptr)
|
||||
{
|
||||
static_cast<WebInterface*>(app)->songChangedFromServer(getCurrentTrack(&sqlSession).get());
|
||||
static_cast<WebInterface*>(app)->songChangedFromServer(getCurrentTrack(&sqlSession));
|
||||
static_cast<WebInterface*>(app)->voteTracksUpdatedFromServer(currentVoteBatch);
|
||||
}
|
||||
}
|
||||
);
|
||||
Wt::log("info") << "Track playing changed to: " << getCurrentTrack(&sqlSession).get()->trackName;
|
||||
Wt::log("info") << "Track playing changed to: " << getCurrentTrack(&sqlSession).trackName;
|
||||
}
|
||||
else if(event == VOTING_ENDED)
|
||||
{
|
||||
//Look at votes and add correct track to end of playlist.
|
||||
//If more than one track has highest votes, pick random. TODO:maybe base off of other play data instead.
|
||||
|
||||
std::list<std::pair<const AudioTrack*,int>> trackWinners;
|
||||
for(std::map<const AudioTrack*,int>::iterator track = currentVoteStatus.begin(); track != currentVoteStatus.end(); track++)
|
||||
std::list<std::pair<AudioTrack,int>> trackWinners;
|
||||
for(auto track : currentVoteStatus)
|
||||
{
|
||||
//There nothing yet and there was at least a vote is an initial winner.
|
||||
if(trackWinners.size() == 0 && track->second > 0)
|
||||
if(trackWinners.size() == 0 && track.second > 0)
|
||||
{
|
||||
trackWinners.push_back(std::pair<const AudioTrack*, int>(track->first,track->second));
|
||||
trackWinners.push_back(track);
|
||||
continue;
|
||||
}
|
||||
//If there is a winner. Check if higher. If so, clear the list and add this one. If equal, add to list.
|
||||
if(trackWinners.size() > 0)
|
||||
{
|
||||
if(trackWinners.front().second < track->second)
|
||||
if(trackWinners.front().second < track.second)
|
||||
{
|
||||
trackWinners.clear();
|
||||
trackWinners.push_back(std::pair<const AudioTrack*,int>(track->first, track->second));
|
||||
trackWinners.push_back(std::pair<AudioTrack,int>(track.first, track.second));
|
||||
}
|
||||
else if(trackWinners.front().second == track->second)
|
||||
else if(trackWinners.front().second == track.second)
|
||||
{
|
||||
trackWinners.push_back(std::pair<const AudioTrack*, int>(track->first, track->second));
|
||||
trackWinners.push_back(std::pair<AudioTrack, int>(track.first, track.second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const AudioTrack* winner;
|
||||
AudioTrack winner;
|
||||
//Randomly pick from winners(in case of tie), if there are any.
|
||||
if(trackWinners.size() > 0)
|
||||
{
|
||||
@@ -259,7 +263,7 @@ void GroovePlayerMgr::grooveEventLoop()
|
||||
if(requestQueue.size() > 0)
|
||||
{
|
||||
//If winning track was a request, now you can remove it from request queue.
|
||||
if(requestQueue.front()->trackFingerprint == winner->trackFingerprint)
|
||||
if(requestQueue.front().trackFingerprint == winner.trackFingerprint)
|
||||
{
|
||||
requestQueue.pop_front();
|
||||
}
|
||||
@@ -296,12 +300,12 @@ void GroovePlayerMgr::grooveEventLoop()
|
||||
else
|
||||
{
|
||||
//Third track wins
|
||||
winner = (*currentVoteBatch.begin()+=2);
|
||||
winner = (*(currentVoteBatch.begin()++)++);
|
||||
}
|
||||
}
|
||||
}
|
||||
groove_playlist_insert(currentPlaylist,groove_file_open(winner->trackPath.c_str()),1.0,1.0,nullptr);
|
||||
Wt::log("info")<< "Voting has ended. Next track is: " << winner->trackName;
|
||||
groove_playlist_insert(currentPlaylist,groove_file_open(winner.trackPath.c_str()),1.0,1.0,nullptr);
|
||||
Wt::log("info")<< "Voting has ended. Next track is: " << winner.trackName;
|
||||
}
|
||||
else if(event == VOTE_CAST)
|
||||
{
|
||||
@@ -350,8 +354,9 @@ GroovePlayerMgr::PlayerEvents GroovePlayerMgr::getNextPlayerEvent(Wt::Dbo::Sessi
|
||||
{
|
||||
double timeIntoTrack;
|
||||
groove_player_position(currentPlayer,nullptr,&timeIntoTrack);
|
||||
if(getCurrentTrack(session).get() != nullptr && getCurrentTrack(session)->trackLengthSeconds-timeIntoTrack < 3)
|
||||
if(!voteEndedButNotNextTrackYet && getCurrentTrack(session).trackName != std::string() && getCurrentTrack(session).trackLengthSeconds-timeIntoTrack < 3)
|
||||
{
|
||||
voteEndedButNotNextTrackYet = true;
|
||||
return VOTING_ENDED;
|
||||
}
|
||||
GroovePlayerEvent event;
|
||||
@@ -359,6 +364,7 @@ GroovePlayerMgr::PlayerEvents GroovePlayerMgr::getNextPlayerEvent(Wt::Dbo::Sessi
|
||||
{
|
||||
if(event.type == GROOVE_EVENT_NOWPLAYING)
|
||||
{
|
||||
voteEndedButNotNextTrackYet = false;
|
||||
return GROOVE_NOWPLAYING;
|
||||
}
|
||||
}
|
||||
@@ -371,17 +377,19 @@ GroovePlayerMgr::PlayerEvents GroovePlayerMgr::getNextPlayerEvent(Wt::Dbo::Sessi
|
||||
return NOTHING;
|
||||
}
|
||||
|
||||
Wt::Dbo::ptr<AudioTrack> GroovePlayerMgr::getCurrentTrack(Wt::Dbo::Session* session)
|
||||
AudioTrack GroovePlayerMgr::getCurrentTrack(Wt::Dbo::Session* session)
|
||||
{
|
||||
Wt::Dbo::Transaction transaction(*session);
|
||||
GroovePlaylistItem* currentItem;
|
||||
groove_player_position(this->currentPlayer,¤tItem,nullptr);
|
||||
if(currentItem != nullptr)
|
||||
{
|
||||
Wt::Dbo::ptr<AudioTrack> track = session->find<AudioTrack>().where("path = ?").bind(currentItem->file->filename);
|
||||
AudioTrack track = *session->find<AudioTrack>().where("path = ?").bind(currentItem->file->filename).resultValue();
|
||||
transaction.commit();
|
||||
return track;
|
||||
}
|
||||
return Wt::Dbo::ptr<AudioTrack>();
|
||||
transaction.commit();
|
||||
return AudioTrack();
|
||||
}
|
||||
|
||||
|
||||
@@ -436,6 +444,7 @@ bool GroovePlayerMgr::addFileToTrackDBIfTagged(Wt::Dbo::Session* session, std::f
|
||||
newTrack->trackFingerprint = fingerprint;
|
||||
newTrack->trackPath = file.string();
|
||||
session->add(newTrack);
|
||||
transaction.commit();
|
||||
groove_file_close(gfile);
|
||||
return true;
|
||||
}
|
||||
@@ -453,6 +462,7 @@ void GroovePlayerMgr::removeOrphanedTracks(Wt::Dbo::Session* session)
|
||||
item.remove();
|
||||
}
|
||||
}
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user