mirror of
https://github.com/tildearrow/furnace.git
synced 2025-01-03 14:11:11 +00:00
add a proper CLI
featuring skip order (left/right) and pause (space)! currently available on macOS and Linux only.
This commit is contained in:
parent
3183400019
commit
83386d082d
5 changed files with 229 additions and 15 deletions
|
@ -478,6 +478,10 @@ if (WIN32)
|
|||
list(APPEND ENGINE_SOURCES res/furnace.rc)
|
||||
endif()
|
||||
|
||||
set(CLI_SOURCES
|
||||
src/cli/cli.cpp
|
||||
)
|
||||
|
||||
set(GUI_SOURCES
|
||||
extern/imgui_patched/imgui.cpp
|
||||
extern/imgui_patched/imgui_draw.cpp
|
||||
|
@ -589,7 +593,7 @@ if (NOT WIN32)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
set(USED_SOURCES ${ENGINE_SOURCES} ${AUDIO_SOURCES} src/main.cpp)
|
||||
set(USED_SOURCES ${ENGINE_SOURCES} ${AUDIO_SOURCES} ${CLI_SOURCES} src/main.cpp)
|
||||
|
||||
if (USE_BACKWARD)
|
||||
list(APPEND USED_SOURCES src/backtrace.cpp)
|
||||
|
|
137
src/cli/cli.cpp
Normal file
137
src/cli/cli.cpp
Normal file
|
@ -0,0 +1,137 @@
|
|||
/**
|
||||
* Furnace Tracker - multi-system chiptune tracker
|
||||
* Copyright (C) 2021-2022 tildearrow and contributors
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "cli.h"
|
||||
#include "../ta-log.h"
|
||||
|
||||
bool cliQuit=false;
|
||||
|
||||
static void handleTerm(int) {
|
||||
cliQuit=true;
|
||||
}
|
||||
|
||||
void FurnaceCLI::bindEngine(DivEngine* eng) {
|
||||
e=eng;
|
||||
}
|
||||
|
||||
bool FurnaceCLI::loop() {
|
||||
bool escape=false;
|
||||
bool escapeSecondStage=false;
|
||||
while (!cliQuit) {
|
||||
unsigned char c;
|
||||
if (read(STDIN_FILENO,&c,1)<=0) continue;
|
||||
if (escape) {
|
||||
if (escapeSecondStage) {
|
||||
switch (c) {
|
||||
case 'C': // right
|
||||
e->setOrder(e->getOrder()+1);
|
||||
escape=false;
|
||||
escapeSecondStage=false;
|
||||
break;
|
||||
case 'D': // left
|
||||
e->setOrder(e->getOrder()-1);
|
||||
escape=false;
|
||||
escapeSecondStage=false;
|
||||
break;
|
||||
default:
|
||||
escape=false;
|
||||
escapeSecondStage=false;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (c) {
|
||||
case '[': case 'O':
|
||||
escapeSecondStage=true;
|
||||
break;
|
||||
default:
|
||||
escape=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (c) {
|
||||
case 0x1b: // <ESC>
|
||||
escape=true;
|
||||
break;
|
||||
case 'h': // left
|
||||
e->setOrder(e->getOrder()-1);
|
||||
break;
|
||||
case 'l': // right
|
||||
e->setOrder(e->getOrder()+1);
|
||||
break;
|
||||
case ' ':
|
||||
if (e->isHalted()) {
|
||||
e->resume();
|
||||
} else {
|
||||
e->halt();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FurnaceCLI::finish() {
|
||||
if (tcsetattr(0,TCSAFLUSH,&termpropold)!=0) {
|
||||
logE("could not set console attributes!");
|
||||
logE("you may have to run `reset` on your terminal.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// blatantly copied from tildearrow/tfmxplay
|
||||
bool FurnaceCLI::init() {
|
||||
#ifdef _WIN32
|
||||
winin=GetStdHandle(STD_INPUT_HANDLE);
|
||||
winout=GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
int termprop=0;
|
||||
int termpropi=0;
|
||||
GetConsoleMode(winout,(LPDWORD)&termprop);
|
||||
GetConsoleMode(winin,(LPDWORD)&termpropi);
|
||||
termprop|=ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
termpropi&=~ENABLE_LINE_INPUT;
|
||||
SetConsoleMode(winout,termprop);
|
||||
SetConsoleMode(winin,termpropi);
|
||||
#else
|
||||
sigemptyset(&intsa.sa_mask);
|
||||
intsa.sa_flags=0;
|
||||
intsa.sa_handler=handleTerm;
|
||||
sigaction(SIGINT,&intsa,NULL);
|
||||
|
||||
if (tcgetattr(0,&termprop)!=0) {
|
||||
logE("could not get console attributes!");
|
||||
return false;
|
||||
}
|
||||
memcpy(&termpropold,&termprop,sizeof(struct termios));
|
||||
termprop.c_lflag&=~ECHO;
|
||||
termprop.c_lflag&=~ICANON;
|
||||
if (tcsetattr(0,TCSAFLUSH,&termprop)!=0) {
|
||||
logE("could not set console attributes!");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
FurnaceCLI::FurnaceCLI():
|
||||
e(NULL) {
|
||||
}
|
55
src/cli/cli.h
Normal file
55
src/cli/cli.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* Furnace Tracker - multi-system chiptune tracker
|
||||
* Copyright (C) 2021-2022 tildearrow and contributors
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef _FUR_CLI_H
|
||||
#define _FUR_CLI_H
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#include "../engine/engine.h"
|
||||
|
||||
class FurnaceCLI {
|
||||
DivEngine* e;
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE winin;
|
||||
HANDLE winout;
|
||||
#else
|
||||
struct sigaction intsa;
|
||||
struct termios termprop;
|
||||
struct termios termpropold;
|
||||
#endif
|
||||
|
||||
public:
|
||||
void bindEngine(DivEngine* eng);
|
||||
bool loop();
|
||||
bool finish();
|
||||
bool init();
|
||||
FurnaceCLI();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -201,7 +201,7 @@ const char* formatNote(unsigned char note, unsigned char octave) {
|
|||
|
||||
int DivEngine::dispatchCmd(DivCommand c) {
|
||||
if (view==DIV_STATUS_COMMANDS) {
|
||||
printf("%8d | %d: %s(%d, %d)\n",totalTicksR,c.chan,cmdName[c.cmd],c.value,c.value2);
|
||||
if (!skipping) printf("%8d | %d: %s(%d, %d)\n",totalTicksR,c.chan,cmdName[c.cmd],c.value,c.value2);
|
||||
}
|
||||
totalCmds++;
|
||||
if (cmdStreamEnabled && cmdStream.size()<2000) {
|
||||
|
@ -771,7 +771,7 @@ void DivEngine::nextRow() {
|
|||
static char pb1[4096];
|
||||
static char pb2[4096];
|
||||
static char pb3[4096];
|
||||
if (view==DIV_STATUS_PATTERN) {
|
||||
if (view==DIV_STATUS_PATTERN && !skipping) {
|
||||
strcpy(pb1,"");
|
||||
strcpy(pb3,"");
|
||||
for (int i=0; i<chans; i++) {
|
||||
|
@ -1105,7 +1105,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
|
|||
}
|
||||
}
|
||||
|
||||
if (consoleMode && subticks<=1) fprintf(stderr,"\x1b[2K> %d:%.2d:%.2d.%.2d %.2x/%.2x:%.3d/%.3d %4dcmd/s\x1b[G",totalSeconds/3600,(totalSeconds/60)%60,totalSeconds%60,totalTicks/10000,curOrder,curSubSong->ordersLen,curRow,curSubSong->patLen,cmdsPerSecond);
|
||||
if (consoleMode && subticks<=1 && !skipping) fprintf(stderr,"\x1b[2K> %d:%.2d:%.2d.%.2d %.2x/%.2x:%.3d/%.3d %4dcmd/s\x1b[G",totalSeconds/3600,(totalSeconds/60)%60,totalSeconds%60,totalTicks/10000,curOrder,curSubSong->ordersLen,curRow,curSubSong->patLen,cmdsPerSecond);
|
||||
}
|
||||
|
||||
if (haltOn==DIV_HALT_TICK) halted=true;
|
||||
|
|
18
src/main.cpp
18
src/main.cpp
|
@ -36,6 +36,8 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "cli/cli.h"
|
||||
|
||||
#ifdef HAVE_GUI
|
||||
#include "gui/gui.h"
|
||||
#endif
|
||||
|
@ -46,6 +48,8 @@ DivEngine e;
|
|||
FurnaceGUI g;
|
||||
#endif
|
||||
|
||||
FurnaceCLI cli;
|
||||
|
||||
String outName;
|
||||
String vgmOutName;
|
||||
int loops=1;
|
||||
|
@ -465,8 +469,21 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
if (consoleMode) {
|
||||
bool cliSuccess=false;
|
||||
cli.bindEngine(&e);
|
||||
if (!cli.init()) {
|
||||
reportError("error while starting CLI!");
|
||||
} else {
|
||||
cliSuccess=true;
|
||||
}
|
||||
logI("playing...");
|
||||
e.play();
|
||||
if (cliSuccess) {
|
||||
cli.loop();
|
||||
cli.finish();
|
||||
e.quit();
|
||||
return 0;
|
||||
} else {
|
||||
#ifdef HAVE_SDL2
|
||||
SDL_Event ev;
|
||||
while (true) {
|
||||
|
@ -485,6 +502,7 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_GUI
|
||||
g.bindEngine(&e);
|
||||
|
|
Loading…
Reference in a new issue