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 /* || type == 5 */) { 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); }