Skip to content

Commit

Permalink
More work on remote playlists. Login. etc
Browse files Browse the repository at this point in the history
  • Loading branch information
sasq64 committed Jul 29, 2014
1 parent 5794bbb commit a35ddf9
Show file tree
Hide file tree
Showing 16 changed files with 234 additions and 41 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ CPP_MODS = ../cpp-mods
include $(CPP_MODS)/config.mk

OBJDIR := obj/
CFLAGS += -g -Wall -I$(CPP_MODS) -Wno-switch
CFLAGS += -g -O2 -Wall -I$(CPP_MODS) -Wno-switch
#CFLAGS += -O2
SRCDIR := src/
#LDFLAGS += -pg
Expand Down Expand Up @@ -44,7 +44,7 @@ include $(CPP_MODS)/crypto/module.mk

TARGET := chipmachine
LOCAL_FILES += main.cpp ChipMachine.cpp ChipMachine_config.cpp ChipMachine_keys.cpp MusicDatabase.cpp PlaylistDatabase.cpp SearchIndex.cpp MusicPlayerList.cpp MusicPlayer.cpp TelnetInterface.cpp
LOCAL_FILES += state_machine.cpp
LOCAL_FILES += renderable.cpp renderset.cpp state_machine.cpp
LIBS += -lz

include $(CPP_MODS)/build.mk
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@ Chipmachine binary;
* Type words separated by spaces for incremental search
* ENTER to play, *SHIFT-ENTER* to enque
* *F1* = Player screen, *F2* = Search screen
* *F6* = Next Song, *ESC* = Clear search field, *F8* = Clear playlist
* *F6* = Next Song
* *ESC* = Clear search field
* *F8* = Clear playlist
* *F7* = Toggle Favorite
* *F9* = Save playlist to server

## Configuring the application

* Start with *-f* for fullscreen
* Start with *-w* for window mode or *-d* for debug output
* Checkout `lua/screen.lua` for GUI layout

## Raspberry PI notes
Expand Down
12 changes: 9 additions & 3 deletions src/ChipMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ ChipMachine::ChipMachine() : currentScreen(0), eq(SpectrumAnalyzer::eq_slots), s
renderSet.add(toastField);
starEffect.fadeIn();

File f { ".login" };
if(f.exists())
userName = f.read();

}

Expand Down Expand Up @@ -195,6 +198,9 @@ void ChipMachine::update() {
scrollEffect.set("scrolltext", m);
}

if(currentDialog && currentDialog->getParent() == nullptr)
currentDialog = nullptr;

update_keys();

auto state = player.getState();
Expand Down Expand Up @@ -358,16 +364,16 @@ void ChipMachine::render(uint32_t delta) {
}

if(currentScreen == MAIN_SCREEN) {
mainScreen.render(screen, delta);
mainScreen.render(delta);
if(isFavorite)
screen.draw(favTexture, favPos.x, favPos.y, favPos.w, favPos.h, nullptr);
} else {
searchScreen.render(screen, delta);
searchScreen.render(delta);
songList.render();
}


renderSet.render(screen, delta);
renderSet.render(delta);

font.update_cache();
listFont.update_cache();
Expand Down
67 changes: 61 additions & 6 deletions src/ChipMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,16 @@ class LineEdit : public TextField {
cursorColor = grappix::Color::WHITE;
}

LineEdit(const grappix::Font &font, const std::string &text, float x, float y, float sc, uint32_t col) : TextField(font, text, x, y, sc, col) {
LineEdit(const grappix::Font &font, const std::string &text = "", float x = 0.F, float y = 0.F, float sc = 1.0F, uint32_t col = 0xffffffff) : TextField(font, "", x, y, sc, col) {
cursorColor = grappix::Color::WHITE;//grappix::Color(col)/2.0F;

this->text = prompt + text;
//tween::make_tween().sine().repeating().to(cursorColor, grappix::Color::WHITE).seconds(1.7);
}

void on_ok(std::function<void(const std::string&)> cb) {
onOk = cb;
}

void on_key(uint32_t key) {
if(key < 0x100)
text = text + (char)key;
Expand All @@ -66,21 +70,67 @@ class LineEdit : public TextField {
prompt = p;
}

virtual void render(grappix::RenderTarget &target, uint32_t delta) override {
TextField::render(target, delta);
virtual void render(uint32_t delta) override {
TextField::render(delta);
getWidth();
//LOGD("REC %s %d %d", text, tsize.x, tsize.y);
target.rectangle(pos.x + tsize.x + 2, pos.y + 2, 10, tsize.y - 4, cursorColor);
target->rectangle(pos.x + tsize.x + 2, pos.y + 2, 10, tsize.y - 4, cursorColor);
}
grappix::Color cursorColor;
std::function<void(const std::string&)> onOk;

std::string prompt = ">";
};

class Dialog : public Renderable {
virtual void render(grappix::RenderTarget &target, uint32_t delta) override {
public:
Dialog(std::shared_ptr<grappix::RenderTarget> target, const grappix::Font &font, const std::string &text, float scale = 1.0F) : Renderable(target), font(font), textField(font, text), lineEdit(font) {
auto size = font.get_size(text, scale);
bounds.w = size.x + 20;
bounds.h = size.y * 3;
bounds.x = (target->width() - bounds.w) / 2;
bounds.y = (target->height() - bounds.h) / 2;
textField.pos = { bounds.x + 10, bounds.y + 10 };
lineEdit.pos = { bounds.x + 10, bounds.y + size.y + 20 };
}

void on_ok(std::function<void(const std::string&)> cb) {
//lineEdit.on_ok(cb);
onOk = cb;
}

void on_key(uint32_t key) {

if(key == grappix::Window::ENTER) {
if(onOk)
onOk(lineEdit.getText());
remove();
} else {
lineEdit.on_key(key);
}
}

virtual void setTarget(std::shared_ptr<grappix::RenderTarget> target) {
textField.setTarget(target);
lineEdit.setTarget(target);
this->target = target;
}

virtual void render(uint32_t delta) override {
target->rectangle(bounds, 0x80ffffff);
textField.render(delta);
lineEdit.render(delta);
}

std::function<void(const std::string&)> onOk;

grappix::Font font;
std::string text;

grappix::Rectangle bounds;
TextField textField;
LineEdit lineEdit;

};

class ChipMachine : public grappix::VerticalList::Renderer {
Expand Down Expand Up @@ -205,13 +255,18 @@ class ChipMachine : public grappix::VerticalList::Renderer {
bool onSearchScreen;
bool onMainScreen;
bool haveSearchChars;
bool dialogOpen;

statemachine::StateMachine smac;

std::string currentPlaylistName = "Favorites";
std::string editPlaylistName;

bool playlistEdit = false;

std::shared_ptr<Dialog> currentDialog;

std::string userName;
};

}
Expand Down
40 changes: 37 additions & 3 deletions src/ChipMachine_keys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ enum ChipAction {
SELECT_PLAYLIST,
EDIT_PLAYLIST,
ADD_COMMAND_CHAR,
ADD_DIALOG_CHAR,
CANCEL_COMMAND,
LAST_ACTION
};
Expand All @@ -43,6 +44,9 @@ void ChipMachine::setup_rules() {

smac.add(Window::F5, if_equals(currentScreen, MAIN_SCREEN), PLAY_PAUSE);
smac.add("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._0123456789 ", if_true(playlistEdit), ADD_COMMAND_CHAR);
smac.add("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._0123456789 ", if_true(dialogOpen), ADD_DIALOG_CHAR);
smac.add({Window::ENTER, Window::ESCAPE}, if_true(dialogOpen), ADD_DIALOG_CHAR);

smac.add({ Window::BACKSPACE, Window::LEFT, Window::RIGHT, Window::HOME, Window::END }, if_true(playlistEdit), ADD_COMMAND_CHAR);
smac.add("abcdefghijklmnopqrstuvwxyz0123456789 ", ADD_SEARCH_CHAR);
smac.add(Window::BACKSPACE, DEL_SEARCH_CHAR);
Expand Down Expand Up @@ -95,6 +99,7 @@ void ChipMachine::update_keys() {
onMainScreen = (currentScreen == MAIN_SCREEN);
onSearchScreen = (currentScreen == SEARCH_SCREEN);
haveSearchChars = (iquery.getString().length() > 0);
dialogOpen = (currentDialog != nullptr);

bool searchUpdated = false;
auto last_selection = songList.selected();
Expand All @@ -104,10 +109,35 @@ void ChipMachine::update_keys() {
// return;

if(key == Window::F9) {
auto plist = PlaylistDatabase::getInstance().getPlaylist(currentPlaylistName);
PlayTracker::getInstance().sendList(plist.songs, plist.name);
}

if(userName == "") {
currentDialog = make_shared<Dialog>(screenptr, font, "Login with handle:");
currentDialog->on_ok([=](const string &text) {
//toast(text, 1);
PlayTracker::getInstance().login(text, [=](int rc) {
LOGD("LOGIN");
userName = text;
if(rc)
toast("Login successful", 2);
File f { ".login" };
f.write(userName);
f.close();
auto plist = PlaylistDatabase::getInstance().getPlaylist(currentPlaylistName);
PlayTracker::getInstance().sendList(plist.songs, plist.name);
});
});
renderSet.add(currentDialog);
} else {
auto plist = PlaylistDatabase::getInstance().getPlaylist(currentPlaylistName);
PlayTracker::getInstance().sendList(plist.songs, plist.name);
}
}
/*
if(key == Window::ENTER && dialogOpen) {
renderSet.remove(currentDialog);
currentDialog = nullptr;
}
*/
if(currentScreen == SEARCH_SCREEN)
songList.on_key(key);

Expand Down Expand Up @@ -157,6 +187,9 @@ void ChipMachine::update_keys() {
case ADD_COMMAND_CHAR:
commandField->on_key(action.event);
break;
case ADD_DIALOG_CHAR:
currentDialog->on_key(action.event);
break;
case CANCEL_COMMAND:
commandField->visible(false);
playlistEdit = false;
Expand Down Expand Up @@ -195,6 +228,7 @@ void ChipMachine::update_keys() {
break;
case SHOW_SEARCH:
show_search();
searchUpdated = true;
break;
case ADD_SEARCH_CHAR:
if(currentScreen == MAIN_SCREEN && action.event != ' ')
Expand Down
Empty file added src/Dialog.h
Empty file.
Empty file added src/LineEdit.h
Empty file.
26 changes: 23 additions & 3 deletions src/MusicDatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,21 @@ int MusicDatabase::search(const string &query, vector<int> &result, unsigned int
return result.size();
}

SongInfo MusicDatabase::lookup(const std::string &path) {
auto q = db.query<string, string, string, string, string, string>("SELECT title, game, composer, format, collection.url, collection.localdir FROM song, collection WHERE song.path=? AND song.collection = collection.id", path);

SongInfo song;
if(q.step()) {
string url, localdir;
tie(song.title, song.game, song.composer, song.format, url, localdir) = q.get_tuple();
song.path = localdir + path;
LOGD("LOCAL FILE: %s", song.path);
if(!File::exists(song.path))
song.path = url + path;
}
return song;
}

string MusicDatabase::getFullString(int id) const {

id++;
Expand Down Expand Up @@ -403,21 +418,26 @@ static uint8_t formatToByte(const std::string &f) {

MusicDatabase::Collection MusicDatabase::stripCollectionPath(string &path) {
vector<Collection> colls;
auto q = db.query<int, string, string>("SELECT ROWID,name,url FROM collection");
auto q = db.query<int, string, string, string>("SELECT ROWID,name,url,localdir FROM collection");
while(q.step()) {
colls.push_back(q.get<Collection>());
}
for(const auto &c : colls) {
if(startsWith(path, c.url)) {
LOGD("COMPARE %s to %s/%s", path, c.url, c.local_dir);
if(c.url != "" && startsWith(path, c.url)) {
path = path.substr(c.url.length());
return c;
}
if(c.local_dir != "" && startsWith(path, c.local_dir)) {
path = path.substr(c.local_dir.length());
return c;
}
}
return Collection();
}

MusicDatabase::Collection MusicDatabase::getCollection(int id) {
auto q = db.query<int, string, string>("SELECT ROWID,name,url FROM collection WHERE ROWID=?", id);
auto q = db.query<int, string, string, string>("SELECT ROWID,name,url,localdir FROM collection WHERE ROWID=?", id);
LOGD("ID %d", id);
if(q.step()) {
LOGD("####### FOUND");
Expand Down
5 changes: 4 additions & 1 deletion src/MusicDatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,17 @@ class MusicDatabase : public SearchProvider {
}

struct Collection {
Collection(int id = -1, const std::string &name = "", const std::string url = "") : id(id), name(name), url(url) {}
Collection(int id = -1, const std::string &name = "", const std::string url = "", const std::string local_dir = "") : id(id), name(name), url(url), local_dir(local_dir) {}
int id;
std::string name;
std::string url;
std::string local_dir;
};

Collection stripCollectionPath(std::string &path);

SongInfo lookup(const std::string &path);

Collection getCollection(int id);
Collection getCollection(const std::string &name);

Expand Down
16 changes: 14 additions & 2 deletions src/PlayTracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <coreutils/format.h>
#include <coreutils/log.h>
#include <webutils/webrpc.h>
#include <grappix/grappix.h>
#include <json/json.h>
#include <random>
#include <set>
Expand All @@ -13,7 +14,7 @@ namespace chipmachine {
//wired-height-596.appspot.com
class PlayTracker {
public:
PlayTracker() : rpc("http://localhost:8080/"), done(true) {
PlayTracker() : rpc("http://wired-height-596.appspot.com/"), done(true) {
utils::File f { ".trackid" };
if(!f.exists()) {
std::random_device rd;
Expand Down Expand Up @@ -72,7 +73,8 @@ class PlayTracker {
rpc.call("get_lists", [=](const std::string &result) {
std::vector<std::string> lists;
LOGD("GET LISTS:%s", result);
for(auto pl : JSon::parse(result)) {
JSon json = JSon::parse(result);
for(auto pl : json("lists")) {
std::string user = pl("user");
std::string name = pl("name");
lists.emplace_back((std::string)pl("name") + ":" + user);
Expand All @@ -81,6 +83,16 @@ class PlayTracker {
});
}

void login(const std::string &name, std::function<void(int)> f) {
JSon json;
json.add("uid", std::to_string(trackid));
json.add("name", name);
rpc.post("login", json.to_string(), [=](const std::string &result) {
LOGD("LOGIN: " + result);
f(0);
});
}

void getList(const std::string &name, std::function<void(const std::string&, const std::vector<std::string>&)> f) {

auto parts = utils::split(name, ":");
Expand Down
Loading

0 comments on commit a35ddf9

Please sign in to comment.