diff --git a/src/main.cpp b/src/main.cpp index 9f599e9..729a623 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,11 +17,14 @@ static char *note_name[] = { "C ", "C#", "D ", "D#", "E ", "F ", "F#", "G ", "G#", "A ", "A#", "B " }; void updateTrack(char* name, char* type); +void renderTrack(WINDOW* win, xmp_module_info *mi, xmp_frame_info *fi); void renderRows(WINDOW* win, xmp_module_info *mi, xmp_frame_info *fi); +void renderChannels(WINDOW* win, xmp_module_info *mi, xmp_frame_info *fi); +void renderInstruments(WINDOW* win, xmp_module_info *mi, xmp_frame_info *fi); char getEffectType(int i); static char *device = "default"; -int chanOffset = 0; int detail = 1; int vol = 100; +int chanOffset = 0; int insOffset = 0; int detail = 2; int vol = 100; int loop_times = 0; bool looper = false, is_stopped = false; int main(int argc, char *argv[]) { printf("Trakker %s (with libxmp %s)\n", VERSION, xmp_version); @@ -92,10 +95,12 @@ int main(int argc, char *argv[]) { xmp_start_player(c, SAMPLERATE, 0); updateTrack(mi.mod->name, mi.mod->type); - while (true) { + while (true) { xmp_get_frame_info(c, &fi); if (xmp_play_frame(c) != 0 && !is_stopped) break; - if (!looper && fi.loop_count > 0) break; + if (fi.loop_count > loop_times) + if (looper) loop_times = fi.loop_count; + else break; // Print Top-Right time mvprintw( @@ -120,26 +125,37 @@ int main(int argc, char *argv[]) { if ((key = wgetch(win)) != 0) { vol = xmp_get_player(c, XMP_PLAYER_VOLUME); switch (key) { + case KEY_RESIZE: + werase(stdscr); + updateTrack(mi.mod->name, mi.mod->type); + wresize(win, LINES-2, COLS-2); + break; case ' ': // Pause/Play time = fi.time; is_stopped = !is_stopped; break; case KEY_LEFT: // Move Channels Left - if (chanOffset > 0) chanOffset--; + if (chanOffset > 0 && detail < 7) chanOffset--; break; case KEY_RIGHT: // Move Channels Right - if (chanOffset < mi.mod->chn-1) chanOffset++; + if (chanOffset < mi.mod->chn-1 && detail < 7) chanOffset++; break; case KEY_UP: // Seek Up - if (is_stopped) fi.row--; - else xmp_set_position(c, fi.pos-1); + if (insOffset > 0 && detail == 7) insOffset--; + else if (detail < 7) fi.row--; break; case KEY_DOWN: // Seek Down - if (is_stopped) fi.row++; - else xmp_set_position(c, fi.pos+1); + if (insOffset < mi.mod->ins-1 && detail == 7) insOffset++; + else if (detail < 7) fi.row++; + break; + case KEY_PPAGE: + xmp_set_position(c, fi.pos-1); + break; + case KEY_NPAGE: + xmp_set_position(c, fi.pos+1); break; case '+': - if (vol < 100) xmp_set_player(c, XMP_PLAYER_VOLUME, vol+=5); + if (vol < 200) xmp_set_player(c, XMP_PLAYER_VOLUME, vol+=5); break; case '-': if (vol > 0) xmp_set_player(c, XMP_PLAYER_VOLUME, vol-=5); @@ -151,11 +167,13 @@ int main(int argc, char *argv[]) { case '2': case '3': case '4': - case '5': - detail = std::atoi(key); + case '5': + case '6': + case '7': + detail = key-48; break; }; - renderRows(win, &mi, &fi); + renderTrack(win, &mi, &fi); } if (!is_stopped) { @@ -168,8 +186,8 @@ int main(int argc, char *argv[]) { pos = fi.pos; row = -1; } - if (fi.row != row) { - renderRows(win, &mi, &fi); + if (fi.row != row || detail >= 6) { + renderTrack(win, &mi, &fi); row = fi.row; fupdate = false; } @@ -201,13 +219,13 @@ void updateTrack(char* name, char* type) { ); } -void renderRows(WINDOW* win, xmp_module_info *mi, xmp_frame_info *fi) { +void renderTrack(WINDOW* win, xmp_module_info *mi, xmp_frame_info *fi) { werase(win); move(LINES-1, 0); wclrtoeol(stdscr); mvprintw( LINES-1, 0, - "[%c] PAT:%02x:%02x/%02x BPM:%02u SPD:%02u CHAN:%02u/%02u VOL:%03u d%i %s", + "[%c] PAT:%02x:%02x/%02x BPM:%02u SPD:%02u CHN:%02u/%02u INS:%02u/%02u VOL:%03u WIN:%i %s", is_stopped?'x':'>', fi->pos, fi->pattern, @@ -216,19 +234,31 @@ void renderRows(WINDOW* win, xmp_module_info *mi, xmp_frame_info *fi) { fi->speed, chanOffset+1, mi->mod->chn, + insOffset, + mi->mod->ins, vol, - detail+1, + detail, looper?"LOOP ":"" ); - int view_chanOffset = chanOffset; - int view_detail = detail; + if (detail < 6) // Row views + renderRows(win, mi, fi); + else if (detail == 6) //Channel views + renderChannels(win, mi, fi); + else if (detail == 7) + renderInstruments(win, mi, fi); + + refresh(); + wrefresh(win); +} + +void renderRows(WINDOW* win, xmp_module_info *mi, xmp_frame_info *fi) { int dlvl; // Set proper sizes for channels. if (detail == 5) dlvl = 19; else if (detail == 4) dlvl = 15; else if (detail == 3) dlvl = 11; else if (detail == 2) dlvl = 7; - else dlvl = 3; + else dlvl = 2; for (int y = 0; y < LINES - 2; y++) { int trow = (fi->row - ((LINES - 2) / 2))+y; if (trow > fi->num_rows-1 || trow < 0) { continue;} @@ -241,14 +271,13 @@ void renderRows(WINDOW* win, xmp_module_info *mi, xmp_frame_info *fi) { } wmove(win, y, 0); wprintw(win, "%02X", trow); - int coff = ((COLS - 2) % dlvl); int maxcol = -1; for (int i = chanOffset; i < mi->mod->chn; i++) { - if (coff+(((i-chanOffset)+1)*dlvl)+dlvl > COLS) { + if (1+(((i-chanOffset)+1)*dlvl)+dlvl > COLS) { maxcol = i; break; } - wmove(win, y, coff+((i-chanOffset)*dlvl)+2); + wmove(win, y, 1+((i-chanOffset)*dlvl)+2); int track = mi->mod->xxp[fi->pattern]->index[i]; struct xmp_event event = mi->mod->xxt[track]->event[trow]; if (i > 0 && i == chanOffset) wprintw(win, "<"); @@ -319,19 +348,50 @@ void renderRows(WINDOW* win, xmp_module_info *mi, xmp_frame_info *fi) { wprintw(win, " "); } } - view_chanOffset = chanOffset; - view_detail = detail; } if (maxcol < mi->mod->chn && maxcol > 0) wprintw(win, ">"); else wprintw(win, "|"); } - refresh(); - wrefresh(win); +} + +void renderChannels(WINDOW* win, xmp_module_info *mi, xmp_frame_info *fi) { + int chns = mi->mod->chn; + for (int y = chanOffset; y < chns; y++) { + struct xmp_channel_info cinfo = fi->channel_info[y]; + if (y > (LINES - 3)+chanOffset) break; + wmove(win, y-chanOffset, 0); + int cvol = (cinfo.volume * (COLS - 7)) / (64 * (vol / 100)); + wprintw(win, "%02X [", y); + for (int c = 0; c < COLS - 7; c++) { + if (c < cvol) wprintw(win, "#"); + else wprintw(win, " "); + } + wprintw(win, "]"); + } +} + +void renderInstruments(WINDOW* win, xmp_module_info *mi, xmp_frame_info *fi) { + int ins = mi->mod->ins; + for (int y = insOffset; y < ins; y++) { + if (y > (LINES - 3)+insOffset) break; + wmove(win, y-insOffset, 0); + wprintw(win, "%02X [", y); + for (int c = 0; c < mi->mod->chn; c++) { + struct xmp_channel_info cinfo = fi->channel_info[c]; + int note = (cinfo.note * (COLS - 7)) / 144; + if (cinfo.instrument != y) continue; + wmove(win, y-insOffset, note); + if (cinfo.volume >= 16) wprintw(win, "#"); + else if (cinfo.volume > 0) wprintw(win, "-"); + } + wmove(win, y-insOffset, COLS-3); + wprintw(win, "]"); + } } char getEffectType(int i) { // The effect type characters are so strange to me. - // They make absolutely no sense in why it's setup this way. + // They make absolutely no sense in why it's set up this way. // Maybe I'm mega stupid right now but this is all of the IT // formats effects, so maybe this will cover everything enough. // Broken, but not crashy-broken anymore.