From d11eed072c6ec4cba50eaeb58defa0ced7bfedca Mon Sep 17 00:00:00 2001 From: Jonas Minnberg Date: Thu, 31 Jul 2014 12:21:41 +0200 Subject: [PATCH] Many changes. New path handling separates data from writable stuff etc. --- .gitignore | 1 - Makefile | 27 +++--- README.md | 4 +- TODO | 17 ++++ data/rsnsets.dat | 0 data/topaz.ttf | Bin extra/cm | 3 +- extra/dpkg.control | 8 +- lua/{db.lua.orig => db.lua} | 0 lua/formats.lua.orig | 0 lua/init.lua | 95 ++++++++++++++++++++++ lua/init.lua.orig | 0 lua/{screen.lua.orig => screen.lua} | 8 +- src/ChipMachine.cpp | 41 ++++++++-- src/ChipMachine.h | 122 ++-------------------------- src/ChipMachine_config.cpp | 21 +++-- src/ChipMachine_keys.cpp | 68 +++++++--------- src/Dialog.h | 61 ++++++++++++++ src/LineEdit.h | 62 ++++++++++++++ src/MusicDatabase.cpp | 11 ++- src/MusicDatabase.h | 2 +- src/MusicPlayer.cpp | 15 ++-- src/MusicPlayerList.cpp | 4 +- src/MusicPlayerList.h | 2 +- src/PlayTracker.h | 34 -------- src/PlaylistDatabase.cpp | 5 +- src/SearchIndex.cpp | 4 + src/SongInfo.h | 4 +- src/renderable.h | 3 +- src/state_machine.h | 26 +++++- 30 files changed, 402 insertions(+), 246 deletions(-) mode change 100755 => 100644 data/rsnsets.dat mode change 100755 => 100644 data/topaz.ttf rename lua/{db.lua.orig => db.lua} (100%) delete mode 100644 lua/formats.lua.orig create mode 100644 lua/init.lua delete mode 100644 lua/init.lua.orig rename lua/{screen.lua.orig => screen.lua} (94%) diff --git a/.gitignore b/.gitignore index f4665a0..cc4a7b3 100644 --- a/.gitignore +++ b/.gitignore @@ -15,5 +15,4 @@ sc68.cfg index.dat *.sublime-* .tags* -lua/*.lua android/ diff --git a/Makefile b/Makefile index c1647c2..5ea3c71 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,8 @@ CFLAGS += -g -O2 -Wall -I$(CPP_MODS) -Wno-switch #CFLAGS += -O2 SRCDIR := src/ #LDFLAGS += -pg -USE_CCACHE := 1 -USE_CLANG := 1 +#USE_CCACHE := 1 +#USE_CLANG := 1 RUN_ARGS := -d @@ -41,6 +41,8 @@ include $(CPP_MODS)/musicplayer/plugins/UADEPlugin/module.mk include $(CPP_MODS)/crypto/module.mk +#APP_DIR := /usr/share/chipmachine +#USER_DIR := chipmachine 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 @@ -52,15 +54,16 @@ include $(CPP_MODS)/build.mk pkg: rm -rf debian-pkg/* mkdir -p debian-pkg/$(TARGET)/DEBIAN - mkdir -p debian-pkg/$(TARGET)/opt/chipmachine + mkdir -p debian-pkg/$(TARGET)/usr/share/chipmachine mkdir -p debian-pkg/$(TARGET)/usr/bin cp extra/dpkg.control debian-pkg/$(TARGET)/DEBIAN/control - cp MANUAL.md debian-pkg/$(TARGET)/opt/chipmachine - cp -a data debian-pkg/$(TARGET)/opt/chipmachine - rm -f debian-pkg/$(TARGET)/opt/chipmachine/data/*.dfield - cp -a lua debian-pkg/$(TARGET)/opt/chipmachine - rm -f debian-pkg/$(TARGET)/opt/chipmachine/lua/*~ debian-pkg/$(TARGET)/opt/chipmachine/lua/*.lua - cp chipmachine debian-pkg/$(TARGET)/opt/chipmachine - arm-linux-gnueabihf-strip debian-pkg/$(TARGET)/opt/chipmachine/chipmachine - cp extra/cm debian-pkg/$(TARGET)/usr/bin/chipmachine - (cd debian-pkg ; dpkg-deb --build $(TARGET)) + cp MANUAL.md debian-pkg/$(TARGET)/usr/share/chipmachine + cp -a data debian-pkg/$(TARGET)/usr/share/chipmachine + rm -f debian-pkg/$(TARGET)/usr/share/chipmachine/data/*.dfield + cp -a lua debian-pkg/$(TARGET)/usr/share/chipmachine + rm -f debian-pkg/$(TARGET)/usr/share/chipmachine/lua/*~ + cp chipmachine debian-pkg/$(TARGET)/usr/bin + $(PREFIX)strip debian-pkg/$(TARGET)/usr/bin/chipmachine + #cp extra/cm debian-pkg/$(TARGET)/usr/bin/chipmachine + chmod -R g-w debian-pkg + (cd debian-pkg ; fakeroot dpkg-deb --build $(TARGET)) diff --git a/README.md b/README.md index 02b2012..fd7c5a1 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ All required packages (hopefully); For UADE support; # git clone --depth 1 https://github.com/heikkiorsila/bencode-tools - # cd bencode-tools ; ./configure ; make ; sudo make-install ; cd .. + # cd bencode-tools ; ./configure ; make ; sudo make install ; cd .. # git clone --depth 1 git://zakalwe.fi/uade - # cd uade ; ./configure --prefix=/usr ; make -j8 ; sudo make-install ; cd .. + # cd uade ; ./configure --prefix=/usr ; make -j8 ; sudo make install ; cd .. Chipmachine binary; diff --git a/TODO b/TODO index e4d4671..eb3f0e0 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,21 @@ +* No STIL info when using online +* Network threads stops quitting + +application dir +cache dir +user dir + +* /usr/share/chipmachine as maindir +* ~/.chipmachine as writable dir for +_files/ +generated/ +index.dat +*.db + +lua + + Read DB into source_list.txt file Make spcsets and hvsc work online out of the box diff --git a/data/rsnsets.dat b/data/rsnsets.dat old mode 100755 new mode 100644 diff --git a/data/topaz.ttf b/data/topaz.ttf old mode 100755 new mode 100644 diff --git a/extra/cm b/extra/cm index 732c413..34298cf 100755 --- a/extra/cm +++ b/extra/cm @@ -1,3 +1,4 @@ #!/bin/sh cd /opt/chipmachine -./chipmachine +./chipmachine "$@" + diff --git a/extra/dpkg.control b/extra/dpkg.control index aeedb79..73ae170 100644 --- a/extra/dpkg.control +++ b/extra/dpkg.control @@ -1,9 +1,9 @@ Package: chipmachine -Version: 1.0-alpha1 -Section: user/extras +Version: 1.0-beta +Section: contrib/sound Priority: extra -Architecture: armhf -Depends: +Architecture: amd64 +Depends: libglfw2 Installed-Size: Maintainer: Jonas Minnberg Description: Scene/Retro Music Player diff --git a/lua/db.lua.orig b/lua/db.lua similarity index 100% rename from lua/db.lua.orig rename to lua/db.lua diff --git a/lua/formats.lua.orig b/lua/formats.lua.orig deleted file mode 100644 index e69de29..0000000 diff --git a/lua/init.lua b/lua/init.lua new file mode 100644 index 0000000..bfae178 --- /dev/null +++ b/lua/init.lua @@ -0,0 +1,95 @@ +------ +-- Lua settings +------ + +HD = false +if Config.screen_width >= 800 then + HD = true +end + +GSCALE = 1.0 + +if Config.screen_width >= 1280 then + GSCALE = 2.0 +end +-- print('HD',Config.screen_width,Config.screen_height,HD) + +X0 = 80 +Y0 = 54 +X1 = 636 +Y1 = 520 + + +if HD then +X0 = 10 +Y0 = 10 +X1 = Config.screen_width-10 +Y1 = Config.screen_height-10 +end + +background = 0x808080 +--Config.screen_height / 576 + +if true then + TEXT_COLOR = 0xffe0e080 + DIGITS_COLOR = 0xff70b050 + SEARCH_COLOR = 0xffaaaaff +else + TEXT_COLOR = 0xff000000 + DIGITS_COLOR = 0xff202080 + RESULT_COLOR = 0xff202040 + SEARCH_COLOR = 0xffffaaaa + FORMAT_COLOR = 0xffffffaa + SPECTRUM_COLOR0 = 0xff000000 + SPECTRUM_COLOR1 = 0xff404040 + Settings.background = 0x888888 + Settings.stars = 0 +end + +Settings.top_left = { X0, Y0 } +Settings.down_right = { X1, Y1 } + + +scale = 3.0 * GSCALE +Settings.main_title = { X0, Y0, scale, TEXT_COLOR } +Settings.main_composer = { X0, Y0+25*scale, scale*0.6, TEXT_COLOR } +Settings.main_format = { X0, Y0+42*scale, scale*0.25, TEXT_COLOR } + + +SY = Settings.main_format[2] + 32 * GSCALE +Settings.song_field = { X0, SY, GSCALE, DIGITS_COLOR } +Settings.time_field = { X0 + 130 * GSCALE, SY, GSCALE, DIGITS_COLOR } +Settings.length_field = { X0 + 220 * GSCALE, SY, GSCALE, DIGITS_COLOR } + +Settings.xinfo_field = { X0 - 4, SY + 35 * GSCALE, GSCALE * 0.75, 0xffffffff } + +if HD then + Settings.scroll = { Y1 - 200, 3.0, 4, "data/Bello.otf" } + Settings.spectrum = { X0, Y1, 32, 24.0, SPECTRUM_COLOR0, SPECTRUM_COLOR1 } +else + Settings.scroll = { Y1 - 100, 2.0, 4, "data/Bello.otf" } + Settings.spectrum = { X0-50, Y1+40, 26, 16.0, SPECTRUM_COLOR0, SPECTRUM_COLOR1 } +end + +x = Config.screen_width - 300 * GSCALE +y = Settings.scroll[1] - 80 * GSCALE + +scale = 1.2 * GSCALE +Settings.next_field = { x, y-14, 0.5, 0xff444477 } +Settings.next_title = { x, y, scale, TEXT_COLOR } +Settings.next_composer = { x, y+26*scale, scale*0.6, TEXT_COLOR } +Settings.next_format = { x, y+44*scale, scale*0.3, TEXT_COLOR } + +scale = 80.0 +Settings.prev_title = { -3200, Y0, scale, 0 } +Settings.prev_composer = { -3200, Y0+25*scale, scale*0.6, 0 } +Settings.prev_format = { -3200, Y0+45*scale, scale*0.3, 0 } + +Settings.search_field = { X0, Y0, 1.0, SEARCH_COLOR, FORMAT_COLOR } + +Settings.result_field = { X0, Y0+30, 0.8, RESULT_COLOR } +Settings.result_lines = (Y1-Y0)/23 + +Settings.font = "data/Neutra.otf" +------ +-- print("Lua parsing done") diff --git a/lua/init.lua.orig b/lua/init.lua.orig deleted file mode 100644 index e69de29..0000000 diff --git a/lua/screen.lua.orig b/lua/screen.lua similarity index 94% rename from lua/screen.lua.orig rename to lua/screen.lua index 167ea08..c9f1cae 100644 --- a/lua/screen.lua.orig +++ b/lua/screen.lua @@ -10,7 +10,7 @@ end GSCALE = 1.0 -if SCREEN_WIDTH >= 1280 then +if SCREEN_HEIGHT >= 800 then GSCALE = 2.0 end -- print('HD',SCREEN_WIDTH,SCREEN_HEIGHT,HD) @@ -68,6 +68,9 @@ Settings.length_field = { X0 + 220 * GSCALE, SY, GSCALE, DIGITS_COLOR } Settings.xinfo_field = { X0 - 4, SY + 35 * GSCALE, GSCALE * 0.75, 0xffffffff } +Settings.favicon = { X0 + 330 * GSCALE, SY - GSCALE*25, 8*8 * GSCALE, 8*6 * GSCALE } + + if HD then Settings.scroll = { Y1 - 200, 3.0, 4, "data/Bello.otf" } Settings.spectrum = { X0, Y1, 32, 24.0, SPECTRUM_COLOR0, SPECTRUM_COLOR1 } @@ -86,8 +89,7 @@ Settings.next_title = { x, y, scale, TEXT_COLOR } Settings.next_composer = { x, y+26*scale, scale*0.6, TEXT_COLOR } Settings.next_format = { x, y+44*scale, scale*0.3, TEXT_COLOR } -y = Settings.scroll[1] - 100 * GSCALE -Settings.favicon = { X0, y, 16*8 * GSCALE, 16*6 * GSCALE } +y = Settings.scroll[1] - 70 * GSCALE scale = 80.0 Settings.exit_title = { -3200, Y0, scale, 0 } diff --git a/src/ChipMachine.cpp b/src/ChipMachine.cpp index 134c737..46d9d7a 100644 --- a/src/ChipMachine.cpp +++ b/src/ChipMachine.cpp @@ -35,6 +35,14 @@ const vector heart = { 0,Z,Z,0,Z,Z,0,0, 0,Z,Z,Z,Z,Z,0,0, 0,0,Z,Z,Z,0,0,0, 0,0,0,Z,0,0,0,0 }; + +#undef Z +#define Z 0xff44cccc +const vector net = { 0,0,Z,Z,Z,0,0,0, + 0,0,Z,0,Z,0,0,0, + Z,Z,Z,0,Z,0,Z,Z, + 0,0,0,0,Z,0,Z,0, + 0,0,0,0,Z,Z,Z,0 }; #undef Z @@ -42,6 +50,12 @@ ChipMachine::ChipMachine() : currentScreen(0), eq(SpectrumAnalyzer::eq_slots), s PlaylistDatabase::getInstance(); + auto path = current_exe_path() + ":" + File::getAppDir(); + LOGD("####### Finding font"); + File ff = File::findFile(path, "data/Bello.otf"); + scrollEffect.set("font", ff.getName()); + + #ifdef ENABLE_TELNET telnet = make_unique(*this); telnet->start(); @@ -73,6 +87,12 @@ ChipMachine::ChipMachine() : currentScreen(0), eq(SpectrumAnalyzer::eq_slots), s glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + bm = image::bitmap(8, 5, &net[0]); + netTexture = Texture(bm); + glBindTexture(GL_TEXTURE_2D, netTexture.id()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + // SEARCHSCREEN iquery = MusicDatabase::getInstance().createQuery(); @@ -132,13 +152,16 @@ void ChipMachine::initLua() { setVariable(name, index, val); }); - File f { "lua/db.lua" }; + auto path = File::getUserDir() + ":" + current_exe_path() + ":" + File::getAppDir(); + File f = File::findFile(path, "lua/db.lua"); + + /*{ "lua/db.lua" }; if(!f.exists()) { f.copyFrom("lua/db.lua.orig"); f.close(); - } + }*/ - lua.loadFile("lua/db.lua"); + lua.loadFile(f.getName()); lua.load(R"( for a,b in pairs(DB) do if type(b) == 'table' then @@ -152,16 +175,17 @@ void ChipMachine::initLua() { )"); MusicDatabase::getInstance().generateIndex(); - File f2 { "lua/screen.lua" }; + File f2 = File::findFile(path, "lua/screen.lua"); + /*File f2 { "lua/screen.lua" }; if(!f2.exists()) { f2.copyFrom("lua/screen.lua.orig"); f2.close(); - } + }*/ lua.set_global("SCREEN_WIDTH", screen.width()); lua.set_global("SCREEN_HEIGHT", screen.height()); - Resources::getInstance().load("lua/screen.lua", [=](shared_ptr contents) { + Resources::getInstance().load(f2.getName() /*"lua/screen.lua" */, [=](shared_ptr contents) { lua.load(*contents, "lua/screen.lua"); lua.load(R"( for a,b in pairs(Settings) do @@ -271,7 +295,7 @@ void ChipMachine::update() { } } - auto tune = player.getTune(); + int tune = player.getTune(); if(currentTune != tune) { songField->add = 0.0; make_tween().sine().to(songField->add, 1.0).seconds(0.5); @@ -372,6 +396,9 @@ void ChipMachine::render(uint32_t delta) { songList.render(); } + if(WebRPC::inProgress() > 0 || WebGetter::inProgress() > 0) { + screen.draw(netTexture, 2, 2, 8*3, 5*3, nullptr); + } renderSet.render(delta); diff --git a/src/ChipMachine.h b/src/ChipMachine.h index 1ff1bf8..590221e 100644 --- a/src/ChipMachine.h +++ b/src/ChipMachine.h @@ -12,6 +12,9 @@ #include "state_machine.h" #include "renderset.h" +#include "LineEdit.h" +#include "Dialog.h" + #include "../demofx/StarField.h" #include "../demofx/Scroller.h" @@ -28,111 +31,6 @@ namespace chipmachine { -class LineEdit : public TextField { -public: - LineEdit() : TextField() { - cursorColor = grappix::Color::WHITE; - } - - 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 cb) { - onOk = cb; - } - - void on_key(uint32_t key) { - if(key < 0x100) - text = text + (char)key; - else { - switch(key) { - case grappix::Window::BACKSPACE: - text = text.substr(0, text.length()-1); - break; - } - } - tsize = font.get_size(text, scale); - } - - virtual void setText(const std::string &t) override { - text = prompt + t; - tsize.x = -1; - } - - virtual std::string getText() const override { - return text.substr(prompt.length()); - } - - void setPrompt(const std::string &p) { - prompt = p; - } - - 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); - } - grappix::Color cursorColor; - std::function onOk; - - std::string prompt = ">"; -}; - -class Dialog : public Renderable { -public: - Dialog(std::shared_ptr 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 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 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 onOk; - - grappix::Font font; - std::string text; - - grappix::Rectangle bounds; - TextField textField; - LineEdit lineEdit; - -}; - class ChipMachine : public grappix::VerticalList::Renderer { public: @@ -211,12 +109,13 @@ class ChipMachine : public grappix::VerticalList::Renderer { string currentNextPath; SongInfo currentInfo; - unsigned currentTune = 0; + int currentTune = 0; tween::TweenHolder currentTween; bool lockDown = false; bool isFavorite = false; grappix::Texture favTexture; + grappix::Texture netTexture; grappix::Rectangle favPos = { 80, 300, 16*8, 16*6 }; RenderSet searchScreen; @@ -227,35 +126,24 @@ class ChipMachine : public grappix::VerticalList::Renderer { std::shared_ptrresultFieldTemplate; - int numLines = 20; tween::TweenHolder markTween; grappix::Color timeColor; - grappix::Color spectrumColor = 0xffffffff; grappix::Color spectrumColorMain = 0xff00aaee; grappix::Color spectrumColorSearch = 0xff111155; - grappix::Color markColor = 0xff00ff00; grappix::Color hilightColor = 0xffffffff; - //grappix::Color searchColor = 0xffffffff; - //grappix::Color formatColor = 0xffcccc66; - IncrementalQuery iquery; grappix::VerticalList songList; - bool switchedToMain = false; - std::vector playlists; - bool onSearchScreen; - bool onMainScreen; bool haveSearchChars; - bool dialogOpen; statemachine::StateMachine smac; diff --git a/src/ChipMachine_config.cpp b/src/ChipMachine_config.cpp index 36320af..09fe700 100644 --- a/src/ChipMachine_config.cpp +++ b/src/ChipMachine_config.cpp @@ -32,6 +32,8 @@ void ChipMachine::setVariable(const std::string &name, int index, const std::str { "result_field", resultFieldTemplate.get() }, }; + auto path = current_exe_path() + ":" + File::getAppDir(); + if(fields.count(name) > 0) { auto &f = (*fields[name]); if(index >= 4) { @@ -73,8 +75,11 @@ void ChipMachine::setVariable(const std::string &name, int index, const std::str spectrumColorSearch = Color(stoll(val)); } else if(name == "font") { - if(File::exists(val)) { - font = Font(val, 48, 512 | Font::DISTANCE_MAP); + + File fontFile = File::findFile(path, val); + + if(fontFile.exists()) { + font = Font(fontFile.getName(), 48, 512 | Font::DISTANCE_MAP); for(auto &f : fields) { f.second->setFont(font); } @@ -83,8 +88,10 @@ void ChipMachine::setVariable(const std::string &name, int index, const std::str } } else if(name == "list_font") { - if(File::exists(val)) { - listFont = Font(val, 32, 256);// | Font::DISTANCE_MAP); + File fontFile = File::findFile(path, val); + + if(fontFile.exists()) { + listFont = Font(fontFile.getName(), 32, 256);// | Font::DISTANCE_MAP); resultFieldTemplate->setFont(listFont); } } else @@ -117,7 +124,11 @@ void ChipMachine::setVariable(const std::string &name, int index, const std::str scrollEffect.scrollspeed = stol(val); break; case 4: - scrollEffect.set("font", val); + { + File fontFile = File::findFile(path, val); + if(fontFile.exists()) + scrollEffect.set("font", fontFile.getName()); + } break; } LOGD("%d %f %d", scrollEffect.scrolly, scrollEffect.scrollsize, scrollEffect.scrollspeed); diff --git a/src/ChipMachine_keys.cpp b/src/ChipMachine_keys.cpp index 07154b3..2dd3a64 100644 --- a/src/ChipMachine_keys.cpp +++ b/src/ChipMachine_keys.cpp @@ -29,6 +29,8 @@ enum ChipAction { ADD_COMMAND_CHAR, ADD_DIALOG_CHAR, CANCEL_COMMAND, + SEND_PLAYLIST, + LOGIN, LAST_ACTION }; @@ -42,10 +44,10 @@ void ChipMachine::setup_rules() { smac.add(Window::F1, if_equals(currentScreen, SEARCH_SCREEN), SHOW_MAIN); smac.add({ Window::F2, Window::UP, Window::DOWN, Window::PAGEUP, Window::PAGEDOWN }, SHOW_SEARCH); - smac.add(Window::F5, if_equals(currentScreen, MAIN_SCREEN), PLAY_PAUSE); + smac.add(Window::F5, 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("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._0123456789 ", if_not_null(currentDialog), ADD_DIALOG_CHAR); + smac.add({Window::ENTER, Window::ESCAPE, Window::BACKSPACE}, if_not_null(currentDialog), 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); @@ -64,6 +66,7 @@ void ChipMachine::setup_rules() { smac.add(Window::F7, if_equals(currentScreen, SEARCH_SCREEN), ADD_LIST_FAVORITE); smac.add(Window::F7, if_equals(currentScreen, MAIN_SCREEN), ADD_CURRENT_FAVORITE); smac.add(Window::F8, CLEAR_SONGS); + smac.add(Window::F9, SEND_PLAYLIST); smac.add(Window::LEFT, PREV_SUBTUNE); smac.add(Window::RIGHT, NEXT_SUBTUNE); @@ -96,10 +99,7 @@ SongInfo ChipMachine::get_selected_song() { void ChipMachine::update_keys() { // Update some flags - onMainScreen = (currentScreen == MAIN_SCREEN); - onSearchScreen = (currentScreen == SEARCH_SCREEN); haveSearchChars = (iquery.getString().length() > 0); - dialogOpen = (currentDialog != nullptr); bool searchUpdated = false; auto last_selection = songList.selected(); @@ -108,36 +108,6 @@ void ChipMachine::update_keys() { //if(key == Window::NO_KEY) // return; - if(key == Window::F9) { - - if(userName == "") { - currentDialog = make_shared(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, [=]() { toast("Uploaded", 2); }); - }); - }); - renderSet.add(currentDialog); - } else { - auto plist = PlaylistDatabase::getInstance().getPlaylist(currentPlaylistName); - PlayTracker::getInstance().sendList(plist.songs, plist.name, [=]() { toast("Uploaded", 2); }); - } - } -/* - if(key == Window::ENTER && dialogOpen) { - renderSet.remove(currentDialog); - currentDialog = nullptr; - } -*/ if(currentScreen == SEARCH_SCREEN) songList.on_key(key); @@ -162,7 +132,7 @@ void ChipMachine::update_keys() { string name; switch((ChipAction)action.id) { case EDIT_PLAYLIST: - if(songList.selected() < playlists.size()) + if(songList.selected() < (int)playlists.size()) editPlaylistName = playlists[songList.selected()]; else editPlaylistName = ""; @@ -206,7 +176,7 @@ void ChipMachine::update_keys() { songList.select(songList.selected()+1); break; case PLAY_LIST_SONG: - if(songList.selected() < playlists.size()) { + if(songList.selected() < (int)playlists.size()) { auto name = playlists[songList.selected()]; PlaylistDatabase::getInstance().getPlaylist(name, [=](const Playlist &pl) { player.clearSongs(); @@ -269,6 +239,28 @@ void ChipMachine::update_keys() { player.clearSongs(); toast("Playlist cleared", 2); break; + case SEND_PLAYLIST: + if(userName == "") { + currentDialog = make_shared(screenptr, font, "Login with handle:"); + currentDialog->on_ok([=](const string &text) { + PlayTracker::getInstance().login(text, [=](int rc) { + 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, [=]() { toast("Uploaded", 2); }); + }); + + }); + renderSet.add(currentDialog); + } else { + auto plist = PlaylistDatabase::getInstance().getPlaylist(currentPlaylistName); + PlayTracker::getInstance().sendList(plist.songs, plist.name, [=]() { toast("Uploaded", 2); }); + } + break; } } diff --git a/src/Dialog.h b/src/Dialog.h index e69de29..a4019a4 100644 --- a/src/Dialog.h +++ b/src/Dialog.h @@ -0,0 +1,61 @@ +#ifndef DIALOG_H +#define DIALOG_H + + +#include "renderable.h" + +class Dialog : public Renderable { +public: + Dialog(std::shared_ptr 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 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 if(key == grappix::Window::ESCAPE) { + remove(); + } else { + lineEdit.on_key(key); + } + } + + virtual void setTarget(std::shared_ptr 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 onOk; + + grappix::Font font; + std::string text; + + grappix::Rectangle bounds; + TextField textField; + LineEdit lineEdit; + +}; + + +#endif // DIALOG_H diff --git a/src/LineEdit.h b/src/LineEdit.h index e69de29..19c55c3 100644 --- a/src/LineEdit.h +++ b/src/LineEdit.h @@ -0,0 +1,62 @@ +#ifndef LINE_EDIT_H +#define LINE_EDIT_H + +#include "TextField.h" + +class LineEdit : public TextField { +public: + LineEdit() : TextField() { + cursorColor = grappix::Color::WHITE; + } + + 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 cb) { + onOk = cb; + } + + void on_key(uint32_t key) { + if(key < 0x100) + text = text + (char)key; + else { + switch(key) { + case grappix::Window::BACKSPACE: + if(text.length() > prompt.length()) + text = text.substr(0, text.length()-1); + break; + } + } + tsize = font.get_size(text, scale); + } + + virtual void setText(const std::string &t) override { + text = prompt + t; + tsize.x = -1; + } + + virtual std::string getText() const override { + return text.substr(prompt.length()); + } + + void setPrompt(const std::string &p) { + prompt = p; + } + + 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); + } + grappix::Color cursorColor; + std::function onOk; + + std::string prompt = ">"; +}; + + +#endif // LINE_EDIT_H diff --git a/src/MusicDatabase.cpp b/src/MusicDatabase.cpp index 8cd23f2..506ff62 100644 --- a/src/MusicDatabase.cpp +++ b/src/MusicDatabase.cpp @@ -138,7 +138,10 @@ void MusicDatabase::initDatabase(unordered_map &vars) { auto query = db.query("INSERT INTO song (title, game, composer, format, path, collection) VALUES (?, ?, ?, ?, ?, ?)"); - File listFile(song_list); + auto path = current_exe_path() + ":" + File::getAppDir(); + File listFile = File::findFile(path, song_list); + //File listFile(song_list); + if(listFile.exists()) { bool isModland = (type == "modland"); @@ -203,7 +206,7 @@ bool MusicDatabase::parseModlandPath(SongInfo &song) { } auto parts = split(song.path, "/"); - auto l = parts.size(); + int l = parts.size(); if(l < 3) { LOGD("%s", song.path); return false; @@ -467,7 +470,7 @@ void MusicDatabase::generateIndex() { lock_guard{dbMutex}; - File f { "index.dat" }; + File f { File::getCacheDir() + "index.dat" }; if(f.exists()) { auto sz = f.read(); @@ -554,7 +557,7 @@ void MusicDatabase::generateIndex() { // p,first == composer, p.second == vector auto cindex = p.second[0]; composerTitleStart[cindex] = composerToTitle.size(); - for(int i=1; i(this->plugins), make_shared(), make_shared(), - make_shared("data/hebios.bin"), + make_shared(find_file("data/hebios.bin")), make_shared(), make_shared(), make_shared(), - make_shared("data/c64"), + make_shared(find_file("data/c64")), make_shared(), make_shared(), - make_shared("data/sc68"), + make_shared(find_file("data/sc68")), make_shared(), make_shared(), make_shared() @@ -187,11 +192,7 @@ MusicPlayer::MusicPlayer() : fifo(32786), plugins { LOGD("WTF!"); int rc = player->getSamples((int16_t*)fifo.ptr(), sz); if(rc <= 0) { - LOGD("RC %d", rc); playEnded = true; - //silentFrames = - //player = nullptr; - //break; memset(fifo.ptr(), 0, sz*2); rc = sz; } diff --git a/src/MusicPlayerList.cpp b/src/MusicPlayerList.cpp index e75f080..87e7963 100644 --- a/src/MusicPlayerList.cpp +++ b/src/MusicPlayerList.cpp @@ -9,7 +9,7 @@ using namespace utils; namespace chipmachine { -MusicPlayerList::MusicPlayerList() { +MusicPlayerList::MusicPlayerList() : webgetter(File::getCacheDir() + "_webfiles") { state = STOPPED; wasAllowed = true; permissions = 0xff; @@ -39,7 +39,7 @@ bool MusicPlayerList::addSong(const SongInfo &si, int pos) { LOGD("Add song %s %s %s", si.title, si.composer, si.format); if(pos >= 0) { - if(playList.size() >= pos) + if((int)playList.size() >= pos) playList.insert(playList.begin() + pos, si); } else { if(partyMode) { diff --git a/src/MusicPlayerList.h b/src/MusicPlayerList.h index a5b8021..d012c90 100644 --- a/src/MusicPlayerList.h +++ b/src/MusicPlayerList.h @@ -126,7 +126,7 @@ class MusicPlayerList { std::atomic files; std::string loadedFile; - WebGetter webgetter { "_files" }; + WebGetter webgetter; std::atomic state;// = STOPPED; SongInfo currentInfo; diff --git a/src/PlayTracker.h b/src/PlayTracker.h index 4bcdf6d..b3f854e 100644 --- a/src/PlayTracker.h +++ b/src/PlayTracker.h @@ -111,40 +111,6 @@ class PlayTracker { }); } - void updateList(const std::vector &songs) { - std::set lastset; - std::set currset; - utils::File f { ".last_favorites" }; - for(const SongInfo &info : songs) { - currset.insert(info.path); - } - for(const auto &line : f.getLines()) { - lastset.insert(line); - if(currset.count(line) == 0) - favorite(line, false); - } - for(const SongInfo &info : songs) { - if(lastset.count(info.path) == 0) - favorite(info.path, true); - } - f.clear(); - for(const SongInfo &info : songs) { - f.writeln(info.path); - } - } - - void favorite(const std::string &fileName, bool add) { - auto fn = fileName; - auto collection = MusicDatabase::getInstance().stripCollectionPath(fn); - - LOGD("FAV %s %s", collection.name, fn); - done = false; - rpc.post(add ? "add_favorite" : "del_favorite", utils::format("{ \"id\" : \"%x\", \"path\" : \"%s\", \"collection\" : \"%s\" }", trackid, fn, collection.name), [=](const std::string &result) { - LOGD("favDone"); - done = true; - }); - } - static PlayTracker& getInstance() { static PlayTracker tracker; return tracker; diff --git a/src/PlaylistDatabase.cpp b/src/PlaylistDatabase.cpp index 0d0d69e..4253ecc 100644 --- a/src/PlaylistDatabase.cpp +++ b/src/PlaylistDatabase.cpp @@ -1,6 +1,7 @@ #include "PlaylistDatabase.h" #include "PlayTracker.h" #include +#include #include #include @@ -14,7 +15,7 @@ namespace chipmachine { // void PlaylistDatabase::init() { -PlaylistDatabase::PlaylistDatabase() : db("play.db") { +PlaylistDatabase::PlaylistDatabase() : db(File::getCacheDir() + "play.db") { db.exec("CREATE TABLE IF NOT EXISTS playlist (title STRING PRIMARY KEY UNIQUE)"); db.exec("CREATE TABLE IF NOT EXISTS song (playlist INT, title STRING, game STRING, composer STRING, format STRING, path STRING, collection INTEGER)"); @@ -35,7 +36,7 @@ PlaylistDatabase::PlaylistDatabase() : db("play.db") { auto q = db.query("SELECT rowid, title FROM playlist"); while(q.step()) { tie(rowid, title) = q.get_tuple(); - if(rowid > playlists.size()) + if(rowid > (int)playlists.size()) playlists.resize(rowid); playlists[rowid-1] = Playlist(title); } diff --git a/src/SearchIndex.cpp b/src/SearchIndex.cpp index 0042420..dac5d1a 100644 --- a/src/SearchIndex.cpp +++ b/src/SearchIndex.cpp @@ -132,6 +132,10 @@ void IncrementalQuery::removeLast() { query.pop_back(); if(query.size() > 0) { search(); + } else { + lastStart = -1; + newRes = true; + finalResult.clear(); } } } diff --git a/src/SongInfo.h b/src/SongInfo.h index 40d4afe..59e3fa6 100644 --- a/src/SongInfo.h +++ b/src/SongInfo.h @@ -15,8 +15,8 @@ struct SongInfo { std::string composer; std::string format; //uint32_t length = 0; - uint32_t numtunes = 0; - uint32_t starttune = 0; + int numtunes = 0; + int starttune = 0; }; diff --git a/src/renderable.h b/src/renderable.h index d76b9e1..47e789a 100644 --- a/src/renderable.h +++ b/src/renderable.h @@ -25,10 +25,9 @@ class Renderable } void remove(); - + //protected: bool is_visible = true; - //bool do_remove = false; RenderSet *parent; std::shared_ptr target; }; diff --git a/src/state_machine.h b/src/state_machine.h index 7bf5c3c..28a1a92 100644 --- a/src/state_machine.h +++ b/src/state_machine.h @@ -38,6 +38,22 @@ template class NEQCondition : public BaseCondition { T val; }; +template class SharedPtrNotNullCondition : public BaseCondition { +public: + SharedPtrNotNullCondition(const std::shared_ptr &ptr) : ptr(ptr) {} + bool check() const override { return ptr != nullptr; } +private: + const std::shared_ptr& ptr; +}; + +template class SharedPtrNullCondition : public BaseCondition { +public: + SharedPtrNullCondition(const std::shared_ptr &ptr) : ptr(ptr) {} + bool check() const override { return ptr == nullptr; } +private: + const std::shared_ptr& ptr; +}; + std::shared_ptr if_true(const bool &watch); std::shared_ptr if_false(const bool &watch); @@ -49,6 +65,14 @@ template std::shared_ptr if_not_equals(const T &watch, return std::make_shared>(watch, val); } +template std::shared_ptr if_not_null(const std::shared_ptr &ptr) { + return std::make_shared>(ptr); +} + +template std::shared_ptr if_null(const std::shared_ptr &ptr) { + return std::make_shared>(ptr); +} + extern std::shared_ptr ALWAYS_TRUE; struct Action { @@ -80,7 +104,7 @@ class StateMachine { } void add(const char *chars, std::shared_ptr c, uint32_t action, bool stop = true) { - for(int i=0; i