Add groove player to stuff linked in. Add some vars to hold player events to watch for in event loop. Implement first version of vote picking algorithm.

This commit is contained in:
Kevin Whitaker
2017-01-31 22:06:58 -05:00
parent 83efc750eb
commit a38258a883
4 changed files with 106 additions and 8 deletions

View File

@@ -9,6 +9,6 @@ find_package(Wt REQUIRED)
find_package(Groove REQUIRED)
add_executable(arbitrateor src/main.cpp src/WebInterface.cpp src/GroovePlayer.cpp src/ui/LoginInterface.cpp src/ui/PlayerInterface.cpp)
target_link_libraries(arbitrateor ${Wt_LIBRARIES} ${GROOVE_LIBRARY} ${GROOVE_FINGERPRINT_LIBRARY} pthread stdc++fs) #TODO get threading links based on platform. Remove gcc experimental fs when official c++17 exists.
target_link_libraries(arbitrateor ${Wt_LIBRARIES} ${GROOVE_LIBRARY} ${GROOVE_FINGERPRINT_LIBRARY} ${GROOVE_PLAYER_LIBRARY} pthread stdc++fs) #TODO get threading links based on platform. Remove gcc experimental fs when official c++17 exists.
install(TARGETS arbitrateor RUNTIME DESTINATION bin)

View File

@@ -6,13 +6,15 @@
# GROOVE_INCLUDE_DIR
# GROOVE_LIBRARY
# GROOVE_FINGERPRINT_LIBRARY
# GROOVE_PLAYER_LIBRARY
find_path(GROOVE_INCLUDE_DIR NAMES groove/groove.h)
find_library(GROOVE_LIBRARY NAMES groove)
find_library(GROOVE_FINGERPRINT_LIBRARY NAMES groovefingerprinter)
find_library(GROOVE_PLAYER_LIBRARY NAMES grooveplayer)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GROOVE DEFAULT_MSG GROOVE_LIBRARY GROOVE_FINGERPRINT_LIBRARY GROOVE_INCLUDE_DIR)
find_package_handle_standard_args(GROOVE DEFAULT_MSG GROOVE_LIBRARY GROOVE_FINGERPRINT_LIBRARY GROOVE_PLAYER_LIBRARY GROOVE_INCLUDE_DIR)
mark_as_advanced(GROOVE_INCLUDE_DIR GROOVE_LIBRARY GROOVE_FINGERPRINT_LIBRARY)
mark_as_advanced(GROOVE_INCLUDE_DIR GROOVE_LIBRARY GROOVE_FINGERPRINT_LIBRARY GROOVE_PLAYER_LIBRARY)

View File

@@ -50,16 +50,103 @@ GroovePlayer::GroovePlayer(std::string dbFile) : sqliteConnection(dbFile)
grooveEvents = new std::thread(grooveEventLoop);
}
std::vector<AudioTrack*> GroovePlayer::getNextVoteBatch()
std::list<const AudioTrack*> GroovePlayer::getNextVoteBatch()
{
//TODO
/**
* This method will attempt to pick 3 tracks that will be up for selection next.
*
* The first track should be from the same album or artist.
* The second track should be from the same genre.
* The third track should be from something in a different genre.
*
* What is picked inside those requirements is a mix of random and TODO:based on past user actions(33% of time).
*
* The third track will be replaced by a recent request item if one exists.
*/
std::list<const AudioTrack*> selectedTracks;
Wt::Dbo::Transaction transaction(getInstance()->sqlSession);
//First make sure there are at least 3 tracks to suggest.
int trackCount = getInstance()->sqlSession.query<int>("select count(fingerprint) from tracks");
if(trackCount < 3)
{
//Return empty list to show there are not enough tracks to allow voting.
return selectedTracks;
}
//Determine first track
int trackAlbumCount = getInstance()->sqlSession.query<int>("select count(fingerprint) from tracks").where("album = ?").bind(getCurrentTrack()->trackAlbumName);
int trackArtistCount = getInstance()->sqlSession.query<int>("select count(fingerprint) from tracks").where("artist = ?").bind(getCurrentTrack()->trackArtistName);
int computerSlightOfHand = rand() % 10 + 1;
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);
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);
selectedTracks.push_back(eligibleTrack.get());
}
//Determine second track
int trackGenreCount = getInstance()->sqlSession.query<int>("select count(fingerprint) from tracks").where("genre = ?").bind(getCurrentTrack()->trackGenre);
if(trackGenreCount > 0)
{
//Pick item from genre
Wt::Dbo::ptr<AudioTrack> eligibleTrack = getInstance()->sqlSession.find<AudioTrack>().where("genre = ?").offset(rand() % trackGenreCount).bind(getCurrentTrack()->trackGenre);
selectedTracks.push_back(eligibleTrack.get());
}
//Determine third track
int trackNotGenreCount = getInstance()->sqlSession.query<int>("select count(fingerprint) from tracks").where("genre != ?").bind(getCurrentTrack()->trackGenre);
if(requestQueue.size() > 0)
{
//There's a request. Pick one up front and put as third item.
selectedTracks.push_back(requestQueue.front());
}
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);
selectedTracks.push_back(eligibleTrack.get());
}
else
{
//Pick randomly
Wt::Dbo::ptr<AudioTrack> eligibleTrack = getInstance()->sqlSession.find<AudioTrack>().offset(rand() % trackCount);
selectedTracks.push_back(eligibleTrack.get());
}
return selectedTracks;
}
void GroovePlayer::grooveEventLoop()
{
/**
* On first boot, random track that has been played 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.
*/
//TODO
}
GroovePlayer::PlayerEvents GroovePlayer::getNextPlayerEvent()
{
//TODO
}
Wt::Dbo::ptr<AudioTrack> GroovePlayer::getCurrentTrack()
{
Wt::Dbo::Transaction transaction(getInstance()->sqlSession);
Wt::Dbo::ptr<AudioTrack> track = getInstance()->sqlSession.find<AudioTrack>().where("path = ?").bind(currentItem->file->filename);
return track;
}
bool GroovePlayer::addFileToTrackDBIfTagged(std::filesystem::path file)
{
//Now check if tags exist and put into DB.

View File

@@ -22,7 +22,7 @@
#include <Wt/Dbo/Session>
#include <Wt/Dbo/backend/Sqlite3>
#include <vector>
#include <list>
#include <thread>
#include "db/User.h"
#include "db/AudioTrack.h"
@@ -44,19 +44,28 @@ public:
GroovePlayer(GroovePlayer const&) = delete;
void operator=(GroovePlayer const&) = delete;
private:
enum PlayerEvents {NOTHING, GROOVE_NOWPLAYING, VOTING_ENDED, VOTE_CAST, PLAYING_PAUSED, PLAYING_RESUMED, SKIP_REQUESTED, SKIP_VOTE_CAST, SKIP_VOTING_ENDED};
GroovePlayer(std::string dbFile);
Wt::Dbo::backend::Sqlite3 sqliteConnection;
Wt::Dbo::Session sqlSession;
std::vector<AudioTrack*> requestQueue;
std::list<const AudioTrack*> requestQueue;
std::list<PlayerEvents> lastInternalEvents;
GroovePlaylistItem* currentItem;
std::thread* grooveEvents;
static void grooveEventLoop();
std::vector<AudioTrack*> getNextVoteBatch();
std::list<const AudioTrack*> getNextVoteBatch();
std::thread* grooveAudioScanner;
static void grooveAudioScannerLoop();
PlayerEvents getNextPlayerEvent();
static bool addFileToTrackDBIfTagged(std::filesystem::path file);
static void removeOrphanedTracks();
Wt::Dbo::ptr<AudioTrack> getCurrentTrack();
};
#endif // GROOVEPLAYER_H