add midi player
This commit is contained in:
parent
bbbace7f46
commit
f8b07a32b9
6 changed files with 608 additions and 935 deletions
|
@ -14,7 +14,6 @@ import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -47,6 +46,7 @@ import client.gui.GuiConsole;
|
||||||
import client.gui.GuiInfo;
|
import client.gui.GuiInfo;
|
||||||
import client.gui.GuiLoading;
|
import client.gui.GuiLoading;
|
||||||
import client.gui.GuiMenu;
|
import client.gui.GuiMenu;
|
||||||
|
import client.gui.GuiPlayer;
|
||||||
import client.gui.GuiServer;
|
import client.gui.GuiServer;
|
||||||
import client.gui.Style;
|
import client.gui.Style;
|
||||||
import client.gui.character.GuiChar;
|
import client.gui.character.GuiChar;
|
||||||
|
@ -634,25 +634,25 @@ public class Client implements IThreadListener {
|
||||||
private int soundFrameSize = 32;
|
private int soundFrameSize = 32;
|
||||||
|
|
||||||
@Variable(name = "mid_dont_fade", category = CVarCategory.SOUND, display = "Nicht ausklingen")
|
@Variable(name = "mid_dont_fade", category = CVarCategory.SOUND, display = "Nicht ausklingen")
|
||||||
private boolean midiNoWait = false;
|
public boolean midiNoWait = false;
|
||||||
@Variable(name = "mid_opl_voices", category = CVarCategory.SOUND, min = 4, max = 192, display = "OPL-Stimmen")
|
@Variable(name = "mid_opl_voices", category = CVarCategory.SOUND, min = 4, max = 192, display = "OPL-Stimmen")
|
||||||
private int midiVoices = 64;
|
public int midiVoices = 64;
|
||||||
@Variable(name = "mid_keep_notes", category = CVarCategory.SOUND, display = "Stimmen behalten")
|
@Variable(name = "mid_keep_notes", category = CVarCategory.SOUND, display = "Stimmen behalten")
|
||||||
private boolean midiKeep = false;
|
public boolean midiKeep = false;
|
||||||
@Variable(name = "mid_play_unknown", category = CVarCategory.SOUND, display = "Unbekannte Banken")
|
@Variable(name = "mid_play_unknown", category = CVarCategory.SOUND, display = "Unbekannte Banken")
|
||||||
private boolean midiUnknown = true;
|
public boolean midiUnknown = true;
|
||||||
// STR(MID_VELO_LOG, "", "Log.+Minimum [m+nlog(x)]")
|
// STR(MID_VELO_LOG, "", "Log.+Minimum [m+nlog(x)]")
|
||||||
// STR(MID_VELO_ATTN, "", "Log. Gedämpft [nlog(x)]")
|
// STR(MID_VELO_ATTN, "", "Log. Gedämpft [nlog(x)]")
|
||||||
// STR(MID_VELO_LIN, "", "Linear [x]")
|
// STR(MID_VELO_LIN, "", "Linear [x]")
|
||||||
// STR(MID_VELO_ONE, "", "Vollklang [1]")
|
// STR(MID_VELO_ONE, "", "Vollklang [1]")
|
||||||
@Variable(name = "mid_velocity_func", category = CVarCategory.SOUND, min = -128, max = 127, display = "Anschlag")
|
@Variable(name = "mid_velocity_func", category = CVarCategory.SOUND, min = -128, max = 127, display = "Anschlag")
|
||||||
private int midiVelocity = 1;
|
public int midiVelocity = 1;
|
||||||
@Variable(name = "mid_opl_bank", category = CVarCategory.SOUND, display = "Bank")
|
@Variable(name = "mid_opl_bank", category = CVarCategory.SOUND, display = "Bank")
|
||||||
private MidiBank midiBank = MidiBank.DMX_DMX;
|
public MidiBank midiBank = MidiBank.DMX_DMX;
|
||||||
@Variable(name = "mid_debug_events", category = CVarCategory.SOUND, display = "MIDI-Debug", callback = MidiDebugFunction.class)
|
@Variable(name = "mid_debug_events", category = CVarCategory.SOUND, display = "MIDI-Debug", callback = MidiDebugFunction.class)
|
||||||
private boolean midiDebug = false;
|
public boolean midiDebug = false;
|
||||||
@Variable(name = "mid_visualizer", category = CVarCategory.SOUND, display = "Visualisation")
|
@Variable(name = "mid_visualizer", category = CVarCategory.SOUND, display = "Visualisation")
|
||||||
private boolean midiVisualizer = true;
|
public boolean midiVisualizer = true;
|
||||||
|
|
||||||
public static final Client CLIENT = new Client();
|
public static final Client CLIENT = new Client();
|
||||||
|
|
||||||
|
@ -1025,6 +1025,7 @@ public class Client implements IThreadListener {
|
||||||
this.world.updateEntities();
|
this.world.updateEntities();
|
||||||
}
|
}
|
||||||
this.soundManager.update();
|
this.soundManager.update();
|
||||||
|
GuiPlayer.INSTANCE.updatePlayer();
|
||||||
if (this.world != null)
|
if (this.world != null)
|
||||||
{
|
{
|
||||||
this.tickWorld();
|
this.tickWorld();
|
||||||
|
@ -3451,37 +3452,6 @@ public class Client implements IThreadListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playMidi(File file) {
|
|
||||||
byte[] data;
|
|
||||||
try {
|
|
||||||
data = Files.readAllBytes(file.toPath());
|
|
||||||
}
|
|
||||||
catch(Throwable e) {
|
|
||||||
Log.SOUND.error(e, "Konnte Datei '%s' nicht laden", file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MidiDecoder midi;
|
|
||||||
try {
|
|
||||||
midi = new MidiDecoder(data, this.midiNoWait, this.midiVoices, this.midiBank, this.midiKeep, this.midiUnknown, this.midiVelocity);
|
|
||||||
}
|
|
||||||
catch(Throwable e) {
|
|
||||||
Log.SOUND.error(e, "Konnte MIDI '%s' nicht laden", file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
midi.setDebug(this.midiDebug);
|
|
||||||
this.audio.alMidi(midi);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMidi(int start) {
|
|
||||||
MidiDecoder midi = new MidiDecoder(this.midiVoices, this.midiBank, this.midiKeep, this.midiUnknown, this.midiVelocity, start);
|
|
||||||
midi.setDebug(this.midiDebug);
|
|
||||||
this.audio.alMidi(midi);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopMidi() {
|
|
||||||
this.audio.alMidi(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void displayTick(int posX, int posY, int posZ) {
|
private void displayTick(int posX, int posY, int posZ) {
|
||||||
int range = 16;
|
int range = 16;
|
||||||
Random rand = new Random();
|
Random rand = new Random();
|
||||||
|
|
|
@ -58,849 +58,6 @@ public class AudioInterface implements Runnable {
|
||||||
|
|
||||||
private MidiDecoder mid;
|
private MidiDecoder mid;
|
||||||
|
|
||||||
/*
|
|
||||||
STR(OPL_CHANNEL, "", "Kanal")
|
|
||||||
STR(OPL_MODULATOR, "", "Operator 1 + 3 / Modulator")
|
|
||||||
STR(OPL_CARRIER, "", "Operator 2 + 4 / Träger")
|
|
||||||
STR(OPL_POINTER, "", "Stimmen-Zeiger")
|
|
||||||
STR(OPL_OUTPUT, "", "Pegel")
|
|
||||||
STR(OPL_MODE, "", "Modus/Al.")
|
|
||||||
STR(OPL_FEEDBACK, "", "Feedback")
|
|
||||||
STR(OPL_FREQUENCY, "", "Frequenz")
|
|
||||||
STR(OPL_FLAGS, "", "T-V-S-K")
|
|
||||||
STR(OPL_MULTIPLIER, "", "Frq.-Mult.")
|
|
||||||
STR(OPL_LEVEL, "", "Op.-Pegel")
|
|
||||||
STR(OPL_KEYSCALE, "", "Tst.-Skale")
|
|
||||||
STR(OPL_WAVEFORM, "", "Wellenf.")
|
|
||||||
STR(OPL_ATTACK, "", "Attack")
|
|
||||||
STR(OPL_DECAY, "", "Decay")
|
|
||||||
STR(OPL_SUSTAIN, "", "Sustain")
|
|
||||||
STR(OPL_RELEASE, "", "Release")
|
|
||||||
STR(OPL_ENVELOPE, "", "Hüllkurve")
|
|
||||||
STR(OPL_TICK, "", "Tick/Pos.")
|
|
||||||
STR(OPL_ACTIVE, "", "Aktiv")
|
|
||||||
STR(OPL_TEMPO, "", "Tempo BPM")
|
|
||||||
|
|
||||||
STR(MID_PLAY, "s", "Spiele MIDI '$1'")
|
|
||||||
STR(CMD_PLAY_QUEUED, "d", "$1 MIDIs werden abgespielt")
|
|
||||||
STR(CMD_PLAY_STOPPED, "", "Wiedergabe ist angehalten")
|
|
||||||
STR(CMD_PLAY_PLAYING, "d", "$1 MIDIs sind in der Liste")
|
|
||||||
STR(CMD_PLAY_ENDED, "", "Wiedergabe gestoppt")
|
|
||||||
STR(CMD_PLAY_BANKID, "d", "Bank-ID: $1")
|
|
||||||
|
|
||||||
STR(PLR_MODE_NORM, "", "Normal")
|
|
||||||
STR(PLR_MODE_REPEAT, "", "Wiederholen")
|
|
||||||
STR(PLR_MODE_LOOP, "", "Schleife")
|
|
||||||
STR(PLR_MODE_RAND, "", "Zufällig")
|
|
||||||
STR(PLR_START, "", "Start")
|
|
||||||
STR(PLR_STOP, "", "Stop")
|
|
||||||
STR(PLR_PAUSE, "", "Pause")
|
|
||||||
STR(PLR_MODE, "", "Modus")
|
|
||||||
STR(PLR_PREV, "", "Vorheriger")
|
|
||||||
STR(PLR_NEXT, "", "Nächster")
|
|
||||||
STR(PLR_RANDOM, "", "Zufälliger")
|
|
||||||
STR(PLR_JUMP, "", "Springe zu")
|
|
||||||
STR(PLR_INFO, "", "Titelinfo")
|
|
||||||
STR(PLR_KARAOKE, "", "Karaoke-Texte")
|
|
||||||
|
|
||||||
STR(TITLE_PLAYER, "", "MIDI-Player")
|
|
||||||
|
|
||||||
STR(TITLE_MIDI, "", "Optionen für MIDI-Wiedergabe")
|
|
||||||
STR(TITLE_PLR_FULL, "", "SKC OPL MIDI Player v 0.0.1 (~ Sen)")
|
|
||||||
|
|
||||||
#define STR_IMID_TITLE "Titel"
|
|
||||||
#define STR_IMID_INFO "Info"
|
|
||||||
#define STR_IMID_COPY "Hinweis"
|
|
||||||
#define STR_IMID_WARN "Lizenz"
|
|
||||||
#define STR_IMID_LANG "Sprache"
|
|
||||||
#define STR_IMID_VER "Version"
|
|
||||||
|
|
||||||
|
|
||||||
#define SYM_PLAY "\U00100000"
|
|
||||||
#define SYM_STOP "\U00100001"
|
|
||||||
#define SYM_PAUSE "\U00100002"
|
|
||||||
#define SYM_NEXT "\U00100003"
|
|
||||||
#define SYM_PREV "\U00100004"
|
|
||||||
#define SYM_FFORWARD "\U00100005"
|
|
||||||
#define SYM_FREVERSE "\U00100006"
|
|
||||||
#define SYM_CONTINUOS "\U00100007"
|
|
||||||
#define SYM_REPEAT "\U00100008"
|
|
||||||
#define SYM_LOOPED "\U00100009"
|
|
||||||
#define SYM_SHUFFLE "\U0010000a"
|
|
||||||
#define SYM_PRANDOM "\U0010000b"
|
|
||||||
#define SYM_JUMPTO "\U0010000c"
|
|
||||||
#define SYM_FOLDER "\U0010000d"
|
|
||||||
#define SYM_DELETE "\U0010000e"
|
|
||||||
#define SYM_SAVEDISK "\U0010000f"
|
|
||||||
|
|
||||||
|
|
||||||
#define SND_INFO 64
|
|
||||||
#define SND_KAR 72
|
|
||||||
#define SND_KLOG 5
|
|
||||||
|
|
||||||
#define BNK_IDX_MELO_ONLY 25
|
|
||||||
#define BNK_IDX_DRUM_ONLY 30
|
|
||||||
|
|
||||||
static const char plr_wheel[] = { '/', '-', '\\', '|'};
|
|
||||||
|
|
||||||
static const char *mid_extensions[] = {"mid", "kar", "midi"};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
window_t *player;
|
|
||||||
ulong mid_poll;
|
|
||||||
char **mid_queue;
|
|
||||||
char *mid_list;
|
|
||||||
byte mid_nowait;
|
|
||||||
byte mid_repeat;
|
|
||||||
byte mid_bank;
|
|
||||||
int mid_queued;
|
|
||||||
int mid_playpos;
|
|
||||||
int mid_prevpos;
|
|
||||||
|
|
||||||
byte mid_keep;
|
|
||||||
byte mid_unknown;
|
|
||||||
byte mid_visual;
|
|
||||||
int mid_velo;
|
|
||||||
int mid_voices;
|
|
||||||
|
|
||||||
byte mid_debug;
|
|
||||||
byte mid_karaoke;
|
|
||||||
uint mid_klog_pos;
|
|
||||||
uint mid_klog_offs;
|
|
||||||
uint mid_info_offs[6];
|
|
||||||
char mid_klogger[SND_KLOG * SND_KAR];
|
|
||||||
char mid_info[SND_INFO * 6];
|
|
||||||
} snd_t;
|
|
||||||
|
|
||||||
snd_t snd;
|
|
||||||
|
|
||||||
plr_debug(cvar_byte("mid_debug_events"));
|
|
||||||
|
|
||||||
|
|
||||||
static const char **plr_descs[] = { &STR_IMID_TITLE, &STR_IMID_INFO, &STR_IMID_COPY, &STR_IMID_WARN, &STR_IMID_LANG, &STR_IMID_VER };
|
|
||||||
|
|
||||||
byte plr_play_file(const char *midname, byte nowait) {
|
|
||||||
mid_handle mid;
|
|
||||||
uint size;
|
|
||||||
if(!(size = mid_read(&mid, midname)))
|
|
||||||
return 0;
|
|
||||||
logi(LOG_CON, STR_MID_PLAY, midname);
|
|
||||||
snd_instruct(mid.track, size, SND_CMD_LOAD, 0, (uint)mid.tracks | ((uint)mid.tpqn << 16) | ((uint)nowait << 31));
|
|
||||||
mem_free(mid.track);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_cmlog(byte empty);
|
|
||||||
|
|
||||||
byte plr_play(int pos, byte nowait) {
|
|
||||||
plr_cmlog(0);
|
|
||||||
if(pos != (snd.mid_queued - 1))
|
|
||||||
snd.mid_queue[pos+1][-1] = 0;
|
|
||||||
byte status = plr_play_file(&(snd.mid_queue[pos])[6], nowait);
|
|
||||||
if(pos != (snd.mid_queued - 1))
|
|
||||||
snd.mid_queue[pos+1][-1] = '\n';
|
|
||||||
snd.mid_queue[pos][0] = COL_GREEN[0];
|
|
||||||
if(snd.mid_prevpos >= 0)
|
|
||||||
snd.mid_queue[snd.mid_prevpos][0] = COL_NEON[0];
|
|
||||||
snd.mid_prevpos = pos;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte plr_stopped() {
|
|
||||||
return snd_query(SND_STAT_STOPPED, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// voices -- 2 ~ 192
|
|
||||||
byte plr_setup(byte voices, const char *dmxname, const char *drumname, byte keep, byte useunkn, char velofunc) {
|
|
||||||
// if(dmxname) {
|
|
||||||
bank_instr *instr = bnk_read_banks(dmxname, drumname, 0);
|
|
||||||
if(!instr)
|
|
||||||
return 0;
|
|
||||||
snd_instruct(instr, sizeof(bank_instr) * 256, SND_CMD_VOICES, 0, 0);
|
|
||||||
mem_free(instr);
|
|
||||||
// }
|
|
||||||
voices = (voices & 1) ? (voices + 1) : voices;
|
|
||||||
// snd_instruct(NULL, 0, SND_CMD_BANK, dmxname ? 31 : bank, 0);
|
|
||||||
snd_instruct(NULL, 0, SND_CMD_MKOPL, 0, (uint)voices | ((uint)((byte)(velofunc & 0xff)) << 8) | ((uint)keep << 16) | ((uint)useunkn << 17));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_debug(byte debug) {
|
|
||||||
snd_instruct(NULL, 0, SND_CMD_DEBUG, 0, debug);
|
|
||||||
snd.mid_debug = debug;
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_volume(byte channel, ushort volume) {
|
|
||||||
snd_instruct(NULL, 0, SND_CMD_VOLUME, channel, volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum repeat_type {
|
|
||||||
REPEAT_OFF,
|
|
||||||
REPEAT_SINGLE,
|
|
||||||
REPEAT_ALL,
|
|
||||||
REPEAT_SHUFFLE
|
|
||||||
};
|
|
||||||
|
|
||||||
void plr_end() {
|
|
||||||
if(snd.mid_queue) {
|
|
||||||
mem_free(snd.mid_queue);
|
|
||||||
mem_free(snd.mid_list);
|
|
||||||
}
|
|
||||||
snd.mid_queue = NULL;
|
|
||||||
snd.mid_list = NULL;
|
|
||||||
snd.mid_queued = 0;
|
|
||||||
snd_instruct(NULL, 0, SND_CMD_LOAD, 0, 0);
|
|
||||||
snd_instruct(NULL, 0, SND_CMD_MKOPL, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte plr_queue(const char *dmxname, const char *drumname, const char **files, int count) {
|
|
||||||
plr_end();
|
|
||||||
if(!plr_setup(snd.mid_voices, dmxname, drumname, snd.mid_keep, snd.mid_unknown, (char)snd.mid_velo))
|
|
||||||
return 0;
|
|
||||||
snd.mid_queue = mem_alloc(sizeof(char *) * count, MEM_FILE);
|
|
||||||
int size = 0;
|
|
||||||
for(int z = 0; z < count; z++) {
|
|
||||||
size += strlen(files[z]) + 7;
|
|
||||||
}
|
|
||||||
char *list = snd.mid_list = mem_alloc(size, MEM_FILE);
|
|
||||||
for(int z = 0; z < count; z++) {
|
|
||||||
snd.mid_queue[z] = list;
|
|
||||||
list += snprintf(list, 1024, (z == (count - 1)) ? COL_NEON "#%03d %s" : COL_NEON "#%03d %s\n", z + 1, files[z]);
|
|
||||||
}
|
|
||||||
snd.mid_queued = count;
|
|
||||||
snd.mid_playpos = -1;
|
|
||||||
snd.mid_prevpos = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_mode(byte repeat) {
|
|
||||||
snd.mid_repeat = repeat;
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_pause() {
|
|
||||||
if(!snd.mid_queue || (snd.mid_playpos == INT_MIN))
|
|
||||||
return;
|
|
||||||
if(snd.mid_playpos >= -1)
|
|
||||||
snd.mid_playpos = -(snd.mid_playpos + 3);
|
|
||||||
else
|
|
||||||
snd.mid_playpos = -(snd.mid_playpos) - 3;
|
|
||||||
if(snd.mid_playpos >= 0 || snd.mid_playpos < -2)
|
|
||||||
snd.mid_queue[(snd.mid_playpos < -1) ? (-(snd.mid_playpos) - 3) : snd.mid_playpos][0] = snd.mid_playpos < -1 ? COL_YELLOW[0] : COL_GREEN[0];
|
|
||||||
snd_instruct(NULL, 0, SND_CMD_PAUSE, 0, snd.mid_playpos < -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_stop() {
|
|
||||||
if(!snd.mid_queue)
|
|
||||||
return;
|
|
||||||
plr_cmlog(1);
|
|
||||||
snd.mid_playpos = INT_MIN;
|
|
||||||
if(snd.mid_prevpos >= 0)
|
|
||||||
snd.mid_queue[snd.mid_prevpos][0] = COL_NEON[0];
|
|
||||||
snd.mid_prevpos = -1;
|
|
||||||
snd_instruct(NULL, 0, SND_CMD_LOAD, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_resume() {
|
|
||||||
if(!snd.mid_queue)
|
|
||||||
return;
|
|
||||||
if(snd.mid_playpos == INT_MIN)
|
|
||||||
plr_play(snd.mid_playpos = 0, snd.mid_nowait);
|
|
||||||
else if(snd.mid_playpos < -1)
|
|
||||||
plr_pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_update() {
|
|
||||||
if(snd.mid_queue && (sys.tmr_current - snd.mid_poll) >= 250000ULL) {
|
|
||||||
snd.mid_poll = sys.tmr_current;
|
|
||||||
if((snd.mid_playpos >= -1) && plr_stopped()) {
|
|
||||||
if(snd.mid_playpos >= 0) {
|
|
||||||
switch(snd.mid_repeat) {
|
|
||||||
case REPEAT_OFF:
|
|
||||||
snd.mid_playpos += 1;
|
|
||||||
break;
|
|
||||||
case REPEAT_SINGLE:
|
|
||||||
break;
|
|
||||||
case REPEAT_ALL:
|
|
||||||
if((snd.mid_playpos += 1) >= snd.mid_queued)
|
|
||||||
snd.mid_playpos = 0;
|
|
||||||
break;
|
|
||||||
case REPEAT_SHUFFLE:
|
|
||||||
snd.mid_playpos = rand() % snd.mid_queued;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
snd.mid_playpos = 0;
|
|
||||||
}
|
|
||||||
if(snd.mid_playpos >= snd.mid_queued)
|
|
||||||
plr_stop();
|
|
||||||
else
|
|
||||||
plr_play(snd.mid_playpos, snd.mid_nowait);
|
|
||||||
if(snd.player && snd.player.open) {
|
|
||||||
gui_update_text(gui_get(snd.player, 1));
|
|
||||||
gui_plr_update(snd.player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_jump(int pos) {
|
|
||||||
if(!snd.mid_queue)
|
|
||||||
return;
|
|
||||||
plr_resume();
|
|
||||||
pos = CLAMP_VALUE(pos, 0, snd.mid_queued - 1);
|
|
||||||
plr_play(snd.mid_playpos = pos, snd.mid_nowait);
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_next() {
|
|
||||||
if(!snd.mid_queue)
|
|
||||||
return;
|
|
||||||
plr_resume();
|
|
||||||
if((snd.mid_playpos += 1) >= snd.mid_queued)
|
|
||||||
snd.mid_playpos = 0;
|
|
||||||
plr_play(snd.mid_playpos, snd.mid_nowait);
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_prev() {
|
|
||||||
if(!snd.mid_queue)
|
|
||||||
return;
|
|
||||||
plr_resume();
|
|
||||||
if((snd.mid_playpos -= 1) < 0)
|
|
||||||
snd.mid_playpos = snd.mid_queued - 1;
|
|
||||||
plr_play(snd.mid_playpos, snd.mid_nowait);
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_rand() {
|
|
||||||
if(!snd.mid_queue)
|
|
||||||
return;
|
|
||||||
plr_resume();
|
|
||||||
plr_play((snd.mid_playpos = rand() % snd.mid_queued), snd.mid_nowait);
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_capture(const char *wavname) {
|
|
||||||
snd_instruct(wavname, wavname ? (strlen(wavname) + 1) : 0, SND_CMD_WAVECAP, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_clog() {
|
|
||||||
snd.mid_klog_pos = 0;
|
|
||||||
snd.mid_klog_offs = 0;
|
|
||||||
for(int z = 0; z < SND_KLOG; z++) {
|
|
||||||
memset(&snd.mid_klogger[z * SND_KAR], ' ', SND_KAR - 1);
|
|
||||||
snd.mid_klogger[z * SND_KAR + (SND_KAR - 1)] = (z == (SND_KLOG - 1)) ? 0 : '\n';
|
|
||||||
}
|
|
||||||
if(snd.player && snd.player.open)
|
|
||||||
gui_update_text(gui_get(snd.player, 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_cmlog(byte empty) {
|
|
||||||
snd.mid_karaoke = 0;
|
|
||||||
for(int z = 0; z < 6; z++) {
|
|
||||||
snd.mid_info_offs[z] = empty ? 0 : sprintf(&snd.mid_info[z * SND_INFO], "%-12s: ", *(plr_descs[z]));
|
|
||||||
if(!empty) {
|
|
||||||
memset(&snd.mid_info[z * SND_INFO + snd.mid_info_offs[z]], ' ', SND_INFO - 1);
|
|
||||||
snd.mid_info[z * SND_INFO + (SND_INFO - 1)] = (z == 5) ? 0 : '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(empty)
|
|
||||||
snd.mid_info[0] = 0;
|
|
||||||
plr_clog();
|
|
||||||
if(snd.player && snd.player.open)
|
|
||||||
gui_update_text(gui_get(snd.player, 15));
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_kar() {
|
|
||||||
if(snd.mid_karaoke ^ 1) {
|
|
||||||
snd.mid_karaoke = 1;
|
|
||||||
plr_clog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_info(int type, const char *text) {
|
|
||||||
char *info = &snd.mid_info[type * SND_INFO];
|
|
||||||
int offs = snd.mid_info_offs[type];
|
|
||||||
int len = strlen(text);
|
|
||||||
int max = (SND_INFO - 1) - 14;
|
|
||||||
max -= (offs > 14) ? 2 : 0;
|
|
||||||
len = (len > (max-offs)) ? (max-offs) : len;
|
|
||||||
if(len <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(offs > 14) {
|
|
||||||
info[offs++] = ';';
|
|
||||||
info[offs++] = ' ';
|
|
||||||
}
|
|
||||||
// else {
|
|
||||||
// max = sprintf(info, "%-12s: ", *(plr_descs[type]));
|
|
||||||
// memset(info+(max + len), ' ', SND_INFO - (1 + max + len));
|
|
||||||
// offs += max;
|
|
||||||
// }
|
|
||||||
memcpy(info+offs, text, len);
|
|
||||||
offs += len;
|
|
||||||
// info[SND_INFO - 1] = (type == 5) ? 0 : '\n';
|
|
||||||
snd.mid_info_offs[type] = offs;
|
|
||||||
if(snd.player && snd.player.open)
|
|
||||||
gui_update_text(gui_get(snd.player, 15));
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_tlog(int type, const char *text) {
|
|
||||||
int slen = strlen(text);
|
|
||||||
// for(int h = 0; h < slen; h++) {
|
|
||||||
// text[h] = ((text[h] < 32) && (text[h] >= 0)) ? ((h == (slen-1)) ? 0 : '?') : text[h];
|
|
||||||
// }
|
|
||||||
if((type == 1) && (text[0] == '@')) {
|
|
||||||
// text += 1;
|
|
||||||
switch(text[1]) {
|
|
||||||
case 'T':
|
|
||||||
plr_info(0, text+2);
|
|
||||||
return;
|
|
||||||
case 'I':
|
|
||||||
plr_info(1, text+2);
|
|
||||||
return;
|
|
||||||
case 'K':
|
|
||||||
plr_info(2, text+2);
|
|
||||||
return;
|
|
||||||
case 'W':
|
|
||||||
plr_info(3, text+2);
|
|
||||||
return;
|
|
||||||
case 'L':
|
|
||||||
plr_info(4, text+2);
|
|
||||||
return;
|
|
||||||
case 'V':
|
|
||||||
plr_info(5, text+2);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// text += (text[0] == 0) ? 0 : 1;
|
|
||||||
}
|
|
||||||
else if((type == 1) && (text[0] == '%') && (text[1] == '-')) {
|
|
||||||
plr_kar();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if(type == 1) {
|
|
||||||
switch(text[0]) {
|
|
||||||
case '\\':
|
|
||||||
plr_kar();
|
|
||||||
plr_clog();
|
|
||||||
text += 1;
|
|
||||||
slen -= 1;
|
|
||||||
break;
|
|
||||||
case '/':
|
|
||||||
// mid_kar();
|
|
||||||
if(snd.mid_karaoke) {
|
|
||||||
snd.mid_klog_pos += 1;
|
|
||||||
snd.mid_klog_offs = 0;
|
|
||||||
if(snd.mid_klog_pos == SND_KLOG)
|
|
||||||
plr_clog();
|
|
||||||
text += 1;
|
|
||||||
slen -= 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(snd.mid_karaoke) {
|
|
||||||
int len;
|
|
||||||
while(slen > 0) {
|
|
||||||
len = (slen > ((SND_KAR - 1) - snd.mid_klog_offs)) ? ((SND_KAR - 1) - snd.mid_klog_offs) : slen;
|
|
||||||
if(len <= 0)
|
|
||||||
break;
|
|
||||||
memcpy(&snd.mid_klogger[snd.mid_klog_pos * SND_KAR + snd.mid_klog_offs], text, len);
|
|
||||||
snd.mid_klog_offs += len;
|
|
||||||
// snd.mid_klogger[snd.mid_klog_pos * SND_KAR + snd.mid_klog_offs] = 0;
|
|
||||||
slen -= len;
|
|
||||||
if(slen > 0) {
|
|
||||||
snd.mid_klog_pos += 1;
|
|
||||||
snd.mid_klog_offs = 0;
|
|
||||||
if(snd.mid_klog_pos == SND_KLOG)
|
|
||||||
plr_clog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(snd.player && snd.player.open)
|
|
||||||
gui_update_text(gui_get(snd.player, 16));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(snd.mid_debug || (type <= 2) || (type >= 5))
|
|
||||||
logd(LOG_CON, STR_MID_TEXT, type, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void gui_fmt_velofunc(gui_t *elem, int value) {
|
|
||||||
snprintf(elem.text, elem.capacity, "%s %d: %s", elem.format_text, value, (value ? (value == -128 ? STR_MID_VELO_ONE : (value < 0 ? STR_MID_VELO_ATTN : STR_MID_VELO_LOG)) : STR_MID_VELO_LIN));
|
|
||||||
}
|
|
||||||
|
|
||||||
byte gui_init_sound(window_t *win, int frame_x, int frame_y, byte open) {
|
|
||||||
gui_add_cvtoggle(win, 20, 360, 340, 24, STR_MID_USEUNKN, "mid_play_unknown");
|
|
||||||
gui_add_cvtoggle(win, 380, 360, 340, 24, STR_MID_KEEPNOTES, "mid_keep_notes");
|
|
||||||
gui_add_cvtoggle(win, 20, 400, 340, 24, STR_MID_DONTFADE, "mid_dont_fade");
|
|
||||||
gui_add_cvtoggle(win, 380, 400, 340, 24, STR_MID_DEBUGEVT, "mid_debug_events");
|
|
||||||
gui_add_cvslider(win, 20, 440, 340, 24, STR_MID_VELOFUNC, "mid_velocity_func").format = gui_fmt_velofunc;
|
|
||||||
gui_add_cvslider(win, 380, 440, 340, 24, STR_MID_OPVOICES, "mid_opl_voices");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void plr_mode(byte repeat);
|
|
||||||
void plr_pause();
|
|
||||||
void plr_stop();
|
|
||||||
void plr_resume();
|
|
||||||
void plr_jump(int pos);
|
|
||||||
void plr_next();
|
|
||||||
void plr_prev();
|
|
||||||
void plr_rand();
|
|
||||||
|
|
||||||
void gui_plr_update_text(window_t *win) {
|
|
||||||
gui_t *elem = gui_get(win, 17);
|
|
||||||
const char *name = "";
|
|
||||||
int pos = (snd.mid_queue && (snd.mid_playpos != INT_MIN)) ? ((snd.mid_playpos < -1) ? (-(snd.mid_playpos) - 3) : snd.mid_playpos) : -1;
|
|
||||||
if(pos >= 0) {
|
|
||||||
if(pos != (snd.mid_queued - 1))
|
|
||||||
snd.mid_queue[pos+1][-1] = 0;
|
|
||||||
if(name = strrchr(&(snd.mid_queue[pos])[6], '/'))
|
|
||||||
name += 1;
|
|
||||||
else
|
|
||||||
name = &(snd.mid_queue[pos])[6];
|
|
||||||
snprintf(elem.text, elem.capacity, "%s: %d/%d - %s", STR_PLR_INFO, pos + 1, snd.mid_queued, name);
|
|
||||||
if(pos != (snd.mid_queued - 1))
|
|
||||||
snd.mid_queue[pos+1][-1] = '\n';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
snprintf(elem.text, elem.capacity, "%s", STR_PLR_INFO);
|
|
||||||
}
|
|
||||||
gui_update_text(elem);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_plr_update(window_t *win) {
|
|
||||||
gui_t *elem = gui_get(win, 2);
|
|
||||||
snprintf(elem.text, elem.capacity, snd.mid_queue && (snd.mid_playpos >= -1) ? COL_GREEN SYM_PLAY : SYM_PLAY);
|
|
||||||
gui_update_text(elem);
|
|
||||||
elem = gui_get(win, 3);
|
|
||||||
snprintf(elem.text, elem.capacity, !snd.mid_queue || (snd.mid_playpos == INT_MIN) ? COL_RED SYM_STOP : SYM_STOP);
|
|
||||||
gui_update_text(elem);
|
|
||||||
elem = gui_get(win, 4);
|
|
||||||
snprintf(elem.text, elem.capacity, snd.mid_queue && (snd.mid_playpos != INT_MIN) && (snd.mid_playpos < -1) ? COL_YELLOW SYM_PAUSE : SYM_PAUSE);
|
|
||||||
gui_update_text(elem);
|
|
||||||
gui_plr_update_text(win);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_fnc_plr_start(gui_t *elem, int value) {
|
|
||||||
plr_resume();
|
|
||||||
gui_update_text(gui_get(elem.window, 1));
|
|
||||||
gui_plr_update(elem.window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_fnc_plr_stop(gui_t *elem, int value) {
|
|
||||||
plr_stop();
|
|
||||||
gui_update_text(gui_get(elem.window, 1));
|
|
||||||
gui_plr_update(elem.window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_fnc_plr_pause(gui_t *elem, int value) {
|
|
||||||
plr_pause();
|
|
||||||
gui_update_text(gui_get(elem.window, 1));
|
|
||||||
gui_plr_update(elem.window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_fnc_plr_mode(gui_t *elem, int value) {
|
|
||||||
plr_mode((byte)value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_fnc_plr_prev(gui_t *elem, int value) {
|
|
||||||
plr_prev();
|
|
||||||
gui_update_text(gui_get(elem.window, 1));
|
|
||||||
gui_plr_update(elem.window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_fnc_plr_next(gui_t *elem, int value) {
|
|
||||||
plr_next();
|
|
||||||
gui_update_text(gui_get(elem.window, 1));
|
|
||||||
gui_plr_update(elem.window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_fnc_plr_rand(gui_t *elem, int value) {
|
|
||||||
plr_rand();
|
|
||||||
gui_update_text(gui_get(elem.window, 1));
|
|
||||||
gui_plr_update(elem.window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_fnc_plr_clear(gui_t *elem, int value) {
|
|
||||||
plr_stop();
|
|
||||||
plr_end();
|
|
||||||
elem = gui_get(elem.window, 1);
|
|
||||||
elem.text = &elem.window.strings[GUI_STR_SIZE * elem.id];
|
|
||||||
elem.text[0] = 0;
|
|
||||||
elem.capacity = GUI_STR_SIZE;
|
|
||||||
gui_update_text(elem);
|
|
||||||
elem.sel_start = elem.sel_end = elem.sel_drag = 0;
|
|
||||||
gui_text_update_cur(elem, elem.sel_start, 1);
|
|
||||||
elem.sel_start = elem.sel_end = elem.sel_drag = -1;
|
|
||||||
gui_plr_update(elem.window);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_fnc_plr_open(gui_t *elem, int value) {
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *gui_plr_modes[] = {
|
|
||||||
SYM_CONTINUOS,
|
|
||||||
SYM_REPEAT,
|
|
||||||
SYM_LOOPED,
|
|
||||||
SYM_SHUFFLE
|
|
||||||
};
|
|
||||||
|
|
||||||
void gui_fnc_plr_jump(gui_t *elem, int value) {
|
|
||||||
if(!value && str_parse_int(elem.text, &value, -10) && value && (value <= snd.mid_queued)) {
|
|
||||||
plr_jump(value - 1);
|
|
||||||
snprintf(elem.text, elem.capacity, SYM_JUMPTO "#");
|
|
||||||
gui_update_text(elem);
|
|
||||||
gui_deselect(elem.window);
|
|
||||||
gui_text_update_cur(elem, elem.sel_start, 1);
|
|
||||||
gui_update_text(gui_get(elem.window, 1));
|
|
||||||
gui_plr_update(elem.window);
|
|
||||||
}
|
|
||||||
else if(value == 4) {
|
|
||||||
elem.text[0] = 0;
|
|
||||||
gui_update_text(elem);
|
|
||||||
gui_text_update_cur(elem, elem.sel_start, 1);
|
|
||||||
}
|
|
||||||
else if(value == -4) {
|
|
||||||
snprintf(elem.text, elem.capacity, SYM_JUMPTO "#");
|
|
||||||
gui_update_text(elem);
|
|
||||||
gui_text_update_cur(elem, elem.sel_start, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_fnc_plr_load(gui_t *elem, int value) {
|
|
||||||
if(!value) {
|
|
||||||
int count;
|
|
||||||
const char **files = file_list(&count, elem.text, mid_extensions, 3);
|
|
||||||
if(files) {
|
|
||||||
count = count > 999 ? 999 : count;
|
|
||||||
plr_queue(snd_bankfiles[snd.mid_bank], NULL, files, count);
|
|
||||||
mem_free(files);
|
|
||||||
elem.text[0] = 0;
|
|
||||||
gui_update_text(elem);
|
|
||||||
gui_deselect(elem.window);
|
|
||||||
gui_text_update_cur(elem, elem.sel_start, 1);
|
|
||||||
elem = gui_get(elem.window, 1);
|
|
||||||
elem.text = snd.mid_list;
|
|
||||||
elem.capacity = strlen(snd.mid_list) + 1;
|
|
||||||
gui_update_text(elem);
|
|
||||||
elem.sel_start = elem.sel_end = elem.sel_drag = 0;
|
|
||||||
gui_text_update_cur(elem, elem.sel_start, 1);
|
|
||||||
elem.sel_start = elem.sel_end = elem.sel_drag = -1;
|
|
||||||
gui_plr_update(elem.window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_fmt_bankdrop(gui_t *elem, int value) {
|
|
||||||
int pos = 0;
|
|
||||||
for(int z = 0; z < elem.max && pos < (elem.capacity - 1); z++) {
|
|
||||||
pos += snprintf(&elem.text[pos], elem.capacity - pos, z ? "\n%s%s" : "%s%s", ((const char **)elem.aux_data)[z], z < BNK_IDX_MELO_ONLY ? "" : (z < BNK_IDX_DRUM_ONLY ? " [0-127]" : " [128-255]"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint plr_waveforms[] = {0xff00ff00, 0xffff0000, 0xff0000ff, 0xff00ffff, 0xffff00ff, 0xffffff00, 0xff80ff00, 0xff00ff80};
|
|
||||||
|
|
||||||
int gui_render_bar(gui_t *elem, int x, int y, int w, int h, uint top, uint bottom, uint bg, int v) {
|
|
||||||
v = (v < 0) ? 0 : v;
|
|
||||||
gfx_draw_rect(elem.pos_x + x, elem.pos_y + y, w, h, 0, 0, 0xff000000 | top, 0xff000000 | bottom, 0, 0);
|
|
||||||
if(++v < h)
|
|
||||||
gfx_draw_rect(elem.pos_x + x, elem.pos_y + y, w, h - v, 0, 0, 0xff000000 | bg, 0xff000000 | bg, 0, 0);
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gui_render_grad(gui_t *elem, int x, int y, int w, int h, uint top, uint bottom) {
|
|
||||||
gfx_draw_rect(elem.pos_x + x, elem.pos_y + y, w, h, 0, 0, 0xff000000 | top, 0xff000000 | bottom, 0, 0);
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gui_render_rect(gui_t *elem, int x, int y, int w, int h, uint color) {
|
|
||||||
gfx_draw_rect(elem.pos_x + x, elem.pos_y + y, w, h, 0, 0, 0xff000000 | color, 0xff000000 | color, 0, 0);
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gui_render_text(gui_t *elem, int x, int y, uint color, const char *text) {
|
|
||||||
txt_draw(elem.pos_x + x, elem.pos_y + y, 0, sys.font.yglyph, sys.font.yglyph, elem.pos_x + x, elem.pos_y + y, elem.pos_x + elem.size_x, elem.pos_y + elem.size_y,
|
|
||||||
0xff000000 | color, 0x00000000, &sys.font, text);
|
|
||||||
return sys.font.yglyph;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_render_player(gui_t *elem, int value) {
|
|
||||||
elem.t_dirty = 1;
|
|
||||||
if(!value)
|
|
||||||
gui_render_grad(elem, 0, 0, elem.size_x, elem.size_y, sys.style.field_btm, sys.style.field_top);
|
|
||||||
if(snd.mid_visual ^ 1)
|
|
||||||
return;
|
|
||||||
pthread_mutex_lock(&sgt.lock);
|
|
||||||
if(!sgt.chip || !sgt.bank) {
|
|
||||||
pthread_mutex_unlock(&sgt.lock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
OPLChip chip = sgt.chip;
|
|
||||||
bank_handle *bank = sgt.bank;
|
|
||||||
int nch = chip.n_voices;
|
|
||||||
int bx = elem.size_x / 2 - (nch * 6 + 2) / 2;
|
|
||||||
int by = elem.size_y / 2 - (698 + 20 * 4) / 2;
|
|
||||||
int x = bx;
|
|
||||||
int y = by;
|
|
||||||
if(value) {
|
|
||||||
x = bx - 84;
|
|
||||||
sprintf(&sys.work_buf[str_time(sys.work_buf, sgt.mid_time)], "\n%c%c%c%c %c",
|
|
||||||
(sgt.mid.tpqn && (((sgt.mid_tick / sgt.mid.tpqn) & 3) == 0)) ? '*' : '.',
|
|
||||||
(sgt.mid.tpqn && (((sgt.mid_tick / sgt.mid.tpqn) & 3) == 1)) ? '*' : '.',
|
|
||||||
(sgt.mid.tpqn && (((sgt.mid_tick / sgt.mid.tpqn) & 3) == 2)) ? '*' : '.',
|
|
||||||
(sgt.mid.tpqn && (((sgt.mid_tick / sgt.mid.tpqn) & 3) == 3)) ? '*' : '.',
|
|
||||||
plr_wheel[(sgt.mid_tick >> 5) & 3]);
|
|
||||||
gui_render_text(elem, x, y + 20, 0xffffff, sys.work_buf);
|
|
||||||
sprintf(sys.work_buf, COL_NEON"%s"COL_RESET"\n%d", STR_OPL_TICK, sgt.mid_tick);
|
|
||||||
gui_render_text(elem, x, y + 60, 0xffffff, sys.work_buf);
|
|
||||||
sprintf(sys.work_buf, COL_NEON"%s"COL_RESET"\n%d / %d", STR_OPL_ACTIVE, bank.v_used, bank.voices.length);
|
|
||||||
gui_render_text(elem, x, y + 100, 0xffffff, sys.work_buf);
|
|
||||||
sprintf(sys.work_buf, COL_NEON"%s"COL_RESET"\n%d +%dQ", STR_OPL_TEMPO, sgt.mid.uspb ? (60000000 / sgt.mid.uspb) : 0, sgt.mid.tpqn);
|
|
||||||
gui_render_text(elem, x, y + 140, 0xffffff, sys.work_buf);
|
|
||||||
x = bx;
|
|
||||||
pthread_mutex_unlock(&sgt.lock);
|
|
||||||
y += 3;
|
|
||||||
gui_render_text(elem, x, y, 0xffffff, STR_OPL_CHANNEL);
|
|
||||||
gui_render_text(elem, x, y + 20 + 226, 0xffffff, STR_OPL_MODULATOR);
|
|
||||||
gui_render_text(elem, x, y + 40 + 226 + 232, 0xffffff, STR_OPL_CARRIER);
|
|
||||||
gui_render_text(elem, x, y + 60 + 226 + 232 * 2, 0xffffff, STR_OPL_POINTER);
|
|
||||||
y -= 3;
|
|
||||||
// x -= 86;
|
|
||||||
x += nch * 6 + 2 + 1;
|
|
||||||
y += 20;
|
|
||||||
gui_render_text(elem, x, y + 0, 0xffffff, STR_OPL_OUTPUT);
|
|
||||||
gui_render_text(elem, x, y + 70, 0xffffff, STR_OPL_MODE);
|
|
||||||
gui_render_text(elem, x, y + 84, 0xffffff, STR_OPL_FEEDBACK);
|
|
||||||
gui_render_text(elem, x, y + 98, 0xffffff, STR_OPL_FREQUENCY);
|
|
||||||
y += 226 + 20;
|
|
||||||
for(int o = 0; o < 2; o++) {
|
|
||||||
gui_render_text(elem, x, y + 6, 0xffffff, STR_OPL_FLAGS);
|
|
||||||
gui_render_text(elem, x, y + 24, 0xffffff, STR_OPL_MULTIPLIER);
|
|
||||||
gui_render_text(elem, x, y + 42, 0xffffff, STR_OPL_LEVEL);
|
|
||||||
gui_render_text(elem, x, y + 96, 0xffffff, STR_OPL_KEYSCALE);
|
|
||||||
gui_render_text(elem, x, y + 110, 0xffffff, STR_OPL_WAVEFORM);
|
|
||||||
gui_render_text(elem, x, y + 124, 0xffffff, STR_OPL_ATTACK);
|
|
||||||
gui_render_text(elem, x, y + 142, 0xffffff, STR_OPL_DECAY);
|
|
||||||
gui_render_text(elem, x, y + 160, 0xffffff, STR_OPL_SUSTAIN);
|
|
||||||
gui_render_text(elem, x, y + 178, 0xffffff, STR_OPL_RELEASE);
|
|
||||||
gui_render_text(elem, x, y + 196, 0xffffff, STR_OPL_ENVELOPE);
|
|
||||||
y += 232 + 20;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
y += 20;
|
|
||||||
y += gui_render_rect(elem, x, y, nch * 6 + 2, 226, 0x3f0000) + 20;
|
|
||||||
y += gui_render_rect(elem, x, y, nch * 6 + 2, 232, 0x003f00) + 20;
|
|
||||||
y += gui_render_rect(elem, x, y, nch * 6 + 2, 232, 0x00003f) + 20;
|
|
||||||
y += gui_render_rect(elem, x, y, nch * 6 + 2, 8, 0x2f2f2f);
|
|
||||||
for(int c = 0; c < nch; c++) {
|
|
||||||
OPLChannel channel = &chip.channel[c];
|
|
||||||
x = bx + 2 + 6 * c;
|
|
||||||
y = by + 2;
|
|
||||||
short **out = channel.out;
|
|
||||||
short accm = *out[0] + *out[1] + *out[2] + *out[3];
|
|
||||||
int chnlvl = 0;
|
|
||||||
for(int n = 0; n < 2; n++) {
|
|
||||||
chnlvl += (short)((accm * channel.level[n]) >> 16);
|
|
||||||
}
|
|
||||||
chnlvl = chnlvl < 0 ? (-chnlvl) : chnlvl;
|
|
||||||
chnlvl = (chnlvl * 16) / 2048;
|
|
||||||
chnlvl = chnlvl > 64 ? 64 : chnlvl;
|
|
||||||
int freq = (int)((((float)channel.f_num * 49716.0f) / powf(2.0f, 20.0f - (float)channel.block)) / 6210.0f * 128.0f);
|
|
||||||
y += 20;
|
|
||||||
y += gui_render_bar(elem, x, y, 4, 64, 0xff0000, 0x00ff00, 0x000000, chnlvl) + 2;
|
|
||||||
y += gui_render_rect(elem, x, y, 4, 4, ((channel.slots[0].eg_out <= 0x100) || (channel.slots[1].eg_out <= 0x100)) ? 0x00ff00 : 0x000000) + 2;
|
|
||||||
y += gui_render_rect(elem, x - (c & 1), y, 5, 4, channel.chtype != ch_2op ? 0xff00ff : 0x000000) + 2;
|
|
||||||
y += gui_render_grad(elem, x, y, 4, 4, channel.con ? 0x00ff00 : 0x808080, 0x0000ff) + 2;
|
|
||||||
y += gui_render_bar(elem, x, y, 4, 8, 0x00ff00, 0xffff00, 0x000000, channel.fb) + 2;
|
|
||||||
y += gui_render_bar(elem, x, y, 4, 128, 0x707070, 0x505050, 0x000000, freq) + 2;
|
|
||||||
gui_render_rect(elem, x, y - 130 + (127 - freq), 4, 1, 0xff0000);
|
|
||||||
for(int o = 0; o < 2; o++) {
|
|
||||||
opl3_slot *slot = channel.slots[o];
|
|
||||||
y += 2;
|
|
||||||
y += 20;
|
|
||||||
y += gui_render_rect(elem, x, y, 4, 4, slot.key ? 0x00ff00 : 0x000000) + 2;
|
|
||||||
y += gui_render_rect(elem, x, y, 4, 4, (slot.trem != (byte*)&slot.chip.zeromod) ? 0x5fdf00 : 0x000000);
|
|
||||||
y += gui_render_rect(elem, x, y, 4, 4, slot.reg_vib ? 0xffff00 : 0x000000);
|
|
||||||
y += gui_render_rect(elem, x, y, 4, 4, slot.reg_type ? 0xff0000 : 0x000000);
|
|
||||||
y += gui_render_rect(elem, x, y, 4, 4, slot.reg_ksr ? 0x5f00bf : 0x000000) + 2;
|
|
||||||
y += gui_render_bar(elem, x, y, 4, 16, 0xff0000, 0xffff00, 0x000000, slot.reg_mult) + 2;
|
|
||||||
y += gui_render_bar(elem, x, y, 4, 64, 0xff0000, 0x00ff00, 0x000000, 63 - slot.reg_tl) + 2;
|
|
||||||
y += gui_render_bar(elem, x, y, 4, 4, 0x7f00ff, 0x3f00ff, 0x000000, slot.reg_ksl) + 2;
|
|
||||||
y += gui_render_rect(elem, x, y, 4, 8, 0x000000) + 2;
|
|
||||||
gui_render_rect(elem, x, y - 10 + (7 - slot.reg_wf), 4, 1, plr_waveforms[slot.reg_wf]);
|
|
||||||
|
|
||||||
y += gui_render_bar(elem, x, y, 4, 16, slot.eg_gen == 0 ? 0xff0000 : 0xaf0000, slot.eg_gen == 0 ? 0x00ffff : 0x00afaf, 0x000000, slot.reg_ar) + 2;
|
|
||||||
y += gui_render_bar(elem, x, y, 4, 16, slot.eg_gen == 1 ? 0xff0000 : 0xaf0000, slot.eg_gen == 1 ? 0x00ffff : 0x00afaf, 0x000000, slot.reg_dr) + 2;
|
|
||||||
y += gui_render_bar(elem, x, y, 4, 16, slot.eg_gen == 2 ? 0xff0000 : 0xaf0000, slot.eg_gen == 2 ? 0x00ffff : 0x00afaf, 0x000000, (slot.reg_sl > 15) ? 0 : (15 - slot.reg_sl)) + 2;
|
|
||||||
y += gui_render_bar(elem, x, y, 4, 16, slot.eg_gen == 3 ? 0xff0000 : 0xaf0000, slot.eg_gen == 3 ? 0x00ffff : 0x00afaf, 0x000000, slot.reg_rr) + 2;
|
|
||||||
y += gui_render_bar(elem, x, y, 4, 32, 0xff0000, 0x0000ff, 0x000000, (0x1ff - slot.eg_rout) / 16) + 2;
|
|
||||||
}
|
|
||||||
y += 2;
|
|
||||||
y += 20;
|
|
||||||
gui_render_rect(elem, x, y, 4, 4, bank.voiceindex == c ? 0x00ffff : 0x000000);
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&sgt.lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte gui_init_player(window_t *win, int frame_x, int frame_y, byte open) {
|
|
||||||
gui_add_fill(win, 0, 0, 696, 24, STR_TITLE_PLR_FULL);
|
|
||||||
|
|
||||||
gui_add_field(win, 0, 24, 720, frame_y - 316, snd.mid_queue ? snd.mid_list : "", snd.mid_queue ? (strlen(snd.mid_list) + 1) : 0, NULL, 0, 0);
|
|
||||||
|
|
||||||
gui_add_button(win, 0, frame_y - 24, 24, 24, SYM_PLAY, gui_fnc_plr_start);
|
|
||||||
gui_add_button(win, 24, frame_y - 24, 24, 24, SYM_STOP, gui_fnc_plr_stop);
|
|
||||||
gui_add_button(win, 48, frame_y - 24, 24, 24, SYM_PAUSE, gui_fnc_plr_pause);
|
|
||||||
gui_add_enum(win, 72, frame_y - 24, 24, 24, STR_PLR_MODE, gui_fnc_plr_mode, gui_plr_modes, 4, 0, snd.mid_repeat).format = gui_fmt_enums;
|
|
||||||
|
|
||||||
gui_add_button(win, 120, frame_y - 24, 24, 24, SYM_PREV, gui_fnc_plr_prev);
|
|
||||||
gui_add_button(win, 144, frame_y - 24, 24, 24, SYM_NEXT, gui_fnc_plr_next);
|
|
||||||
gui_add_button(win, 168, frame_y - 24, 24, 24, SYM_PRANDOM, gui_fnc_plr_rand);
|
|
||||||
gui_add_field(win, 192, frame_y - 24, 48, 24, SYM_JUMPTO "#", 0, gui_fnc_plr_jump, 1, 1);
|
|
||||||
|
|
||||||
gui_add_button(win, 264, frame_y - 24, 24, 24, SYM_DELETE, gui_fnc_plr_clear);
|
|
||||||
cvar_t *cv = cvar_get("mid_opl_bank");
|
|
||||||
gui_t *elem = gui_add_dropup(win, 288, frame_y - 24, 192, 24, STR_MID_BANK, gui_fnc_cvar_bool, snd_banknames, cv.max, cv.def, cv.value);
|
|
||||||
elem.cv_data = cv;
|
|
||||||
elem = elem + 1;
|
|
||||||
elem.capacity = GUI_AUX_STR;
|
|
||||||
elem.text = win.str_aux;
|
|
||||||
elem.format = gui_fmt_bankdrop;
|
|
||||||
elem.cv_data = cv;
|
|
||||||
gui_add_field(win, 480, frame_y - 24, 216, 24, "", 0, gui_fnc_plr_load, 1, 1);
|
|
||||||
gui_add_button(win, 696, frame_y - 24, 24, 24, SYM_FOLDER, gui_fnc_plr_open);
|
|
||||||
|
|
||||||
gui_add_field(win, 0, frame_y - 268, 720, 120, snd.mid_info, 6 * SND_INFO, NULL, 0, 0);
|
|
||||||
gui_add_field(win, 0, frame_y - 124, 720, 100, snd.mid_klogger, SND_KLOG * SND_KAR, NULL, 0, 0);
|
|
||||||
|
|
||||||
gui_add_fill(win, 0, frame_y - 292, 720, 24, STR_PLR_INFO);
|
|
||||||
gui_add_fill(win, 96, frame_y - 24, 24, 24, "");
|
|
||||||
gui_add_fill(win, 240, frame_y - 24, 24, 24, "");
|
|
||||||
gui_add_fill(win, 0, frame_y - 148, 720, 24, STR_PLR_KARAOKE);
|
|
||||||
|
|
||||||
gui_add_custom(win, 720, 0, frame_x - 720, frame_y, gui_render_player);
|
|
||||||
|
|
||||||
gui_add_cvtoggle(win, 696, 0, 24, 24, "V", "mid_visualizer").format = gui_fmt_keep;
|
|
||||||
|
|
||||||
// gui_add_nbutton(win, 0, 0, 160, 24, STR_BACK, GUI_MENU);
|
|
||||||
gui_plr_update(win);
|
|
||||||
// gui_reformat();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
private void push() {
|
private void push() {
|
||||||
for(int z = 0; z < 2 * 2; z++) {
|
for(int z = 0; z < 2 * 2; z++) {
|
||||||
this.buffer[this.smppos * 2 * 2 + z] = (byte)((this.data[z >> 1] >> ((z & 1) * 8)) & 0xff);
|
this.buffer[this.smppos * 2 * 2 + z] = (byte)((this.data[z >> 1] >> ((z & 1) * 8)) & 0xff);
|
||||||
|
|
|
@ -226,13 +226,16 @@ public class MidiDecoder {
|
||||||
this.playing = true;
|
this.playing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MidiDecoder(int voices, MidiBank bank, boolean keep, boolean useunkn, int velofunc, int start) {
|
public MidiDecoder(MidiBank bank, int start, int end, int delay, int note) {
|
||||||
this.tracks = null;
|
this.tracks = null;
|
||||||
this.tpqn = 0;
|
this.tpqn = note;
|
||||||
this.nowait = false;
|
this.nowait = false;
|
||||||
this.chip = new OPLChip(48000, voices, velofunc, 0, false, false);
|
this.chip = new OPLChip(48000, 16, 0, 0, false, false);
|
||||||
this.bank = new MidiHandle(this.chip, bank.getData(), keep, useunkn);
|
this.bank = new MidiHandle(this.chip, bank.getData(), false, true);
|
||||||
this.ticktime = start;
|
this.ticktime = start;
|
||||||
|
this.uspb = end;
|
||||||
|
this.time = (long)delay * 1000000L;
|
||||||
|
this.debug = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTempo(int tempo) {
|
private void setTempo(int tempo) {
|
||||||
|
@ -488,16 +491,17 @@ public class MidiDecoder {
|
||||||
|
|
||||||
public long process() {
|
public long process() {
|
||||||
if(this.tracks == null) {
|
if(this.tracks == null) {
|
||||||
this.bank.progchange(0, this.ticktime < 128 ? this.ticktime : 0);
|
int pos = this.ticktime + (this.tick % (this.uspb + 1 - this.ticktime));
|
||||||
|
this.bank.progchange(0, pos < 128 ? pos : 0);
|
||||||
this.bank.progchange(9, 0);
|
this.bank.progchange(9, 0);
|
||||||
Log.SOUND.user("MIDI-Test %s%d", this.ticktime < 128 ? "#" : "P", this.ticktime < 128 ? this.ticktime : this.ticktime - 128);
|
Log.SOUND.user("MIDI-Test %s%d", pos < 128 ? "#" : "P", pos < 128 ? pos : pos - 128);
|
||||||
this.bank.noteon(this.ticktime < 128 ? 0 : 9, this.ticktime < 128 ? 36 : this.ticktime - 128, 127);
|
this.bank.noteon(pos < 128 ? 0 : 9, pos < 128 ? this.tpqn : pos - 128, 127);
|
||||||
this.ticktime++;
|
pos++;
|
||||||
if(this.ticktime == 128)
|
if(pos == 128)
|
||||||
this.ticktime = 128 + 35;
|
pos = 128 + 35;
|
||||||
else if(this.ticktime == 128 + 82)
|
else if(pos == 128 + 82)
|
||||||
this.ticktime = 0;
|
pos = 0;
|
||||||
return 500000000L;
|
return this.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.playing && (this.nowait || !this.chip.isPlaying())) {
|
if(!this.playing && (this.nowait || !this.chip.isPlaying())) {
|
||||||
|
@ -515,6 +519,7 @@ public class MidiDecoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDebug(boolean debug) {
|
public void setDebug(boolean debug) {
|
||||||
|
if(this.tracks != null)
|
||||||
this.debug = debug;
|
this.debug = debug;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package client.gui;
|
package client.gui;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import client.Client;
|
import client.Client;
|
||||||
import client.Client.FileMode;
|
|
||||||
import client.gui.character.GuiChar;
|
import client.gui.character.GuiChar;
|
||||||
import client.gui.character.GuiCharacters;
|
import client.gui.character.GuiCharacters;
|
||||||
import client.gui.element.ActButton;
|
import client.gui.element.ActButton;
|
||||||
|
@ -78,8 +75,9 @@ public class GuiMenu extends Gui {
|
||||||
GuiMenu.this.gm.show(GuiServer.INSTANCE);
|
GuiMenu.this.gm.show(GuiServer.INSTANCE);
|
||||||
}
|
}
|
||||||
}, "Schnellverbindung"));
|
}, "Schnellverbindung"));
|
||||||
this.add(new NavButton(0, 40, 180, 0, GuiOptions.getPage(), "Einstellungen"));
|
this.add(new NavButton(0, 40, 180, 0, GuiPlayer.INSTANCE, "MIDI-Player"));
|
||||||
this.infoButton = this.add(new ActButton(0, 60, 180, 0, new ButtonCallback() {
|
this.add(new NavButton(0, 60, 180, 0, GuiOptions.getPage(), "Einstellungen"));
|
||||||
|
this.infoButton = this.add(new ActButton(0, 80, 180, 0, new ButtonCallback() {
|
||||||
public void use(ActButton elem, PressType action) {
|
public void use(ActButton elem, PressType action) {
|
||||||
GuiMenu.this.gm.show(GuiMenu.this.hacked == 10 ? GuiInfo.HAX : GuiInfo.INSTANCE);
|
GuiMenu.this.gm.show(GuiMenu.this.hacked == 10 ? GuiInfo.HAX : GuiInfo.INSTANCE);
|
||||||
}
|
}
|
||||||
|
@ -102,30 +100,11 @@ public class GuiMenu extends Gui {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.add(new ActButton(0, 90, 180, 0, new ButtonCallback() {
|
this.add(new ActButton(0, 110, 180, 0, new ButtonCallback() {
|
||||||
public void use(ActButton elem, PressType action) {
|
public void use(ActButton elem, PressType action) {
|
||||||
GuiMenu.this.gm.interrupted = true;
|
GuiMenu.this.gm.interrupted = true;
|
||||||
}
|
}
|
||||||
}, "Client schließen"));
|
}, "Client schließen"));
|
||||||
this.add(new ActButton(0, 110, 180, 0, new ButtonCallback() {
|
|
||||||
public void use(ActButton elem, PressType action) {
|
|
||||||
GuiMenu.this.gm.showFileDialog(FileMode.FILE_LOAD, "MIDI laden", null, new FileCallback() {
|
|
||||||
public void selected(File file) {
|
|
||||||
GuiMenu.this.gm.playMidi(file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, "MIDI-Player"));
|
|
||||||
this.add(new ActButton(0, 130, 180, 0, new ButtonCallback() {
|
|
||||||
public void use(ActButton elem, PressType action) {
|
|
||||||
GuiMenu.this.gm.testMidi(0);
|
|
||||||
}
|
|
||||||
}, "MIDI-Bank testen"));
|
|
||||||
this.add(new ActButton(0, 150, 180, 0, new ButtonCallback() {
|
|
||||||
public void use(ActButton elem, PressType action) {
|
|
||||||
GuiMenu.this.gm.stopMidi();
|
|
||||||
}
|
|
||||||
}, "MIDI stoppen"));
|
|
||||||
this.shift();
|
this.shift();
|
||||||
this.add(new Label(4, 4, 200, 0, Color.VIOLET + Client.VERSION, true));
|
this.add(new Label(4, 4, 200, 0, Color.VIOLET + Client.VERSION, true));
|
||||||
this.splashLabel = this.add(new Label(0, 100, width, 0, ""));
|
this.splashLabel = this.add(new Label(0, 100, width, 0, ""));
|
||||||
|
@ -133,24 +112,16 @@ public class GuiMenu extends Gui {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.add(new NavButton(0, 0, 180, 0, this.gm.charEditor ? GuiChar.INSTANCE : null, this.gm.charEditor ? "Zurück zum Editor" : "Zurück zum Spiel"));
|
this.add(new NavButton(0, 0, 180, 0, this.gm.charEditor ? GuiChar.INSTANCE : null, this.gm.charEditor ? "Zurück zum Editor" : "Zurück zum Spiel"));
|
||||||
this.add(new NavButton(0, 20, 180, 0, GuiOptions.getPage(), "Einstellungen"));
|
this.add(new NavButton(0, 20, 180, 0, GuiPlayer.INSTANCE, "MIDI-Player"));
|
||||||
|
this.add(new NavButton(0, 40, 180, 0, GuiOptions.getPage(), "Einstellungen"));
|
||||||
if(!this.gm.charEditor)
|
if(!this.gm.charEditor)
|
||||||
this.add(new NavButton(0, 40, 180, 0, GuiCharacters.INSTANCE, "Charakter")).enabled = !(this.gm.player instanceof EntityCameraHolder);
|
this.add(new NavButton(0, 60, 180, 0, GuiCharacters.INSTANCE, "Charakter")).enabled = !(this.gm.player instanceof EntityCameraHolder);
|
||||||
this.add(new ActButton(0, this.gm.charEditor ? 50 : 70, 180, 0, new ButtonCallback() {
|
this.add(new ActButton(0, this.gm.charEditor ? 70 : 90, 180, 0, new ButtonCallback() {
|
||||||
public void use(ActButton elem, PressType action) {
|
public void use(ActButton elem, PressType action) {
|
||||||
GuiMenu.this.gm.unload(true);
|
GuiMenu.this.gm.unload(true);
|
||||||
// GuiMenu.this.gm.displayGuiScreen(INSTANCE);
|
// GuiMenu.this.gm.displayGuiScreen(INSTANCE);
|
||||||
}
|
}
|
||||||
}, "Server verlassen"));
|
}, "Server verlassen"));
|
||||||
this.add(new ActButton(0, this.gm.charEditor ? 70 : 90, 180, 0, new ButtonCallback() {
|
|
||||||
public void use(ActButton elem, PressType action) {
|
|
||||||
GuiMenu.this.gm.showFileDialog(FileMode.FILE_LOAD, "MIDI laden", null, new FileCallback() {
|
|
||||||
public void selected(File file) {
|
|
||||||
GuiMenu.this.gm.playMidi(file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, "MIDI-Player"));
|
|
||||||
this.shift();
|
this.shift();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
570
client/src/main/java/client/gui/GuiPlayer.java
Normal file
570
client/src/main/java/client/gui/GuiPlayer.java
Normal file
|
@ -0,0 +1,570 @@
|
||||||
|
package client.gui;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
import client.Client.FileMode;
|
||||||
|
import client.audio.MidiDecoder;
|
||||||
|
import client.gui.element.ActButton;
|
||||||
|
import client.gui.element.ButtonCallback;
|
||||||
|
import client.gui.element.Fill;
|
||||||
|
import client.gui.element.GuiList;
|
||||||
|
import client.gui.element.ListEntry;
|
||||||
|
import client.gui.element.NavButton;
|
||||||
|
import client.gui.element.PressType;
|
||||||
|
import client.renderer.Drawing;
|
||||||
|
import common.log.Log;
|
||||||
|
import common.rng.Random;
|
||||||
|
|
||||||
|
public class GuiPlayer extends GuiList<GuiPlayer.SongEntry> {
|
||||||
|
protected class SongEntry implements ListEntry {
|
||||||
|
private final File file;
|
||||||
|
|
||||||
|
protected SongEntry(File file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void draw(int x, int y, int width, int height, int mouseX, int mouseY, boolean hovered) {
|
||||||
|
Drawing.drawText(this.file.getName(), x + 3, y, GuiPlayer.this.playing && GuiPlayer.this.entry == this ? (GuiPlayer.this.paused != null ? 0xffffff00 : 0xff00ff00) : 0xffffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void select(boolean dclick, int mx, int my) {
|
||||||
|
if(dclick)
|
||||||
|
GuiPlayer.this.select();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum RepeatMode {
|
||||||
|
REPEAT_OFF("N"),
|
||||||
|
REPEAT_SINGLE("L"),
|
||||||
|
REPEAT_ALL("A"),
|
||||||
|
REPEAT_SHUFFLE("R");
|
||||||
|
|
||||||
|
private final String display;
|
||||||
|
|
||||||
|
private RepeatMode(String display) {
|
||||||
|
this.display = display;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static final GuiPlayer INSTANCE = new GuiPlayer();
|
||||||
|
|
||||||
|
private final Random rand = new Random();
|
||||||
|
private MidiDecoder paused;
|
||||||
|
private int position = -1;
|
||||||
|
private SongEntry entry;
|
||||||
|
private boolean playing;
|
||||||
|
private RepeatMode mode = RepeatMode.REPEAT_OFF;
|
||||||
|
private ActButton playButton;
|
||||||
|
private ActButton stopButton;
|
||||||
|
private ActButton modeButton;
|
||||||
|
|
||||||
|
private GuiPlayer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDisplay() {
|
||||||
|
if(this.gm.open != this)
|
||||||
|
return;
|
||||||
|
this.playButton.setText(!this.elements.isEmpty() && this.playing && this.paused == null ? "=" : "*");
|
||||||
|
this.modeButton.setText(this.mode.display);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void playMidi(int index) {
|
||||||
|
this.paused = null;
|
||||||
|
this.playing = true;
|
||||||
|
this.entry = this.getListEntry(this.position = index);
|
||||||
|
this.updateDisplay();
|
||||||
|
File file = this.entry.file;
|
||||||
|
byte[] data;
|
||||||
|
try {
|
||||||
|
data = Files.readAllBytes(file.toPath());
|
||||||
|
}
|
||||||
|
catch(Throwable e) {
|
||||||
|
Log.SOUND.error(e, "Konnte Datei '%s' nicht laden", file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MidiDecoder midi;
|
||||||
|
try {
|
||||||
|
midi = new MidiDecoder(data, this.gm.midiNoWait, this.gm.midiVoices, this.gm.midiBank, this.gm.midiKeep, this.gm.midiUnknown, this.gm.midiVelocity);
|
||||||
|
}
|
||||||
|
catch(Throwable e) {
|
||||||
|
Log.SOUND.error(e, "Konnte MIDI '%s' nicht laden", file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
midi.setDebug(this.gm.midiDebug);
|
||||||
|
this.gm.getAudioInterface().alMidi(midi);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test(int start, int end, int delay, int note) {
|
||||||
|
this.paused = null;
|
||||||
|
this.playing = false;
|
||||||
|
this.position = -1;
|
||||||
|
this.gm.getAudioInterface().alMidi(new MidiDecoder(this.gm.midiBank, start, end, delay, note));
|
||||||
|
this.updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
this.stop();
|
||||||
|
this.elements.clear();
|
||||||
|
this.setSelected(-1);
|
||||||
|
this.updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
if(this.selectedElement >= 0) {
|
||||||
|
this.elements.remove(this.selectedElement);
|
||||||
|
if(this.playing && this.position == this.selectedElement) {
|
||||||
|
if(this.position == this.elements.size())
|
||||||
|
this.stop();
|
||||||
|
else
|
||||||
|
this.playMidi(this.position);
|
||||||
|
}
|
||||||
|
if(this.elements.isEmpty())
|
||||||
|
this.setSelected(-1);
|
||||||
|
else if(this.selectedElement >= this.elements.size())
|
||||||
|
this.setSelected(this.elements.size() - 1);
|
||||||
|
this.updateDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void select() {
|
||||||
|
if(this.selectedElement >= 0)
|
||||||
|
this.playMidi(this.selectedElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void random() {
|
||||||
|
if(!this.elements.isEmpty())
|
||||||
|
this.playMidi(this.rand.zrange(this.elements.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void prev() {
|
||||||
|
if(!this.elements.isEmpty())
|
||||||
|
this.playMidi(this.position <= 0 ? this.elements.size() - 1 : this.position - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void next() {
|
||||||
|
if(!this.elements.isEmpty())
|
||||||
|
this.playMidi(this.position >= this.elements.size() - 1 ? 0 : this.position + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mode(int dir) {
|
||||||
|
this.mode = dir == 0 ? RepeatMode.REPEAT_OFF : RepeatMode.values()[(RepeatMode.values().length + this.mode.ordinal() + dir) % RepeatMode.values().length];
|
||||||
|
this.updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isMidiFile(File file) {
|
||||||
|
String name = file.getName().toLowerCase();
|
||||||
|
return name.endsWith(".mid") || name.endsWith(".midi") || name.endsWith(".kar");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(File file) {
|
||||||
|
if(file.isDirectory()) {
|
||||||
|
File[] files = file.listFiles(sub -> sub.isDirectory() || GuiPlayer.isMidiFile(sub));
|
||||||
|
if(files != null) {
|
||||||
|
for(File sub : files) {
|
||||||
|
this.add(sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(isMidiFile(file)) {
|
||||||
|
this.elements.add(new SongEntry(file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
this.paused = null;
|
||||||
|
this.playing = false;
|
||||||
|
this.position = -1;
|
||||||
|
this.gm.getAudioInterface().alMidi(null);
|
||||||
|
this.updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void play() {
|
||||||
|
MidiDecoder midi = this.gm.getAudioInterface().alGetMidi();
|
||||||
|
if(midi != null) {
|
||||||
|
this.gm.getAudioInterface().alMidi(null);
|
||||||
|
this.paused = midi;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.playing = true;
|
||||||
|
if(this.paused != null) {
|
||||||
|
this.paused.setDebug(this.gm.midiDebug);
|
||||||
|
this.gm.getAudioInterface().alMidi(this.paused);
|
||||||
|
}
|
||||||
|
this.paused = null;
|
||||||
|
}
|
||||||
|
this.updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updatePlayer() {
|
||||||
|
if(!this.elements.isEmpty() && this.playing && this.paused == null && this.gm.getAudioInterface().alGetMidi() == null) {
|
||||||
|
if(this.position >= 0) {
|
||||||
|
switch(this.mode) {
|
||||||
|
case REPEAT_OFF:
|
||||||
|
this.position += 1;
|
||||||
|
break;
|
||||||
|
case REPEAT_SINGLE:
|
||||||
|
break;
|
||||||
|
case REPEAT_ALL:
|
||||||
|
if((this.position += 1) >= this.elements.size())
|
||||||
|
this.position = 0;
|
||||||
|
break;
|
||||||
|
case REPEAT_SHUFFLE:
|
||||||
|
this.position = this.rand.zrange(this.elements.size());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.position = 0;
|
||||||
|
}
|
||||||
|
if(this.position >= this.elements.size()) {
|
||||||
|
this.playing = false;
|
||||||
|
this.position = -1;
|
||||||
|
this.updateDisplay();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.playMidi(this.position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(int width, int height) {
|
||||||
|
super.init(width, height);
|
||||||
|
this.setDimensions(320, height, 18, height - 18);
|
||||||
|
|
||||||
|
this.add(new NavButton(0, 0, 60, 18, GuiMenu.INSTANCE, "Zurück"));
|
||||||
|
this.add(new Fill(60, 0, 242, 18, "SKC OPL MIDI Player v 0.0.1 (~ Sen)", true));
|
||||||
|
this.addSelector("mid_visualizer", 302, 0, 18, 18);
|
||||||
|
|
||||||
|
this.playButton = this.add(new ActButton(0, height - 18, 18, 18, new ButtonCallback() {
|
||||||
|
public void use(ActButton elem, PressType action) {
|
||||||
|
GuiPlayer.this.play();
|
||||||
|
}
|
||||||
|
}, "*"));
|
||||||
|
this.stopButton = this.add(new ActButton(18, height - 18, 18, 18, new ButtonCallback() {
|
||||||
|
public void use(ActButton elem, PressType action) {
|
||||||
|
GuiPlayer.this.stop();
|
||||||
|
}
|
||||||
|
}, "#"));
|
||||||
|
this.modeButton = this.add(new ActButton(36, height - 18, 18, 18, new ButtonCallback() {
|
||||||
|
public void use(ActButton elem, PressType action) {
|
||||||
|
GuiPlayer.this.mode(action == PressType.TERTIARY ? 0 : (action == PressType.SECONDARY ? -1 : 1));
|
||||||
|
}
|
||||||
|
}, ""));
|
||||||
|
this.add(new ActButton(54, height - 18, 18, 18, new ButtonCallback() {
|
||||||
|
public void use(ActButton elem, PressType action) {
|
||||||
|
GuiPlayer.this.prev();
|
||||||
|
}
|
||||||
|
}, "<"));
|
||||||
|
this.add(new ActButton(72, height - 18, 18, 18, new ButtonCallback() {
|
||||||
|
public void use(ActButton elem, PressType action) {
|
||||||
|
GuiPlayer.this.next();
|
||||||
|
}
|
||||||
|
}, ">"));
|
||||||
|
this.add(new ActButton(90, height - 18, 18, 18, new ButtonCallback() {
|
||||||
|
public void use(ActButton elem, PressType action) {
|
||||||
|
GuiPlayer.this.random();
|
||||||
|
}
|
||||||
|
}, "?"));
|
||||||
|
this.add(new ActButton(108, height - 18, 18, 18, new ButtonCallback() {
|
||||||
|
public void use(ActButton elem, PressType action) {
|
||||||
|
GuiPlayer.this.select();
|
||||||
|
}
|
||||||
|
}, "~"));
|
||||||
|
this.add(new ActButton(126, height - 18, 18, 18, new ButtonCallback() {
|
||||||
|
public void use(ActButton elem, PressType action) {
|
||||||
|
GuiPlayer.this.remove();
|
||||||
|
}
|
||||||
|
}, "-"));
|
||||||
|
this.add(new ActButton(144, height - 18, 18, 18, new ButtonCallback() {
|
||||||
|
public void use(ActButton elem, PressType action) {
|
||||||
|
GuiPlayer.this.clear();
|
||||||
|
}
|
||||||
|
}, "X"));
|
||||||
|
|
||||||
|
this.addSelector("mid_opl_bank", 162, height - 18, 122, -18);
|
||||||
|
this.add(new ActButton(284, height - 18, 18, 18, new ButtonCallback() {
|
||||||
|
public void use(ActButton elem, PressType action) {
|
||||||
|
GuiPlayer.this.gm.showFileDialog(FileMode.FILE_LOAD_MULTI, "MIDIs laden", null, new FileCallback() {
|
||||||
|
public void selected(File file) {
|
||||||
|
GuiPlayer.this.add(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, "+"));
|
||||||
|
this.add(new ActButton(302, height - 18, 18, 18, new ButtonCallback() {
|
||||||
|
public void use(ActButton elem, PressType action) {
|
||||||
|
GuiPlayer.this.gm.showFileDialog(FileMode.DIRECTORY_LOAD, "MIDIs laden", null, new FileCallback() {
|
||||||
|
public void selected(File file) {
|
||||||
|
GuiPlayer.this.add(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, "^"));
|
||||||
|
// this.add(new ActButton(0, 130, 180, 0, new ButtonCallback() {
|
||||||
|
// public void use(ActButton elem, PressType action) {
|
||||||
|
// GuiPlayer.this.test(0, 255, 500, 36);
|
||||||
|
// }
|
||||||
|
// }, "MIDI-Bank testen"));
|
||||||
|
|
||||||
|
// gui_add_custom(win, 720, 0, frame_x - 720, frame_y, gui_render_player);
|
||||||
|
|
||||||
|
this.updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return "MIDI-Player";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSlotHeight() {
|
||||||
|
return 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
STR(OPL_CHANNEL, "", "Kanal")
|
||||||
|
STR(OPL_MODULATOR, "", "Operator 1 + 3 / Modulator")
|
||||||
|
STR(OPL_CARRIER, "", "Operator 2 + 4 / Träger")
|
||||||
|
STR(OPL_POINTER, "", "Stimmen-Zeiger")
|
||||||
|
STR(OPL_OUTPUT, "", "Pegel")
|
||||||
|
STR(OPL_MODE, "", "Modus/Al.")
|
||||||
|
STR(OPL_FEEDBACK, "", "Feedback")
|
||||||
|
STR(OPL_FREQUENCY, "", "Frequenz")
|
||||||
|
STR(OPL_FLAGS, "", "T-V-S-K")
|
||||||
|
STR(OPL_MULTIPLIER, "", "Frq.-Mult.")
|
||||||
|
STR(OPL_LEVEL, "", "Op.-Pegel")
|
||||||
|
STR(OPL_KEYSCALE, "", "Tst.-Skale")
|
||||||
|
STR(OPL_WAVEFORM, "", "Wellenf.")
|
||||||
|
STR(OPL_ATTACK, "", "Attack")
|
||||||
|
STR(OPL_DECAY, "", "Decay")
|
||||||
|
STR(OPL_SUSTAIN, "", "Sustain")
|
||||||
|
STR(OPL_RELEASE, "", "Release")
|
||||||
|
STR(OPL_ENVELOPE, "", "Hüllkurve")
|
||||||
|
STR(OPL_TICK, "", "Tick/Pos.")
|
||||||
|
STR(OPL_ACTIVE, "", "Aktiv")
|
||||||
|
STR(OPL_TEMPO, "", "Tempo BPM")
|
||||||
|
|
||||||
|
STR(MID_PLAY, "s", "Spiele MIDI '$1'")
|
||||||
|
STR(CMD_PLAY_QUEUED, "d", "$1 MIDIs werden abgespielt")
|
||||||
|
STR(CMD_PLAY_STOPPED, "", "Wiedergabe ist angehalten")
|
||||||
|
STR(CMD_PLAY_PLAYING, "d", "$1 MIDIs sind in der Liste")
|
||||||
|
STR(CMD_PLAY_ENDED, "", "Wiedergabe gestoppt")
|
||||||
|
STR(CMD_PLAY_BANKID, "d", "Bank-ID: $1")
|
||||||
|
|
||||||
|
STR(PLR_MODE_NORM, "", "Normal")
|
||||||
|
STR(PLR_MODE_REPEAT, "", "Wiederholen")
|
||||||
|
STR(PLR_MODE_LOOP, "", "Schleife")
|
||||||
|
STR(PLR_MODE_RAND, "", "Zufällig")
|
||||||
|
STR(PLR_START, "", "Start")
|
||||||
|
STR(PLR_STOP, "", "Stop")
|
||||||
|
STR(PLR_PAUSE, "", "Pause")
|
||||||
|
STR(PLR_MODE, "", "Modus")
|
||||||
|
STR(PLR_PREV, "", "Vorheriger")
|
||||||
|
STR(PLR_NEXT, "", "Nächster")
|
||||||
|
STR(PLR_RANDOM, "", "Zufälliger")
|
||||||
|
STR(PLR_JUMP, "", "Springe zu")
|
||||||
|
|
||||||
|
|
||||||
|
#define SYM_PLAY "\U00100000"
|
||||||
|
#define SYM_STOP "\U00100001"
|
||||||
|
#define SYM_PAUSE "\U00100002"
|
||||||
|
#define SYM_NEXT "\U00100003"
|
||||||
|
#define SYM_PREV "\U00100004"
|
||||||
|
#define SYM_FFORWARD "\U00100005"
|
||||||
|
#define SYM_FREVERSE "\U00100006"
|
||||||
|
#define SYM_CONTINUOS "\U00100007"
|
||||||
|
#define SYM_REPEAT "\U00100008"
|
||||||
|
#define SYM_LOOPED "\U00100009"
|
||||||
|
#define SYM_SHUFFLE "\U0010000a"
|
||||||
|
#define SYM_PRANDOM "\U0010000b"
|
||||||
|
#define SYM_JUMPTO "\U0010000c"
|
||||||
|
#define SYM_FOLDER "\U0010000d"
|
||||||
|
#define SYM_DELETE "\U0010000e"
|
||||||
|
#define SYM_SAVEDISK "\U0010000f"
|
||||||
|
|
||||||
|
|
||||||
|
static const char plr_wheel[] = { '/', '-', '\\', '|'};
|
||||||
|
|
||||||
|
void gui_fmt_velofunc(gui_t *elem, int value) {
|
||||||
|
snprintf(elem.text, elem.capacity, "%s %d: %s", elem.format_text, value, (value ? (value == -128 ? STR_MID_VELO_ONE : (value < 0 ? STR_MID_VELO_ATTN : STR_MID_VELO_LOG)) : STR_MID_VELO_LIN));
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_plr_update_text(window_t *win) {
|
||||||
|
gui_t *elem = gui_get(win, 17);
|
||||||
|
const char *name = "";
|
||||||
|
int pos = (snd.mid_queue && (snd.mid_playpos != INT_MIN)) ? ((snd.mid_playpos < -1) ? (-(snd.mid_playpos) - 3) : snd.mid_playpos) : -1;
|
||||||
|
if(pos >= 0) {
|
||||||
|
if(pos != (snd.mid_queued - 1))
|
||||||
|
snd.mid_queue[pos+1][-1] = 0;
|
||||||
|
if(name = strrchr(&(snd.mid_queue[pos])[6], '/'))
|
||||||
|
name += 1;
|
||||||
|
else
|
||||||
|
name = &(snd.mid_queue[pos])[6];
|
||||||
|
snprintf(elem.text, elem.capacity, "%s: %d/%d - %s", STR_PLR_INFO, pos + 1, snd.mid_queued, name);
|
||||||
|
if(pos != (snd.mid_queued - 1))
|
||||||
|
snd.mid_queue[pos+1][-1] = '\n';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
snprintf(elem.text, elem.capacity, "%s", STR_PLR_INFO);
|
||||||
|
}
|
||||||
|
gui_update_text(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_plr_update(window_t *win) {
|
||||||
|
gui_t *elem = gui_get(win, 2);
|
||||||
|
snprintf(elem.text, elem.capacity, snd.mid_queue && (snd.mid_playpos >= -1) ? COL_GREEN SYM_PLAY : SYM_PLAY);
|
||||||
|
gui_update_text(elem);
|
||||||
|
elem = gui_get(win, 3);
|
||||||
|
snprintf(elem.text, elem.capacity, !snd.mid_queue || (snd.mid_playpos == INT_MIN) ? COL_RED SYM_STOP : SYM_STOP);
|
||||||
|
gui_update_text(elem);
|
||||||
|
elem = gui_get(win, 4);
|
||||||
|
snprintf(elem.text, elem.capacity, snd.mid_queue && (snd.mid_playpos != INT_MIN) && (snd.mid_playpos < -1) ? COL_YELLOW SYM_PAUSE : SYM_PAUSE);
|
||||||
|
gui_update_text(elem);
|
||||||
|
gui_plr_update_text(win);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint plr_waveforms[] = {0xff00ff00, 0xffff0000, 0xff0000ff, 0xff00ffff, 0xffff00ff, 0xffffff00, 0xff80ff00, 0xff00ff80};
|
||||||
|
|
||||||
|
int gui_render_bar(gui_t *elem, int x, int y, int w, int h, uint top, uint bottom, uint bg, int v) {
|
||||||
|
v = (v < 0) ? 0 : v;
|
||||||
|
gfx_draw_rect(elem.pos_x + x, elem.pos_y + y, w, h, 0, 0, 0xff000000 | top, 0xff000000 | bottom, 0, 0);
|
||||||
|
if(++v < h)
|
||||||
|
gfx_draw_rect(elem.pos_x + x, elem.pos_y + y, w, h - v, 0, 0, 0xff000000 | bg, 0xff000000 | bg, 0, 0);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gui_render_grad(gui_t *elem, int x, int y, int w, int h, uint top, uint bottom) {
|
||||||
|
gfx_draw_rect(elem.pos_x + x, elem.pos_y + y, w, h, 0, 0, 0xff000000 | top, 0xff000000 | bottom, 0, 0);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gui_render_rect(gui_t *elem, int x, int y, int w, int h, uint color) {
|
||||||
|
gfx_draw_rect(elem.pos_x + x, elem.pos_y + y, w, h, 0, 0, 0xff000000 | color, 0xff000000 | color, 0, 0);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gui_render_text(gui_t *elem, int x, int y, uint color, const char *text) {
|
||||||
|
txt_draw(elem.pos_x + x, elem.pos_y + y, 0, sys.font.yglyph, sys.font.yglyph, elem.pos_x + x, elem.pos_y + y, elem.pos_x + elem.size_x, elem.pos_y + elem.size_y,
|
||||||
|
0xff000000 | color, 0x00000000, &sys.font, text);
|
||||||
|
return sys.font.yglyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_render_player(gui_t *elem, int value) {
|
||||||
|
elem.t_dirty = 1;
|
||||||
|
if(!value)
|
||||||
|
gui_render_grad(elem, 0, 0, elem.size_x, elem.size_y, sys.style.field_btm, sys.style.field_top);
|
||||||
|
if(snd.mid_visual ^ 1)
|
||||||
|
return;
|
||||||
|
pthread_mutex_lock(&sgt.lock);
|
||||||
|
if(!sgt.chip || !sgt.bank) {
|
||||||
|
pthread_mutex_unlock(&sgt.lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
OPLChip chip = sgt.chip;
|
||||||
|
bank_handle *bank = sgt.bank;
|
||||||
|
int nch = chip.n_voices;
|
||||||
|
int bx = elem.size_x / 2 - (nch * 6 + 2) / 2;
|
||||||
|
int by = elem.size_y / 2 - (698 + 20 * 4) / 2;
|
||||||
|
int x = bx;
|
||||||
|
int y = by;
|
||||||
|
if(value) {
|
||||||
|
x = bx - 84;
|
||||||
|
sprintf(&sys.work_buf[str_time(sys.work_buf, sgt.mid_time)], "\n%c%c%c%c %c",
|
||||||
|
(sgt.mid.tpqn && (((sgt.mid_tick / sgt.mid.tpqn) & 3) == 0)) ? '*' : '.',
|
||||||
|
(sgt.mid.tpqn && (((sgt.mid_tick / sgt.mid.tpqn) & 3) == 1)) ? '*' : '.',
|
||||||
|
(sgt.mid.tpqn && (((sgt.mid_tick / sgt.mid.tpqn) & 3) == 2)) ? '*' : '.',
|
||||||
|
(sgt.mid.tpqn && (((sgt.mid_tick / sgt.mid.tpqn) & 3) == 3)) ? '*' : '.',
|
||||||
|
plr_wheel[(sgt.mid_tick >> 5) & 3]);
|
||||||
|
gui_render_text(elem, x, y + 20, 0xffffff, sys.work_buf);
|
||||||
|
sprintf(sys.work_buf, COL_NEON"%s"COL_RESET"\n%d", STR_OPL_TICK, sgt.mid_tick);
|
||||||
|
gui_render_text(elem, x, y + 60, 0xffffff, sys.work_buf);
|
||||||
|
sprintf(sys.work_buf, COL_NEON"%s"COL_RESET"\n%d / %d", STR_OPL_ACTIVE, bank.v_used, bank.voices.length);
|
||||||
|
gui_render_text(elem, x, y + 100, 0xffffff, sys.work_buf);
|
||||||
|
sprintf(sys.work_buf, COL_NEON"%s"COL_RESET"\n%d +%dQ", STR_OPL_TEMPO, sgt.mid.uspb ? (60000000 / sgt.mid.uspb) : 0, sgt.mid.tpqn);
|
||||||
|
gui_render_text(elem, x, y + 140, 0xffffff, sys.work_buf);
|
||||||
|
x = bx;
|
||||||
|
pthread_mutex_unlock(&sgt.lock);
|
||||||
|
y += 3;
|
||||||
|
gui_render_text(elem, x, y, 0xffffff, STR_OPL_CHANNEL);
|
||||||
|
gui_render_text(elem, x, y + 20 + 226, 0xffffff, STR_OPL_MODULATOR);
|
||||||
|
gui_render_text(elem, x, y + 40 + 226 + 232, 0xffffff, STR_OPL_CARRIER);
|
||||||
|
gui_render_text(elem, x, y + 60 + 226 + 232 * 2, 0xffffff, STR_OPL_POINTER);
|
||||||
|
y -= 3;
|
||||||
|
// x -= 86;
|
||||||
|
x += nch * 6 + 2 + 1;
|
||||||
|
y += 20;
|
||||||
|
gui_render_text(elem, x, y + 0, 0xffffff, STR_OPL_OUTPUT);
|
||||||
|
gui_render_text(elem, x, y + 70, 0xffffff, STR_OPL_MODE);
|
||||||
|
gui_render_text(elem, x, y + 84, 0xffffff, STR_OPL_FEEDBACK);
|
||||||
|
gui_render_text(elem, x, y + 98, 0xffffff, STR_OPL_FREQUENCY);
|
||||||
|
y += 226 + 20;
|
||||||
|
for(int o = 0; o < 2; o++) {
|
||||||
|
gui_render_text(elem, x, y + 6, 0xffffff, STR_OPL_FLAGS);
|
||||||
|
gui_render_text(elem, x, y + 24, 0xffffff, STR_OPL_MULTIPLIER);
|
||||||
|
gui_render_text(elem, x, y + 42, 0xffffff, STR_OPL_LEVEL);
|
||||||
|
gui_render_text(elem, x, y + 96, 0xffffff, STR_OPL_KEYSCALE);
|
||||||
|
gui_render_text(elem, x, y + 110, 0xffffff, STR_OPL_WAVEFORM);
|
||||||
|
gui_render_text(elem, x, y + 124, 0xffffff, STR_OPL_ATTACK);
|
||||||
|
gui_render_text(elem, x, y + 142, 0xffffff, STR_OPL_DECAY);
|
||||||
|
gui_render_text(elem, x, y + 160, 0xffffff, STR_OPL_SUSTAIN);
|
||||||
|
gui_render_text(elem, x, y + 178, 0xffffff, STR_OPL_RELEASE);
|
||||||
|
gui_render_text(elem, x, y + 196, 0xffffff, STR_OPL_ENVELOPE);
|
||||||
|
y += 232 + 20;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
y += 20;
|
||||||
|
y += gui_render_rect(elem, x, y, nch * 6 + 2, 226, 0x3f0000) + 20;
|
||||||
|
y += gui_render_rect(elem, x, y, nch * 6 + 2, 232, 0x003f00) + 20;
|
||||||
|
y += gui_render_rect(elem, x, y, nch * 6 + 2, 232, 0x00003f) + 20;
|
||||||
|
y += gui_render_rect(elem, x, y, nch * 6 + 2, 8, 0x2f2f2f);
|
||||||
|
for(int c = 0; c < nch; c++) {
|
||||||
|
OPLChannel channel = &chip.channel[c];
|
||||||
|
x = bx + 2 + 6 * c;
|
||||||
|
y = by + 2;
|
||||||
|
short **out = channel.out;
|
||||||
|
short accm = *out[0] + *out[1] + *out[2] + *out[3];
|
||||||
|
int chnlvl = 0;
|
||||||
|
for(int n = 0; n < 2; n++) {
|
||||||
|
chnlvl += (short)((accm * channel.level[n]) >> 16);
|
||||||
|
}
|
||||||
|
chnlvl = chnlvl < 0 ? (-chnlvl) : chnlvl;
|
||||||
|
chnlvl = (chnlvl * 16) / 2048;
|
||||||
|
chnlvl = chnlvl > 64 ? 64 : chnlvl;
|
||||||
|
int freq = (int)((((float)channel.f_num * 49716.0f) / powf(2.0f, 20.0f - (float)channel.block)) / 6210.0f * 128.0f);
|
||||||
|
y += 20;
|
||||||
|
y += gui_render_bar(elem, x, y, 4, 64, 0xff0000, 0x00ff00, 0x000000, chnlvl) + 2;
|
||||||
|
y += gui_render_rect(elem, x, y, 4, 4, ((channel.slots[0].eg_out <= 0x100) || (channel.slots[1].eg_out <= 0x100)) ? 0x00ff00 : 0x000000) + 2;
|
||||||
|
y += gui_render_rect(elem, x - (c & 1), y, 5, 4, channel.chtype != ch_2op ? 0xff00ff : 0x000000) + 2;
|
||||||
|
y += gui_render_grad(elem, x, y, 4, 4, channel.con ? 0x00ff00 : 0x808080, 0x0000ff) + 2;
|
||||||
|
y += gui_render_bar(elem, x, y, 4, 8, 0x00ff00, 0xffff00, 0x000000, channel.fb) + 2;
|
||||||
|
y += gui_render_bar(elem, x, y, 4, 128, 0x707070, 0x505050, 0x000000, freq) + 2;
|
||||||
|
gui_render_rect(elem, x, y - 130 + (127 - freq), 4, 1, 0xff0000);
|
||||||
|
for(int o = 0; o < 2; o++) {
|
||||||
|
opl3_slot *slot = channel.slots[o];
|
||||||
|
y += 2;
|
||||||
|
y += 20;
|
||||||
|
y += gui_render_rect(elem, x, y, 4, 4, slot.key ? 0x00ff00 : 0x000000) + 2;
|
||||||
|
y += gui_render_rect(elem, x, y, 4, 4, (slot.trem != (byte*)&slot.chip.zeromod) ? 0x5fdf00 : 0x000000);
|
||||||
|
y += gui_render_rect(elem, x, y, 4, 4, slot.reg_vib ? 0xffff00 : 0x000000);
|
||||||
|
y += gui_render_rect(elem, x, y, 4, 4, slot.reg_type ? 0xff0000 : 0x000000);
|
||||||
|
y += gui_render_rect(elem, x, y, 4, 4, slot.reg_ksr ? 0x5f00bf : 0x000000) + 2;
|
||||||
|
y += gui_render_bar(elem, x, y, 4, 16, 0xff0000, 0xffff00, 0x000000, slot.reg_mult) + 2;
|
||||||
|
y += gui_render_bar(elem, x, y, 4, 64, 0xff0000, 0x00ff00, 0x000000, 63 - slot.reg_tl) + 2;
|
||||||
|
y += gui_render_bar(elem, x, y, 4, 4, 0x7f00ff, 0x3f00ff, 0x000000, slot.reg_ksl) + 2;
|
||||||
|
y += gui_render_rect(elem, x, y, 4, 8, 0x000000) + 2;
|
||||||
|
gui_render_rect(elem, x, y - 10 + (7 - slot.reg_wf), 4, 1, plr_waveforms[slot.reg_wf]);
|
||||||
|
|
||||||
|
y += gui_render_bar(elem, x, y, 4, 16, slot.eg_gen == 0 ? 0xff0000 : 0xaf0000, slot.eg_gen == 0 ? 0x00ffff : 0x00afaf, 0x000000, slot.reg_ar) + 2;
|
||||||
|
y += gui_render_bar(elem, x, y, 4, 16, slot.eg_gen == 1 ? 0xff0000 : 0xaf0000, slot.eg_gen == 1 ? 0x00ffff : 0x00afaf, 0x000000, slot.reg_dr) + 2;
|
||||||
|
y += gui_render_bar(elem, x, y, 4, 16, slot.eg_gen == 2 ? 0xff0000 : 0xaf0000, slot.eg_gen == 2 ? 0x00ffff : 0x00afaf, 0x000000, (slot.reg_sl > 15) ? 0 : (15 - slot.reg_sl)) + 2;
|
||||||
|
y += gui_render_bar(elem, x, y, 4, 16, slot.eg_gen == 3 ? 0xff0000 : 0xaf0000, slot.eg_gen == 3 ? 0x00ffff : 0x00afaf, 0x000000, slot.reg_rr) + 2;
|
||||||
|
y += gui_render_bar(elem, x, y, 4, 32, 0xff0000, 0x0000ff, 0x000000, (0x1ff - slot.eg_rout) / 16) + 2;
|
||||||
|
}
|
||||||
|
y += 2;
|
||||||
|
y += 20;
|
||||||
|
gui_render_rect(elem, x, y, 4, 4, bank.voiceindex == c ? 0x00ffff : 0x000000);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&sgt.lock);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
|
@ -81,7 +81,7 @@ public class EnumVar<T extends Enum> extends BaseVar {
|
||||||
if(this.useSwitch)
|
if(this.useSwitch)
|
||||||
return this.switcher(x, y, w, h);
|
return this.switcher(x, y, w, h);
|
||||||
try {
|
try {
|
||||||
return new Dropdown<T>(x, y, w, h, false, (T[])this.field.getType().getEnumConstants(), this.def, (T)this.field.get(this.object), new DropdownCallback<T>() {
|
return new Dropdown<T>(x, y, w, h < 0 ? -h : h, h < 0, (T[])this.field.getType().getEnumConstants(), this.def, (T)this.field.get(this.object), new DropdownCallback<T>() {
|
||||||
public void use(Dropdown<T> elem, T value) {
|
public void use(Dropdown<T> elem, T value) {
|
||||||
EnumVar.this.parse(value instanceof Identifyable ? ((Identifyable)value).getName() : value.toString());
|
EnumVar.this.parse(value instanceof Identifyable ? ((Identifyable)value).getName() : value.toString());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue