/*** *** *** MP - a free music module player based on ncurses (GUI) *** and mikmod (sound engine). *** *** *** Copyright (C) 2003-2004 Gael Gence *** and Gregoire Welraeds *** *** *** *** For licence, please refer to the COPYING file distributed *** with the archive. *** *** *** *** Home site: http://mp.waw.cx/ *** ***/ #include #include #include #include #include #include #include #include #include #include #include #include #include /****************************************************************************** *** *** Defines. *** ******************************************************************************/ #define VERSION "0.6" /* here it is */ #define NAME_MAX 255 /*** Various. ***/ #define MIN_FREQ 4000 /* minimum frequency */ #define MAX_FREQ 60000 /* maximum frequency */ #define MAX_CHANNELS 64 /* max # channels */ #define CHN_START 7 /* display channel y start */ #define FILE_Y 1 /* module file y pos */ #define TITLE_Y 2 /* module title y pos */ #define DRIVER_Y 3 /* driver info y pos */ #define MODINFO_Y 4 /* module info y pos */ #define EFFECTS 10 /* # of effects */ /*** Options. ***/ #define OPTIONS 12 /* # of options */ #define _16BITS_OPT 0 /* option # */ #define STEREO_OPT 1 /* option # */ #define REVSTEREO_OPT 2 /* option # */ #define SURROUND_OPT 3 /* option # */ #define INTERPOLATE_OPT 4 /* option # */ #define HQMIXER_OPT 6 /* option # */ #define MIXFREQ_OPT 7 /* option # */ #define LOOP_OPT 9 /* option # */ #define FADE_OPT 10 /* option # */ #define RANDOM_OPT 11 /* option # */ #define DELAY_OPT 13 /* option # */ #define SAVE_OPT 15 /* option # */ /*** Limits. ***/ #define SPEED_LIMIT 256 #define REVERB_LIMIT 15 #define STEREO_LIMIT 128 #define TEMPO_LIMIT 256 #define BPM_LIMIT 256 #define GENVOL_LIMIT 128 #define MODVOL_LIMIT 256 #define REALVOL_LIMIT 65535 #define MIXVOL_LIMIT 25700 #define BASS_LIMIT 256 #define TREBLE_LIMIT 256 #define MAX_FILES 16384 /*** Message IDs ***/ #define ERROR_MSG 1 #define INFO_MSG 2 /*** Keys. ***/ #undef KEY_TAB #define KEY_TAB 9 #undef KEY_ENTER #define KEY_ENTER 10 #undef KEY_DELETE #define KEY_DELETE 330 #undef KEY_BACKSPACE #define KEY_BACKSPACE 263 #undef KEY_ESCAPE #define KEY_ESCAPE 27 #undef KEY_SPACE #define KEY_SPACE 0 /*** Windows coords. ***/ #define AC_W 68 #define AC_H 16 int AC_X; int AC_Y; /* all channels window */ #define VFREQ_W 68 #define VFREQ_H 16 int VFREQ_X; int VFREQ_Y; /* all channels window */ #define VPOS_W 68 #define VPOS_H 16 int VPOS_X; int VPOS_Y; /* voices position window */ #define FS_W 60 #define FS_H (LINES-3) int FS_X; int FS_Y; /* file selector window */ #define PL_W 72 #define PL_H (LINES-2) int PL_X; int PL_Y; /* playlist window */ #define EFT_W 40 #define EFT_H EFFECTS+4 int EFT_X; int EFT_Y; /* effect window */ #define OPT_W 40 #define OPT_H OPTIONS+8 int OPT_X; int OPT_Y; /* options window */ #define SMP_W 54 #define SMP_H 15 int SMP_X; int SMP_Y; /* samples window */ #define INS_W 54 #define INS_H 13 int INS_X; int INS_Y; /* instruments window */ #define DSP_X 0 #define DSP_Y 0 int DSP_W; int DSP_H; /* display window */ #define HELP_H 20 #define HELP_W 70 int HELP_X; int HELP_Y; /* help window */ /*** Colors. ***/ #define WHITE 0 #define RED 1 #define GREEN 2 #define BLUE 3 #define YELLOW 4 #define CYAN 5 #define MAGENTA 6 #define BLUE_BLUE 7 #define CYAN_BLUE 8 #define GREEN_BLUE 9 #define YELLOW_BLUE 10 #define MAGENTA_MAGENTA 11 #define CYAN_CYAN 12 #define RED_RED 13 #define WHITE_RED 14 /****************************************************************************** *** *** Global variables. *** ******************************************************************************/ /*** Various. ***/ int pos = 0; /* current position */ int page = 0; /* vertical page */ int gauge_style = 1; /* block */ int curch = 0; /* current channel number */ int oldcurch = 0; /* last channel number */ chtype oldc1, oldc2; /* previous characters (pointer) */ MODULE *mod = NULL; /* current module */ int DELAY = 40; /* screen refresh delay */ /*** Mixer. ***/ char *mixerdev = "/dev/mixer"; /* mixer device */ int mixerfd = 0; /* mixer file descriptor */ int mixerok = 0; /* set to 1 of open succeeds */ int treble = 0; int bass = 0; int mixvol = 0; /*** Options. ***/ char _16bits = 1; char stereo = 1; char surround = 1; char hq_mixer = 1; char loop_module = 0; /* yes by default in MikMod */ char fade_module = 0; char random_mode = 0; char reverse_stereo = 0; char interpolate = 0; /*** Flags. ***/ char stopped = 0; /* set to 1 when module stooped */ char in_playlist = 0; /* set to 1 when playlist */ char output = 1; /* used for muting all channels */ char playing = 0; /* 1 playing module, 0 not playing */ char real_volume = 1; /* real volume display switch */ char ptn_view = 0; /* pattern view */ /*** Paths and names. ***/ char option_file[NAME_MAX+1]; /* option file path */ char moddir[NAME_MAX+1]; /* module directory */ char full_modname[NAME_MAX+1]; /* full module path */ char *short_modname; /* module name only */ char pl_file[NAME_MAX+1]; /* playlist file */ /*** Channels info arrays. ***/ int lastvol[MAX_CHANNELS]; /* last volume of each channel */ int maxvol[MAX_CHANNELS]; /* max channels volume */ int maxrvol[MAX_CHANNELS]; /* max channels real volume */ int maxfreq[MAX_CHANNELS]; /* max channels frequency */ int maxpos[MAX_CHANNELS]; /* max channels frequency */ char muted[MAX_CHANNELS]; /* keep channels mute status */ int maxrvoli; /*** Current file size in bytes and KB. ***/ int file_sizeb; float file_size; /*** Windows. ***/ WINDOW *dspwin; PANEL *dsppan; WINDOW *eftwin; PANEL *eftpan; WINDOW *optwin; PANEL *optpan; WINDOW *acwin; PANEL *acpan; WINDOW *vposwin; PANEL *vpospan; WINDOW *vfreqwin; PANEL *vfreqpan; WINDOW *poswin; PANEL *pospan; WINDOW *helpwin; PANEL *helppan; WINDOW *smpwin; PANEL *smppan; WINDOW *inswin; PANEL *inspan; WINDOW *fswin; PANEL *fspan; WINDOW *plwin; PANEL *plpan; /****************************************************************************** *** *** Prototypes. *** ******************************************************************************/ /* Used once. */ static void init_nc(void); /* init ncurses */ static void init_windows(void); /* init windows */ static void init_sound(void); /* init mikmod */ static void leave(int ignored); /* leave cleanly */ /* Get voice information. */ static inline int get_voice_volume(int channel); static inline int get_voice_realvol(int channel); static inline int get_voice_panning(int channel); static inline int get_voice_freq(int channel); static inline int get_voice_pos(int channel); static inline int get_channel_period(int channel); /* Module related. */ static int play_module(char *modname); void module_control(int c); static void do_pause(void); static void do_stop(void); /* Windows. */ static void options(void); static void effects(void); /* Info. */ static void refresh_driver_info(void); static void refresh_info(void); static void refresh_module_info(void); static void refresh_legend(void); static void refresh_pl_info(void); /* Utils. */ static void draw_pointer(void); static void draw_gauge(WINDOW *win, int x, int y, int pc, int vh, int style); static void get_string(WINDOW *win, int ys, int xs, char *prompt, char *str); static char *file_select(void); static void mp_move_panel(PANEL *pan); static void message(char *msg, int level); /****************************************************************************** *** *** Functions. *** ******************************************************************************/ /*** . ***/ static void dot(void) { printf("."); } /*** Initialize ncurses and colors. ***/ static void init_nc(void) { /* Init ncurses. */ if ((initscr()) == NULL) { fprintf(stderr, "MP: Can't init ncurses.\n"); exit(-1); } /* Set display (main) window dimensions. */ DSP_W = COLS; DSP_H = LINES; /* Set window options. */ cbreak(); noecho(); timeout(DELAY); curs_set(0); keypad(stdscr, TRUE); /* Init colors. */ if ((has_colors()) == FALSE) { endwin(); fprintf(stderr, "mp: Terminal doesn't support colors.\n"); exit(-1); } start_color(); init_pair(RED, COLOR_RED, COLOR_BLACK); init_pair(GREEN, COLOR_GREEN, COLOR_BLACK); init_pair(BLUE, COLOR_BLUE, COLOR_BLACK); init_pair(YELLOW, COLOR_YELLOW, COLOR_BLACK); init_pair(CYAN, COLOR_CYAN, COLOR_BLACK); init_pair(MAGENTA, COLOR_MAGENTA, COLOR_BLACK); init_pair(BLUE_BLUE, COLOR_BLUE, COLOR_BLUE); init_pair(CYAN_BLUE, COLOR_CYAN, COLOR_BLUE); init_pair(GREEN_BLUE, COLOR_GREEN, COLOR_BLUE); init_pair(YELLOW_BLUE, COLOR_YELLOW, COLOR_BLUE); init_pair(MAGENTA_MAGENTA, COLOR_MAGENTA, COLOR_MAGENTA); init_pair(CYAN_CYAN, COLOR_CYAN, COLOR_CYAN); init_pair(RED_RED, COLOR_RED, COLOR_RED); init_pair(WHITE_RED, COLOR_WHITE, COLOR_RED); /* Calculate default windows coords. */ AC_X = ((COLS/2)-(AC_W/2)); AC_Y = ((LINES/2)-(AC_H/2)); /* all channels window */ VFREQ_X = ((COLS/2)-(VFREQ_W/2)); VFREQ_Y = ((LINES/2)-(VFREQ_H/2)); /* voices frequency */ VPOS_X = ((COLS/2)-(VPOS_W/2)); VPOS_Y = ((LINES/2)-(VPOS_H/2)); /* voices position */ FS_X = ((COLS/2)-(FS_W/2)); FS_Y = ((LINES/2)-(FS_H/2)); /* file selector window */ PL_X = ((COLS/2)-(PL_W/2)); PL_Y = ((LINES/2)-(PL_H/2)); /* playlist window */ EFT_X = ((COLS/2)-(EFT_W/2)); EFT_Y = ((LINES/2)-(EFT_H/2)); /* effect window */ OPT_X = ((COLS/2)-(OPT_W/2)); OPT_Y = ((LINES/2)-(OPT_H)/2); /* options window */ SMP_X = ((COLS/2)-(SMP_W)/2); SMP_Y = ((LINES/2)-(SMP_H/2)); /* samples window */ INS_X = ((COLS/2)-(INS_W)/2); INS_Y = ((LINES/2)-(INS_H/2)); /* instruments window */ HELP_X = ((COLS/2)-(HELP_W)/2); HELP_Y = ((LINES/2)-(HELP_H/2)); /* help window */ } /*** Initialize windows. ***/ static void init_windows(void) { dspwin = newwin(DSP_H, DSP_W, DSP_Y, DSP_X); wtimeout(dspwin, DELAY); keypad(dspwin, TRUE); leaveok(dspwin, TRUE); box(dspwin, 0, 0); refresh_legend(); dsppan = new_panel(dspwin); wattrset(dspwin, COLOR_PAIR(GREEN_BLUE)|A_BOLD); mvwprintw(dspwin, 0, 0, "%80s", "Press 'h' for help "); wattrset(dspwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD); mvwprintw(dspwin, 0, 0, " :: MP v%s ::", VERSION); update_panels(); doupdate(); } /*** Initialize MikMod. ***/ static void init_sound(void) { /* Register loaders and drivers. */ MikMod_RegisterAllDrivers(); MikMod_RegisterAllLoaders(); /* Set options. */ if (_16bits == 1) md_mode |= DMODE_16BITS; else md_mode &= ~DMODE_16BITS; if (stereo == 1) md_mode |= DMODE_STEREO; else md_mode &= ~DMODE_STEREO; if (reverse_stereo == 1) md_mode |= DMODE_REVERSE; else md_mode &= ~DMODE_REVERSE; if (interpolate == 1) md_mode |= DMODE_INTERP; else md_mode &= ~DMODE_INTERP; if (surround == 1) md_mode |= DMODE_SURROUND; else md_mode &= ~DMODE_SURROUND; if (hq_mixer == 1) md_mode |= DMODE_HQMIXER; else md_mode &= ~DMODE_HQMIXER; /* Initialize MikMod. */ if (MikMod_Init("")) { fprintf(stderr, "\nMP: Couln't initialize sound, reason: %s.\n", MikMod_strerror(MikMod_errno)); fprintf(stderr, " Verify settings in $HOME/.mp/options\n"); exit(-1); } /* Open mixer (for volume, treble and bass). */ if ((mixerfd = open(mixerdev, O_RDWR)) == -1) mixerok = 0; else mixerok = 1; ioctl(mixerfd, MIXER_READ(SOUND_MIXER_VOLUME), &mixvol); ioctl(mixerfd, MIXER_READ(SOUND_MIXER_BASS), &bass); ioctl(mixerfd, MIXER_READ(SOUND_MIXER_TREBLE), &treble); } /*** Close everything. ***/ static void leave(int ignored) { /* Close mixer. */ if (mixerok) close(mixerfd); /* Close MikMod. */ if (mod) Player_Free(mod); MikMod_Exit(); /* Close ncurses. */ endwin(); /* Exit... */ printf(":: MP v%s ::\n", VERSION); /* ;) */ exit(0); } /*** About window. ***/ static void about(void) { WINDOW *tmpwin; PANEL *tmppan; tmpwin = newwin(14, 40, (LINES/2)-6, (COLS/2)-20); wtimeout(tmpwin, DELAY); keypad(tmpwin, TRUE); tmppan = new_panel(tmpwin); box(tmpwin, 0, 0); wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD); mvwprintw(tmpwin, 2, 12, ":: "); wattrset(tmpwin, COLOR_PAIR(GREEN)|A_BOLD); wprintw(tmpwin, "About "); wattrset(tmpwin, COLOR_PAIR(BLUE)|A_BOLD); wprintw(tmpwin, "MP "); wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(tmpwin, "::"); wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD); mvwprintw(tmpwin, 4, 8, "Copyright (c) 2003-2004"); wattrset(tmpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(tmpwin, 5, 4, "Gael Gence and Gregoire Welraeds"); wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL); mvwprintw(tmpwin, 8, 5, "mp.c v%s (280104): 5984 lines", VERSION); wattrset(tmpwin, COLOR_PAIR(BLUE)|A_BOLD); mvwprintw(tmpwin, 11, 11, "http:"); wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD); mvwprintw(tmpwin, 11, 16, "// /"); wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD); mvwprintw(tmpwin, 11, 18, "mp.waw.cx"); while ((wgetch(tmpwin)) != 'q') { if (mod && playing) { refresh_info(); refresh_module_info(); update_panels(); doupdate(); MikMod_Update(); } } del_panel(tmppan); delwin(tmpwin); } /******************************************************************************/ /*** Get voice volume. ***/ static inline int get_voice_volume(int channel) { int i; i = Voice_GetVolume(channel); if (maxvol[channel] < i) maxvol[channel] = i; return i; } /*** Get playing volume. ***/ static inline int get_voice_realvol(int channel) { int i; i = Voice_RealVolume(channel); if (maxrvol[channel] < i) maxrvol[channel] = i; if (maxrvoli < i) maxrvoli = i; return i; } /*** Get voice panning. ***/ static inline int get_voice_panning(int channel) { return(Voice_GetPanning(channel)); } /*** Get voice frequency. ***/ static inline int get_voice_freq(int channel) { int i; i = Voice_GetFrequency(channel); if (maxfreq[channel] < i) maxfreq[channel] = i; return i; } /*** Get voice position. ***/ static inline int get_voice_pos(int channel) { int i; i = Voice_GetPosition(channel); if (maxpos[channel] < i) maxpos[channel] = i; return i; } /*** Get channel period. ***/ static inline int get_channel_period(int channel) { return(Player_GetChannelPeriod(channel)); } /*** Get channel voice. ***/ static inline int get_channel_voice(int channel) { return(Player_GetChannelVoice(channel)); } /*****************************************************************************/ /*** Show module info. ***/ #define CMT_H 21 #define CMT_W 73 int CMT_X; int CMT_Y; static void module_info(MODULE *mod) { int i; int c; int x, y, cnt, len, xoff = 0; WINDOW *tmpwin, *minfowin; PANEL *minfopan; if (mod == NULL) return; if (mod->comment == NULL) { message("No comment in this module.", INFO_MSG); return; } CMT_X = ((COLS/2)-(CMT_W/2)); CMT_Y = ((LINES/2)-(CMT_H/2)); tmpwin = newwin(CMT_H, CMT_W, CMT_Y, CMT_X); if (tmpwin == NULL) return; wtimeout(tmpwin, DELAY); keypad(tmpwin, TRUE); box(tmpwin, 0, 0); mvwprintw(tmpwin, 0, 2, "[ ]"); wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD); mvwprintw(tmpwin, 0, 4, "Comment"); wattrset(tmpwin, A_NORMAL); minfopan = new_panel(tmpwin); minfowin = subwin(tmpwin, CMT_H-2, CMT_W-2, CMT_Y+1, CMT_X+1); wattrset(minfowin, COLOR_PAIR(CYAN)|A_NORMAL); cnt = 0; len = strlen(mod->comment); for (y = 0; y < CMT_H; y++) { if (y == CMT_H-1 && xoff == 0) { for (i = 0; i < CMT_H-2; i++) { wattrset(minfowin, COLOR_PAIR(WHITE)|A_NORMAL); mvwaddch(minfowin, i, 34, '|'); wattrset(minfowin, COLOR_PAIR(CYAN)|A_NORMAL); } y = 0; xoff = 36; } for (x = 0; x < (CMT_W/2)-3; x++, cnt++) { if (cnt >= len) break; mvwaddch(minfowin, y, x + xoff, mod->comment[cnt]); } } /*** Loop ***/ while ((c = wgetch(tmpwin)) != 'q') { module_control(c); if (mod && playing) { refresh_info(); refresh_module_info(); update_panels(); doupdate(); MikMod_Update(); } } del_panel(minfopan); delwin(minfowin); } /*** Load and start module. ***/ static int play_module(char *modname) { int i; struct stat sbuf; char buf[NAME_MAX+1]; MODULE *new; /* Check file. */ if (access(modname, R_OK) != 0) { /* Avoid core dump if file can't be read. */ playing = 0; beep(); message("File can't be read.", ERROR_MSG); return -1; } stat(modname, &sbuf); if (S_ISREG(sbuf.st_mode) == 0) { playing = 0; beep(); message("Not a file.", ERROR_MSG); return -1; } file_size = (((float) (sbuf.st_size)) / 1024.0); file_sizeb = sbuf.st_size; if ((short_modname = rindex(modname, '/')) != NULL) short_modname++; else short_modname = modname; /* Load module. */ new = Player_Load(modname, MAX_CHANNELS, 0); if (new != NULL) { if (mod != NULL) Player_Free(mod); mod = new; wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); for (i = 1; i < COLS-2; i++) mvwaddch(dspwin, TITLE_Y, i, ' '); wattrset(dspwin, COLOR_PAIR(WHITE)|A_BOLD); mvwprintw(dspwin, 2, 1, "Title : "); wattrset(dspwin, COLOR_PAIR(CYAN)|A_NORMAL); wprintw(dspwin, strlen(mod->songname) > 0 ? mod->songname : ""); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(dspwin, " - " ); wattrset(dspwin, COLOR_PAIR(WHITE)|A_BOLD); wprintw(dspwin, "Type: "); wattrset(dspwin, COLOR_PAIR(CYAN|A_NORMAL)); wprintw(dspwin, strlen(mod->modtype) > 0 ? mod->modtype : ""); } else { beep(); sprintf(buf, "%s.", MikMod_strerror(MikMod_errno)); message(buf, ERROR_MSG); return -1; } curch = 0; memset(muted, 0, sizeof(muted)); refresh_module_info(); refresh_info(); draw_pointer(); /* Start the module. */ if (mod != NULL) { pos = 0; mod->loop = loop_module; mod->fadeout = fade_module; for (i = 0; i < MAX_CHANNELS; maxvol[i] = MODVOL_LIMIT, i++); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); for (i = 1; i < COLS-2; i++) mvwaddch(dspwin, FILE_Y, i, ' '); wattrset(dspwin, COLOR_PAIR(WHITE)|A_BOLD); mvwprintw(dspwin, FILE_Y, 1, "File : "); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(dspwin, "%s [ %d smp, %d ins, %d bytes, %.1f KB ]", short_modname, mod->numsmp, mod->numins, file_sizeb, file_size); wnoutrefresh(dspwin); doupdate(); Player_Start(mod); playing = 1; } return 0; } /*** Pause the module. ***/ static void do_pause(void) { int c; WINDOW *tmpwin; if (mod && playing) { tmpwin = newwin(5, 13, (LINES/2)-4, 34); box(tmpwin, 0, 0); wattrset(tmpwin, (COLOR_PAIR(YELLOW)|A_BOLD)); mvwprintw(tmpwin, 2, 2, "Paused..."); Player_TogglePause(); wnoutrefresh(tmpwin); doupdate(); while ((c = wgetch(tmpwin)) != 'p'); Player_Start(mod); playing = 1; delwin(tmpwin); touchwin(dspwin); doupdate(); } else { Player_Start(mod); playing = 1; } } /*** Pause the module. ***/ static void do_stop(void) { WINDOW *tmpwin; tmpwin = newwin(5, 15, (LINES/2)-4, 34); box(tmpwin, 0, 0); wattrset(tmpwin, (COLOR_PAIR(RED)|A_BOLD)); mvwprintw(tmpwin, 2, 2, "Stopping..."); wnoutrefresh(tmpwin); doupdate(); Player_SetPosition(0); Player_Stop(); stopped = 1; playing = 0; mod->patpos = 0; usleep(500000); delwin(tmpwin); touchwin(dspwin); doupdate(); } /*****************************************************************************/ /*** *** Options window. ***/ char *options_strings[OPTIONS+4] = { "16bit", "Stereo", "Reverse stereo", "Surround", "Interpolate", "", "High quality mixer", "Mixing frequency", "", "Loop module", "Fadeout module", "Random mode (playlist)", "", "Refresh delay", "", "Save options" }; /*** Print option and status. ***/ static void print_opt(WINDOW *win, int opt) { int c; if (opt == MIXFREQ_OPT) { mvwprintw(win, opt+2, 3, " %s [ %5d ] ", options_strings[opt], md_mixfreq); } else if (opt == DELAY_OPT) { mvwprintw(win, opt+2, 3, " %s [ %5d ] ", options_strings[opt], DELAY); } else if (opt == SAVE_OPT) { mvwprintw(win, opt+2, 3, " %s ", options_strings[opt]); } else { if (opt == HQMIXER_OPT && hq_mixer) c = 'X'; else if (opt == _16BITS_OPT && _16bits) c = 'X'; else if (opt == STEREO_OPT && stereo) c = 'X'; else if (opt == REVSTEREO_OPT && reverse_stereo) c = 'X'; else if (opt == SURROUND_OPT && surround) c = 'X'; else if (opt == INTERPOLATE_OPT && interpolate) c = 'X'; else if (opt == LOOP_OPT && loop_module) c = 'X'; else if (opt == FADE_OPT && fade_module) c = 'X'; else if (opt == RANDOM_OPT && random_mode) c = 'X'; else c = ' '; mvwprintw(win, opt+2, 3, " [%c] %s ", c, options_strings[opt]); } } /*** Get mix frequency from user. ***/ static void get_mix_freq(WINDOW *win) { int c; int freq = md_mixfreq; while ((c = wgetch(win)) != KEY_ENTER) { switch (c) { case ERR: break; case KEY_RIGHT: if (freq*2 < MAX_FREQ) freq *= 2; else freq = MAX_FREQ; break; case KEY_LEFT: if (freq/2 > MIN_FREQ) freq /= 2; else freq = MIN_FREQ; break; case KEY_UP: if (freq < MAX_FREQ) freq++; break; case KEY_PPAGE: if (freq+100 <= MAX_FREQ) freq += 100; break; case KEY_DOWN: if (freq > MIN_FREQ) freq--; break; case KEY_NPAGE: if (freq-100 >= MIN_FREQ) freq -= 100; break; } wattrset(win, A_NORMAL); mvwprintw(win, MIXFREQ_OPT+2, 3, " %s [ ] ", options_strings[MIXFREQ_OPT]); wattrset(win, A_REVERSE); mvwprintw(win, MIXFREQ_OPT+2, 24, " %5d ", freq); if (mod && playing) { refresh_info(); refresh_module_info(); update_panels(); doupdate(); MikMod_Update(); } } md_mixfreq = freq; refresh_driver_info(); } /*** Get DELAY from user. ***/ static void get_delay(WINDOW *win) { int c; int delay = DELAY; while ((c = wgetch(win)) != KEY_ENTER) { switch (c) { case ERR: break; case KEY_RIGHT: if (delay*2 < 10000) delay *= 2; else delay = 10000; break; case KEY_LEFT: if (delay/2 > 0) delay /= 2; else delay = 0; break; case KEY_UP: if (delay < 10000) delay++; break; case KEY_PPAGE: if (delay+5 <= 10000) delay += 5; break; case KEY_DOWN: if (delay > 0) delay--; break; case KEY_NPAGE: if (delay-5 >= 0) delay -= 5; break; } wattrset(win, A_NORMAL); mvwprintw(win, DELAY_OPT+2, 3, " %s [ ] ", options_strings[DELAY_OPT]); wattrset(win, A_REVERSE); mvwprintw(win, DELAY_OPT+2, 21, " %5d ", delay); if (mod && playing) { refresh_info(); refresh_module_info(); update_panels(); doupdate(); MikMod_Update(); } } DELAY = delay; } /*** Read options file. ***/ static void read_options_file(void) { int cnt; FILE *f; char c; char fixed_path[NAME_MAX+1]; char buf[NAME_MAX+1]; char *ptr1; sprintf(fixed_path, "%s/%s", (getenv("HOME")), ".mp/options"); if ((f = fopen(fixed_path, "r")) == NULL) return; cnt = 0; memset(buf, 0, NAME_MAX); while ((fread(&c, 1, 1, f)) > 0) { if (c != '\n') { buf[cnt++] = c; continue; } /* 16bits. */ if (!(strncmp(buf, "16bits", 5))) { ptr1 = rindex(buf, '='); ptr1++; if (atoi(ptr1)) { _16bits=1; } else { _16bits=0; } /* Stereo. */ } else if (!(strncmp(buf, "stereo", 6))) { ptr1 = rindex(buf, '='); ptr1++; if (atoi(ptr1)) { stereo=1; } else { stereo=0; } /* Reverse stereo. */ } else if (!(strncmp(buf, "reverse_stereo", 14))) { ptr1 = rindex(buf, '='); ptr1++; if (atoi(ptr1)) { reverse_stereo=1; } else { reverse_stereo=0; } /* Surround. */ } else if (!(strncmp(buf, "surround", 8))) { ptr1 = rindex(buf, '='); ptr1++; if (atoi(ptr1)) { surround=1; } else { surround=0; } /* Interpolate. */ } else if (!(strncmp(buf, "interpolate", 11))) { ptr1 = rindex(buf, '='); ptr1++; if ((atoi(ptr1)) == 1) { interpolate=1; } else { interpolate=0; } /* HQ mixer. */ } else if (!(strncmp(buf, "hq_mixer", 8))) { ptr1 = rindex(buf, '='); ptr1++; if ((atoi(ptr1)) == 1) { hq_mixer=1; } else { hq_mixer=0; } /* Loop module. */ } else if (!(strncmp(buf, "loop_module", 11))) { ptr1 = rindex(buf, '='); ptr1++; if ((atoi(ptr1)) == 1) { loop_module=1; } else { loop_module=0; } /* Fadeout module. */ } else if (!(strncmp(buf, "fade_module", 11))) { ptr1 = rindex(buf, '='); ptr1++; if ((atoi(ptr1)) == 1) { fade_module=1; } else { fade_module=0; } /* Random mode (playlist). */ } else if (!(strncmp(buf, "random_mode", 11))) { ptr1 = rindex(buf, '='); ptr1++; if (atoi(ptr1)) { random_mode=1; } else { random_mode=0; } /* Screen refresh delay. */ } else if (!(strncmp(buf, "delay", 5))) { ptr1 = rindex(buf, '='); ptr1++; DELAY = atoi(ptr1); /*** Windows coords. ***/ } else if (!(strncmp(buf, "AC_X", 4))) { ptr1 = rindex(buf, '='); ptr1++; AC_X=atoi(ptr1); } else if (!(strncmp(buf, "AC_Y", 4))) { ptr1 = rindex(buf, '='); ptr1++; AC_Y=atoi(ptr1); } else if (!(strncmp(buf, "VFREQ_X", 7))) { ptr1 = rindex(buf, '='); ptr1++; VFREQ_X=atoi(ptr1); } else if (!(strncmp(buf, "VFREQ_Y", 7))) { ptr1 = rindex(buf, '='); ptr1++; VFREQ_Y=atoi(ptr1); } else if (!(strncmp(buf, "VPOS_X", 6))) { ptr1 = rindex(buf, '='); ptr1++; VPOS_X=atoi(ptr1); } else if (!(strncmp(buf, "VPOS_Y", 6))) { ptr1 = rindex(buf, '='); ptr1++; VPOS_Y=atoi(ptr1); } else if (!(strncmp(buf, "OPT_X", 5))) { ptr1 = rindex(buf, '='); ptr1++; OPT_X=atoi(ptr1); } else if (!(strncmp(buf, "OPT_Y", 5))) { ptr1 = rindex(buf, '='); ptr1++; OPT_Y=atoi(ptr1); } else if (!(strncmp(buf, "EFT_X", 5))) { ptr1 = rindex(buf, '='); ptr1++; EFT_X=atoi(ptr1); } else if (!(strncmp(buf, "EFT_Y", 5))) { ptr1 = rindex(buf, '='); ptr1++; EFT_Y=atoi(ptr1); } cnt = 0; memset(buf, 0, NAME_MAX); } /* Check coords. */ if (EFT_Y+EFT_H >= LINES) EFT_Y = 2; if (OPT_Y+OPT_H >= LINES) OPT_Y = 2; if (VFREQ_Y+VFREQ_H >= LINES) VFREQ_Y = 2; if (VPOS_Y+VPOS_H >= LINES) VPOS_Y = 2; if (AC_Y+AC_H >= LINES) AC_Y = 2; fclose(f); } /*** Save options file. ***/ static void save_options_file(void) { FILE *f; char fixed_path[NAME_MAX+1]; char buf[NAME_MAX+1]; sprintf(fixed_path, "%s/%s", (getenv("HOME")), ".mp/options"); f = fopen(fixed_path, "w"); if (f == NULL) { sprintf(buf, "Can't open '%s'.", fixed_path); message(buf, ERROR_MSG); return; } /* 16bits. */ if (_16bits) { sprintf(buf, "16bits=1\n"); fwrite(buf, strlen(buf), 1, f); } else { sprintf(buf, "16bits=0\n"); fwrite(buf, strlen(buf), 1, f); } /* Stereo. */ if (stereo) { sprintf(buf, "stereo=1\n"); fwrite(buf, strlen(buf), 1, f); } else { sprintf(buf, "stereo=0\n"); fwrite(buf, strlen(buf), 1, f); } /* Stereo. */ if (reverse_stereo) { sprintf(buf, "reverse_stereo=1\n"); fwrite(buf, strlen(buf), 1, f); } else { sprintf(buf, "reverse_stereo=0\n"); fwrite(buf, strlen(buf), 1, f); } /* Surround. */ if (surround) { sprintf(buf, "surround=1\n"); fwrite(buf, strlen(buf), 1, f); } else { sprintf(buf, "surround=0\n"); fwrite(buf, strlen(buf), 1, f); } /* Interpolate. */ if (interpolate) { sprintf(buf, "interpolate=1\n"); fwrite(buf, strlen(buf), 1, f); } else { sprintf(buf, "interpolate=0\n"); fwrite(buf, strlen(buf), 1, f); } /* HQ/LQ mixer. */ if (hq_mixer) { sprintf(buf, "hq_mixer=1\n"); fwrite(buf, strlen(buf), 1, f); } else { sprintf(buf, "hq_mixer=0\n"); fwrite(buf, strlen(buf), 1, f); } /* Loop module. */ if (loop_module) { sprintf(buf, "loop_module=1\n"); fwrite(buf, strlen(buf), 1, f); } else { sprintf(buf, "loop_module=0\n"); fwrite(buf, strlen(buf), 1, f); } /* Fadeout module. */ if (fade_module) { sprintf(buf, "fade_module=1\n"); fwrite(buf, strlen(buf), 1, f); } else { sprintf(buf, "fade_module=0\n"); fwrite(buf, strlen(buf), 1, f); } /* Random mode. */ if (random_mode) { sprintf(buf, "random_mode=1\n"); fwrite(buf, strlen(buf), 1, f); } else { sprintf(buf, "random_mode=0\n"); fwrite(buf, strlen(buf), 1, f); } /* Screen refresh delay. */ sprintf(buf, "delay=%d\n", DELAY); fwrite(buf, strlen(buf), 1, f); /* Windows coords. */ sprintf(buf, "AC_X=%d\n", AC_X); fwrite(buf, strlen(buf), 1, f); sprintf(buf, "AC_Y=%d\n", AC_Y); fwrite(buf, strlen(buf), 1, f); sprintf(buf, "VPOS_X=%d\n", VPOS_X); fwrite(buf, strlen(buf), 1, f); sprintf(buf, "VPOS_Y=%d\n", VPOS_Y); fwrite(buf, strlen(buf), 1, f); sprintf(buf, "VFREQ_X=%d\n", VFREQ_X); fwrite(buf, strlen(buf), 1, f); sprintf(buf, "VFREQ_Y=%d\n", VFREQ_Y); fwrite(buf, strlen(buf), 1, f); sprintf(buf, "OPT_X=%d\n", OPT_X); fwrite(buf, strlen(buf), 1, f); sprintf(buf, "OPT_Y=%d\n", OPT_Y); fwrite(buf, strlen(buf), 1, f); sprintf(buf, "EFT_X=%d\n", EFT_X); fwrite(buf, strlen(buf), 1, f); sprintf(buf, "EFT_Y=%d\n", EFT_Y); fwrite(buf, strlen(buf), 1, f); fclose(f); sprintf(buf, "'%s' saved.", fixed_path); message(buf, INFO_MSG); } /*** Enter options window. ***/ static void options(void) { int c, opt = 0; WINDOW *tmpwin; optwin = tmpwin = newwin(OPT_H, OPT_W, OPT_Y, OPT_X); wtimeout(tmpwin, DELAY); keypad(tmpwin, TRUE); box(tmpwin, 0, 0); optpan = new_panel(tmpwin); wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL); mvwprintw(tmpwin, 0, 2, "[ ]"); wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD); mvwprintw(tmpwin, 0, 4, "Options"); /* Prepare display. */ for (c = 0; c < OPTIONS+4; c++) { if (strlen(options_strings[c]) == 0) { mvwprintw(tmpwin, c+2, 1, ""); continue; } if (c == 0) wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE)); else wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL)); print_opt(tmpwin, c); } wnoutrefresh(tmpwin); doupdate(); /*** Loop. ***/ while ((c = wgetch(tmpwin)) != 'q') { if (c == KEY_ESCAPE) break; if (c == 'm') mp_move_panel(optpan); switch (c) { case ERR: case KEY_ESCAPE: break; case KEY_ENTER: /* HQ/LQ mixer. */ if (opt == HQMIXER_OPT) { hq_mixer = 1-hq_mixer; if (!hq_mixer) { md_mode &= ~DMODE_HQMIXER; } else md_mode |= DMODE_HQMIXER; refresh_driver_info(); /* 16 bit */ } else if (opt == _16BITS_OPT) { _16bits = 1-_16bits; if (!_16bits) md_mode &= ~DMODE_16BITS; else md_mode |= DMODE_16BITS; refresh_driver_info(); /* Stereo */ } else if (opt == STEREO_OPT) { stereo = 1-stereo; if (!stereo) { md_mode &= ~DMODE_STEREO; if (reverse_stereo) { md_mode &= ~DMODE_REVERSE; reverse_stereo = 1-reverse_stereo; } } else md_mode |= DMODE_STEREO; refresh_driver_info(); /* Surround */ } else if (opt == SURROUND_OPT) { surround = 1-surround; if (!surround) { md_mode &= ~DMODE_SURROUND; } else md_mode |= DMODE_SURROUND; refresh_driver_info(); /* Mix freqency */ } else if (opt == MIXFREQ_OPT) { get_mix_freq(tmpwin); /* Loop module */ } else if (opt == LOOP_OPT) { loop_module = 1-loop_module; mod->loop = loop_module; /* Fadeout */ } else if (opt == FADE_OPT) { fade_module = 1-fade_module; mod->fadeout = fade_module; /* Reverse stereo */ } else if (opt == REVSTEREO_OPT) { if (md_mode & DMODE_STEREO) reverse_stereo = 1-reverse_stereo; else break; if (!reverse_stereo) { md_mode &= ~DMODE_REVERSE; } else md_mode |= DMODE_REVERSE; refresh_driver_info(); /* Interpolate */ } else if (opt == INTERPOLATE_OPT) { interpolate = 1-interpolate; if (!interpolate) { md_mode &= ~DMODE_INTERP; } else md_mode |= DMODE_INTERP; /* Random */ } else if (opt == RANDOM_OPT) { random_mode = 1-random_mode; /* Delay */ } else if (opt == DELAY_OPT) { get_delay(tmpwin); /* Save file */ } else if (opt == SAVE_OPT) { save_options_file(); } wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE)); print_opt(tmpwin, opt); break; /* Select option. */ case KEY_UP: wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL)); print_opt(tmpwin, opt); if (opt == 6 || opt == 9 || opt == 13 || opt == 15) opt -= 2; else if (opt > 0) opt--; wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE)); print_opt(tmpwin, opt); break; case KEY_PPAGE: wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL)); print_opt(tmpwin, opt); opt = 0; wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE)); print_opt(tmpwin, opt); break; case KEY_DOWN: wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL)); print_opt(tmpwin, opt); if (opt == 4 || opt == 7 || opt == 11 || opt == 13) opt += 2; else if (opt < (OPTIONS+3)-1) opt++; wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE)); print_opt(tmpwin, opt); break; case KEY_NPAGE: wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL)); print_opt(tmpwin, opt); opt = 15; wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE)); print_opt(tmpwin, opt); break; } if (mod && playing) { refresh_info(); refresh_module_info(); MikMod_Update(); } update_panels(); doupdate(); } del_panel(optpan); update_panels(); doupdate(); } /*** *** Effects panel. ***/ static void effects(void) { int i; int c; int pc; int effect = 0; float f1, f2; char *effect_strings[EFFECTS] = { " Speed ", " Tempo ", " BPM ", " Reverb ", " Stereo ", " Gen Vol ", " Mod Vol ", " Mix Vol ", " Bass ", " Treble " }; eftwin = newwin(EFT_H, EFT_W, EFT_Y, EFT_X); wtimeout(eftwin, DELAY); keypad(eftwin, TRUE); box(eftwin, 0, 0); eftpan = new_panel(eftwin); top_panel(eftpan); wattrset(eftwin, (COLOR_PAIR(WHITE)|A_NORMAL)); mvwprintw(eftwin, 0, 2, "[ ]"); wattrset(eftwin, COLOR_PAIR(YELLOW)|A_BOLD); mvwprintw(eftwin, 0, 4, "Effects"); /* Prepare display. */ for (c = 0; c < EFFECTS; c++) { wattrset(eftwin, (COLOR_PAIR(WHITE)|A_NORMAL)); if (c == 0) wattrset(eftwin, (COLOR_PAIR(WHITE)|A_REVERSE)); mvwprintw(eftwin, c+2, 1, effect_strings[c]); switch (c) { case 0: /* speed */ f1 = mod->sngspd; f2 = SPEED_LIMIT; pc = 100*(f1/f2); pc = 100-pc; draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style); break; case 1: /* tempo */ f1 = mod->inittempo; f2 = TEMPO_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style); break; case 2: /* BPM */ f1 = mod->bpm; f2 = BPM_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style); break; case 3: /* reverb */ f1 = md_reverb; f2 = REVERB_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style); break; case 4: /* stereo */ f1 = md_pansep; f2 = STEREO_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style); break; case 5: /* general volume */ f1 = md_volume; f2 = GENVOL_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style); break; case 6: /* module volume */ f1 = mod->volume; f2 = MODVOL_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style); break; case 7: /* mixer volume */ f1 = mixvol; f2 = MIXVOL_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style); break; case 8: /* bass level */ f1 = bass; f2 = BASS_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style); break; case 9: /* treble level */ f1 = treble; f2 = TREBLE_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style); break; } } /*** Loop ***/ while ((c = wgetch(eftwin)) != 'q') { if (c == KEY_ESCAPE) break; if (c == 'm') mp_move_panel(eftpan); switch (c) { case ERR: break; /* UP */ case KEY_UP: wattrset(eftwin, (COLOR_PAIR(WHITE)|A_NORMAL)); mvwprintw(eftwin, effect+2, 1, effect_strings[effect]); if (effect > 0) effect--; wattrset(eftwin, (COLOR_PAIR(WHITE)|A_REVERSE)); mvwprintw(eftwin, effect+2, 1, effect_strings[effect]); break; case KEY_PPAGE: wattrset(eftwin, (COLOR_PAIR(WHITE)|A_NORMAL)); mvwprintw(eftwin, effect+2, 1, effect_strings[effect]); effect = 0; wattrset(eftwin, (COLOR_PAIR(WHITE)|A_REVERSE)); mvwprintw(eftwin, effect+2, 1, effect_strings[effect]); break; /* DOWN */ case KEY_DOWN: wattrset(eftwin, (COLOR_PAIR(WHITE)|A_NORMAL)); mvwprintw(eftwin, effect+2, 1, effect_strings[effect]); if (effect < EFFECTS-1) effect++; wattrset(eftwin, (COLOR_PAIR(WHITE)|A_REVERSE)); mvwprintw(eftwin, effect+2, 1, effect_strings[effect]); break; case KEY_NPAGE: wattrset(eftwin, (COLOR_PAIR(WHITE)|A_NORMAL)); mvwprintw(eftwin, effect+2, 1, effect_strings[effect]); effect = EFFECTS-1; wattrset(eftwin, (COLOR_PAIR(WHITE)|A_REVERSE)); mvwprintw(eftwin, effect+2, 1, effect_strings[effect]); break; case KEY_LEFT: switch (effect) { case 0: /* speed */ if (mod->sngspd < SPEED_LIMIT) mod->sngspd++; f1 = mod->sngspd; f2 = SPEED_LIMIT; pc = 100*(f1/f2); pc = 100-pc; draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 1: /* tempo */ if (mod->inittempo > 0) mod->inittempo--; f1 = mod->inittempo; f2 = TEMPO_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 2: /* BPM */ if (mod->bpm > 1) mod->bpm--; f1 = mod->bpm; f2 = BPM_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 3: /* reverb */ if (md_reverb > 0) md_reverb--; f1 = md_reverb; f2 = REVERB_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 4: /* stereo */ if (md_pansep > 0) md_pansep--; f1 = md_pansep; f2 = STEREO_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 5: /* general volume */ if (md_volume > 0) md_volume--; f1 = md_volume; f2 = GENVOL_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 6: /* module volume */ if (mod->volume > 0) mod->volume--; f1 = mod->volume; f2 = MODVOL_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 7: /* mixer volume */ if (mixvol > 771) mixvol -= 771; else mixvol = 0; f1 = mixvol; f2 = MIXVOL_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); ioctl( mixerfd, MIXER_WRITE(SOUND_MIXER_VOLUME), &mixvol ); break; case 8: /* mixer bass */ if (bass > 0) bass--; f1 = bass; f2 = BASS_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); ioctl( mixerfd, MIXER_WRITE(SOUND_MIXER_BASS), &bass ); break; case 9: /* mixer treble */ if (treble > 0) treble--; f1 = treble; f2 = TREBLE_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); ioctl( mixerfd, MIXER_WRITE(SOUND_MIXER_TREBLE), &treble ); break; } break; case KEY_RIGHT: switch (effect) { case 0: /* speed */ if (mod->sngspd > 0) mod->sngspd--; f1 = mod->sngspd; f2 = SPEED_LIMIT; pc = 100*(f1/f2); pc = 100-pc; draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 1: /* tempo */ if (mod->inittempoinittempo++; f1 = mod->inittempo; f2 = TEMPO_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 2: /* BPM */ if (mod->bpm < BPM_LIMIT) mod->bpm++; f1 = mod->bpm; f2 = BPM_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 3: /* reverb */ if (md_reverb < REVERB_LIMIT) md_reverb++; f1 = md_reverb; f2 = REVERB_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 4: /* stereo */ if (md_pansep < STEREO_LIMIT) md_pansep++; f1 = md_pansep; f2 = STEREO_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 5: /* general volume */ if (md_volume < GENVOL_LIMIT) md_volume++; f1 = md_volume; f2 = GENVOL_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 6: /* module volume */ if (mod->volume < MODVOL_LIMIT) mod->volume++; f1 = mod->volume; f2 = MODVOL_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); break; case 7: /* mixer volume */ if (mixvol < MIXVOL_LIMIT) mixvol += 771; f1 = mixvol; f2 = MIXVOL_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); ioctl( mixerfd, MIXER_WRITE(SOUND_MIXER_VOLUME), &mixvol ); break; case 8: /* mixer bass */ if (bass < BASS_LIMIT) bass++; f1 = bass; f2 = BASS_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); i = (bass * 16); ioctl( mixerfd, MIXER_WRITE(SOUND_MIXER_BASS), &i ); break; case 9: /* mixer treble */ if (treble < TREBLE_LIMIT) treble++; f1 = treble; f2 = TREBLE_LIMIT; pc = 100*(f1/f2); draw_gauge(eftwin, 12, effect+2, pc, 1, gauge_style); ioctl( mixerfd, MIXER_WRITE(SOUND_MIXER_TREBLE), &treble ); break; } break; } if (mod && playing) { refresh_info(); refresh_module_info(); MikMod_Update(); } update_panels(); doupdate(); } del_panel(eftpan); touchwin(dspwin); doupdate(); } /*****************************************************************************/ /*** *** Instruments panel. ***/ int insnum; /* instrument number */ INSTRUMENT *curins; /* pointer to current instrument */ int ins_val; /* used for buttons */ /*** Show instrument. ***/ static void show_instrument(WINDOW *win, INSTRUMENT *ins, int num) { if (mod->instruments == NULL) { message("No instruments in this module.", ERROR_MSG); return; } wattrset(win, A_BOLD); mvwprintw(win, 2, 1, " #: "); wattrset(win, A_NORMAL); wprintw(win, "%-4d/%4d", num, mod->numins); wattrset(win, A_BOLD); mvwprintw(win, 3, 1, " Name: "); wattrset(win, A_NORMAL); wprintw(win, "%-40s", ins->insname); wattrset(win, A_BOLD); mvwprintw(win, 4, 1, " Flags: "); wattrset(win, A_NORMAL); wprintw(win, "0x%04x", ins->flags); wattrset(win, A_BOLD); mvwprintw(win, 5, 1, " Pan: "); wattrset(win, A_NORMAL); wprintw(win, "%-3d", ins->panning); wattrset(win, A_BOLD); mvwprintw(win, 6, 1, " Vol: "); wattrset(win, A_NORMAL); wprintw(win, "%-4d", ins->globvol); } /*** Instruments window buttons. ***/ static int ins_buttons(WINDOW *win) { int i, c; int in_loop = 1; char *ins_btns[3] = { "[ Next ]", "[ Prev ]", // "[ Play ]", // "[ Stop ]", "[ Quit ]" }; ins_val = 0; wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL); for (i = 0; i < 3; i++) { if (ins_val == i) wattrset(win, A_REVERSE); else wattrset(win, A_NORMAL); mvwprintw(win, INS_H-3, 5+(i*18), "%s", ins_btns[i]); } while (in_loop) { switch ((c = wgetch(win))) { case KEY_ESCAPE: case 'q': ins_val = 2; in_loop = 0; break; case KEY_RIGHT: wattrset(win, A_NORMAL); mvwprintw(win, INS_H-3, 5+(ins_val*18), "%s", ins_btns[ins_val]); if (ins_val < 2) ins_val++; wattrset(win, A_REVERSE); mvwprintw(win, INS_H-3, 5+(ins_val*18), "%s", ins_btns[ins_val]); break; case KEY_LEFT: wattrset(win, A_NORMAL); mvwprintw(win, INS_H-3, 5+(ins_val*18), "%s", ins_btns[ins_val]); if (ins_val > 0) ins_val--; wattrset(win, A_REVERSE); mvwprintw(win, INS_H-3, 5+(ins_val*18), "%s", ins_btns[ins_val]); break; case KEY_ENTER: /* Next. */ if (ins_val == 0) { if (insnum < mod->numins-1) { insnum++; curins++; show_instrument(win, curins, insnum+1); } /* Previous. */ } else if (ins_val == 1) { if (insnum > 0) { insnum--; curins--; show_instrument(win, curins, insnum+1); } /* Play. */ /*} else if (ins_val == 2) { int i = Sample_Play(cursmp, 1, 0); fprintf(stderr, "%d\n", i);*/ /* Stop. */ /*} else if (ins_val == 3) {*/ /* Quit. */ } else if (ins_val == 2) { in_loop = 0; continue; } break; } if (mod && playing) { refresh_module_info(); refresh_info(); update_panels(); doupdate(); MikMod_Update(); } } return ins_val; } /*** Open instruments window. ***/ void show_instruments(void) { int i; WINDOW *tmpwin; inswin = tmpwin = newwin(INS_H, INS_W, INS_Y, INS_X); wtimeout(tmpwin, DELAY); keypad(tmpwin, TRUE); box(tmpwin, 0, 0); inspan = new_panel(inswin); wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL); mvwprintw(tmpwin, 0, 2, "[ ]"); wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD); mvwprintw(tmpwin, 0, 4, "Instruments"); wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL); for (i = 1; i < INS_W-1; i++) mvwaddch(tmpwin, INS_H-5, i, ACS_HLINE); mvwaddch(tmpwin, INS_H-5, 0, ACS_LTEE); mvwaddch(tmpwin, INS_H-5, INS_W-1, ACS_RTEE); insnum = 0; curins = mod->instruments; show_instrument(tmpwin, mod->instruments, insnum+1); ins_buttons(tmpwin); del_panel(inspan); touchwin(dspwin); update_panels(); doupdate(); } /*****************************************************************************/ /*** *** Sample window. ***/ int smpnum; /* sample number */ SAMPLE *cursmp; /* pointer to current sample */ int smp_val; /* used for buttons */ /*** Show sample. ***/ static void show_sample(WINDOW *win, SAMPLE *smp, int num) { wattrset(win, A_BOLD); mvwprintw(win, 2, 1, " #: "); wattrset(win, A_NORMAL); wprintw(win, "%-4d/%4d", num, mod->numsmp); wattrset(win, A_BOLD); mvwprintw(win, 3, 1, " Name: "); wattrset(win, A_NORMAL); wprintw(win, "%-40s", smp->samplename); wattrset(win, A_BOLD); mvwprintw(win, 4, 1, " "); mvwprintw(win, 4, 1, " Flags: "); wattrset(win, A_NORMAL); if (smp->flags & SF_16BITS) wprintw(win, "16bit "); if (smp->flags & SF_STEREO) wprintw(win, "stereo "); if (smp->flags & SF_SIGNED) wprintw(win, "signed "); if (smp->flags & SF_ITPACKED) wprintw(win, "IT_packed "); if (smp->flags & SF_BIDI) wprintw(win, "bidir "); if (smp->flags & SF_LOOP) wprintw(win, "loop "); if (smp->flags & SF_REVERSE) wprintw(win, "reverse "); if (smp->flags & SF_OWNPAN) wprintw(win, "own_pan "); wprintw(win, "(0x%04x)", smp->flags); wattrset(win, A_BOLD); mvwprintw(win, 5, 1, "Length: "); wattrset(win, A_NORMAL); wprintw(win, "%-8d", smp->length); wattrset(win, A_BOLD); mvwprintw(win, 6, 1, " Pan: "); wattrset(win, A_NORMAL); wprintw(win, "%-3d", smp->panning); wattrset(win, A_BOLD); mvwprintw(win, 7, 1, " Speed: "); wattrset(win, A_NORMAL); wprintw(win, "%-6d", smp->speed); wattrset(win, A_BOLD); mvwprintw(win, 8, 1, " Vol: "); wattrset(win, A_NORMAL); wprintw(win, "%-4d (glob. %-4d)", smp->volume, smp->globvol); } /*** Samples window buttons. ***/ static int smp_buttons(WINDOW *win) { int i, c; int in_loop = 1; char *smp_btns[3] = { "[ Next ]", "[ Prev ]", // "[ Play ]", // "[ Stop ]", "[ Quit ]" }; smp_val = 0; wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL); for (i = 0; i < 3; i++) { if (smp_val == i) wattrset(win, A_REVERSE); else wattrset(win, A_NORMAL); mvwprintw(win, SMP_H-3, 5+(i*18), "%s", smp_btns[i]); } while (in_loop) { switch ((c = wgetch(win))) { case KEY_ESCAPE: case 'q': smp_val = 2; in_loop = 0; break; case 'm': mp_move_panel(smppan); break; case KEY_RIGHT: wattrset(win, A_NORMAL); mvwprintw(win, SMP_H-3, 5+(smp_val*18), "%s", smp_btns[smp_val]); if (smp_val < 2) smp_val++; wattrset(win, A_REVERSE); mvwprintw(win, SMP_H-3, 5+(smp_val*18), "%s", smp_btns[smp_val]); break; case KEY_LEFT: wattrset(win, A_NORMAL); mvwprintw(win, SMP_H-3, 5+(smp_val*18), "%s", smp_btns[smp_val]); if (smp_val > 0) smp_val--; wattrset(win, A_REVERSE); mvwprintw(win, SMP_H-3, 5+(smp_val*18), "%s", smp_btns[smp_val]); break; case KEY_ENTER: /* Next. */ if (smp_val == 0) { if (smpnum < mod->numsmp-1) { smpnum++; cursmp++; show_sample(win, cursmp, smpnum+1); } /* Previous. */ } else if (smp_val == 1) { if (smpnum > 0) { smpnum--; cursmp--; show_sample(win, cursmp, smpnum+1); } /* Play. */ /*} else if (smp_val == 2) { int i = Sample_Play(cursmp, 1, 0); fprintf(stderr, "%d\n", i);*/ /* Stop. */ /*} else if (smp_val == 3) {*/ /* Quit. */ } else if (smp_val == 2) { in_loop = 0; continue; } break; } if (mod && playing) { refresh_module_info(); refresh_info(); update_panels(); doupdate(); MikMod_Update(); } } return smp_val; } /*** Open samples window. ***/ void show_samples(void) { int i; WINDOW *tmpwin; smpwin = tmpwin = newwin(SMP_H, SMP_W, SMP_Y, SMP_X); wtimeout(tmpwin, DELAY); keypad(tmpwin, TRUE); box(tmpwin, 0, 0); smppan = new_panel(tmpwin); wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL); mvwprintw(tmpwin, 0, 2, "[ ]"); wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD); mvwprintw(tmpwin, 0, 4, "Samples"); wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL); for (i = 1; i < SMP_W-1; i++) mvwaddch(tmpwin, SMP_H-5, i, ACS_HLINE); mvwaddch(tmpwin, SMP_H-5, 0, ACS_LTEE); mvwaddch(tmpwin, SMP_H-5, SMP_W-1, ACS_RTEE); smpnum = 0; cursmp = mod->samples; show_sample(tmpwin, mod->samples, smpnum+1); smp_buttons(tmpwin); del_panel(smppan); delwin(smpwin); touchwin(dspwin); update_panels(); doupdate(); } /*****************************************************************************/ /*** *** Various functions. ***/ /*** Get a string from anywhere in a window. ***/ char getstrtab = 0; static void get_string(WINDOW *win, int ys, int xs, char *prompt, char *str) { int slen = strlen(prompt) + strlen(str); int c, i, j, k; int piece; int in_loop = 1; int x = xs + slen; int maxlen = 57 - strlen(prompt); char strbuf[NAME_MAX+1], *bufp = strbuf; k = i = strlen(str); mvwprintw(win, ys, xs, "%s%s", prompt, str); curs_set(TRUE); wnoutrefresh(win); doupdate(); /*** Loop ***/ getstrtab = 0; while (in_loop) { switch ((c = wgetch(win))) { case ERR: break; case KEY_ENTER: in_loop = 0; continue; break; case KEY_DELETE: case KEY_BACKSPACE: if (x == xs+strlen(prompt)) { beep(); break; } if (i == 1 || (k % maxlen-1)) { str[--i] = 0; mvwaddch(win, ys, x--, '\b'); waddch(win, ' '); waddch(win, '\b'); k--; } else { piece = (i / maxlen); bufp = strbuf; sprintf(bufp, str); bufp += (piece * maxlen); bufp[maxlen] = '\0'; if (piece > 0) bufp[0] = '~'; k = strlen(bufp); j = strlen(prompt); for (; j < FS_W-2; j++) mvwaddch(win, ys, j, ' '); x = xs + (strlen(prompt) + strlen(bufp)); mvwprintw(win, ys, xs, "%s%s", prompt, bufp); } break; /* case KEY_LEFT: if (x == xs+strlen(prompt)+1) { beep(); break; } wmove(win, ys, --x); i--; break; case KEY_RIGHT: if (x == 48) { beep(); break; } wmove(win, ys, --x); i++; break; */ case KEY_ESCAPE: in_loop = 0; continue; break; case KEY_TAB: getstrtab = 1; in_loop = 0; continue; break; /* Ignored characters. */ case KEY_UP: case KEY_DOWN: case KEY_LEFT: case KEY_RIGHT: break; /* Add character. */ default: if (i >= NAME_MAX) { beep(); break; } if (i == 0 || (k % maxlen)) { str[i++] = (char ) c; mvwaddch(win, ys, x++, c); k++; } else { bufp = strbuf; sprintf(bufp, str); bufp += i-4; bufp[0] = '~'; bufp[5] = '\0'; k = 5; j = strlen(prompt); for (; j < FS_W-2; j++) mvwaddch(win, ys, j, ' '); x = xs + (strlen(prompt) + strlen(bufp)); mvwprintw(win, ys, xs, "%s%s", prompt, bufp); str[i++] = (char ) c; mvwaddch(win, ys, x++, c); } break; } if (mod && playing) { refresh_info(); refresh_module_info(); update_panels(); doupdate(); MikMod_Update(); } } str[i] = '\0'; curs_set(FALSE); touchwin(dspwin); doupdate(); } /*** Move panel. ***/ static void mp_move_panel(PANEL *pan) { int c; int x = pan->win->_begx, y = pan->win->_begy; while ((c = wgetch(pan->win)) != KEY_ENTER || c == KEY_ESCAPE) { switch (c) { case KEY_UP: if (y) move_panel(pan, --y, x); break; case KEY_DOWN: if (y < (LINES-(pan->win->_maxy+1))) move_panel(pan, ++y, x); break; case KEY_LEFT: if (x) move_panel(pan, y, --x); break; case KEY_RIGHT: if (x < (COLS-(pan->win->_maxx+1))) move_panel(pan, y, ++x); break; } if (mod && playing) { refresh_info(); refresh_module_info(); MikMod_Update(); } update_panels(); doupdate(); } if (pan->win == acwin) { AC_X = acwin->_begx; AC_Y = acwin->_begy; } else if (pan->win == helpwin) { HELP_X = helpwin->_begx; HELP_Y = helpwin->_begy; } else if (pan->win == vfreqwin) { VFREQ_X = vfreqwin->_begx; VFREQ_Y = vfreqwin->_begy; } else if (pan->win == vposwin) { VPOS_X = vposwin->_begx; VPOS_Y = vposwin->_begy; } else if (pan->win == eftwin) { EFT_X = eftwin->_begx; EFT_Y = eftwin->_begy; } else if (pan->win == optwin) { OPT_X = optwin->_begx; OPT_Y = optwin->_begy; } else if (pan->win == smpwin) { SMP_X = smpwin->_begx; SMP_Y = smpwin->_begy; } } /*****************************************************************************/ /*** *** File selector. ***/ /*** Variables. ***/ int fs_val; int current, nument; int fspage = 0, lastpage = 0; struct dirent *drent[MAX_FILES]; char dname[MAX_FILES][NAME_MAX+1]; char dnamed[MAX_FILES][NAME_MAX+1]; char dnamef[MAX_FILES][NAME_MAX+1]; DIR *dentry = NULL; char modpath[NAME_MAX+1]; char dirname[NAME_MAX+1]; char filename[NAME_MAX+1]; char lastdir[NAME_MAX+1]; /*** List directory content in window win (without reading). ***/ static void list_dir(WINDOW *win) { int y; int cnt = fspage*(FS_H-10); struct stat sbuf; char strbuf[NAME_MAX+1]; for (y = 5; y < FS_H-5; y++, cnt++) { if ((drent[cnt]) == NULL) break; strncpy(strbuf, dname[cnt], 48); strbuf[48] = '\0'; stat(dname[cnt], &sbuf); file_size = (((float)(sbuf.st_size)) / 1024.0); file_sizeb = sbuf.st_size; if (S_ISDIR(sbuf.st_mode)) { wattrset(win, COLOR_PAIR(WHITE)|A_BOLD); mvwprintw(win, y, 1, "%-48s", strbuf); wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(win, " "); } else { wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL); mvwprintw(win, y, 1, "%-48s %9d", strbuf, file_sizeb); } } for (; y < FS_H-5; y++) mvwprintw(win, y, 1, "%-58s", ""); } /*** Print the directory content in window win. ***/ static void print_dir(WINDOW *win) { int i; int y; int cnt; int d = 0, f = 0; char strbuf[NAME_MAX+1]; struct stat _sbuf, *sbuf = &_sbuf; wattrset(win, A_NORMAL); mvwprintw(win, 2, 1, "Dir: %-52s", dirname); wattrset(win, A_BOLD); mvwaddch(win, 2, 1, 'D'); wattrset(win, A_NORMAL); /* Read dir. */ cnt = 0, nument = 0; while ((drent[cnt] = readdir(dentry)) != NULL) { if ((strcmp(drent[cnt]->d_name, ".")) == 0) continue; stat(drent[cnt]->d_name, sbuf); if (S_ISDIR(sbuf->st_mode)) strcpy(dnamed[d++], drent[cnt]->d_name); else strcpy(dnamef[f++], drent[cnt]->d_name); cnt++, nument++; } drent[cnt] = NULL; /* Copy dir and file name to entries name buffer * (this is needed by list_dir). */ for (i = 0, cnt = 0; i < d; i++, cnt++) strcpy(dname[cnt], dnamed[i]); for (i = 0; i < f; i++, cnt++) strcpy(dname[cnt], dnamef[i]); /* Print entries. */ for (y = 0, i = 0; i < FS_H-10; i++, y++) { if (i == nument) break; strncpy(strbuf, dname[i+current], 48); strbuf[48] = '\0'; stat(dname[i+current], sbuf); file_size = (((float)(sbuf->st_size)) / 1024.0); file_sizeb = sbuf->st_size; if (S_ISDIR(sbuf->st_mode)) { if (i == current) wattrset(win, COLOR_PAIR(CYAN_BLUE)|A_BOLD); else wattrset(win, COLOR_PAIR(WHITE)|A_BOLD); mvwprintw(win, y+5, 1, "%-48s", strbuf); wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(win, " "); } else { if (i == current) wattrset(win, COLOR_PAIR(CYAN_BLUE)|A_BOLD); else wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL); mvwprintw(win, y+5, 1, "%-48s %9d", strbuf, file_sizeb); } } wattrset(win, A_NORMAL); for (; y < FS_H-10; y++) mvwprintw(win, y+5, 1, "%-58s", ""); wnoutrefresh(win); } /*** Check symlink. ***/ static int check_symlink(char *dir) { int i; char strbuf[NAME_MAX+1], *ptr; i = readlink(dir, strbuf, NAME_MAX); switch (i) { case 0: case -1: return -1; break; default: /* not added by readlink */ if (strbuf[i-1] == '/') strbuf[i-1] = '\0'; else { strbuf[i] = '\0'; } if (strbuf[0] == '/') { /* absolute path */ sprintf(dirname, strbuf); } else { i = strlen((ptr = rindex(dir, '/'))); fprintf(stderr, "%s\n", strbuf); sprintf(ptr+1, strbuf); } break; } return 0; } /*** Check directory entry. ***/ static void check_dentry(char *name, WINDOW *win) { char *tmpstr; char strbuf[NAME_MAX+1]; int len1, len2, len3; struct stat _sbuf, *sbuf = &_sbuf; check_symlink(dirname); stat(name, sbuf); if (S_ISDIR(sbuf->st_mode)) { if (strcmp(name, "..") == 0) { len1 = strlen(dirname); len2 = strlen(tmpstr = rindex(dirname, '/')); len3 = len1 - len2; if (len3 == 0) sprintf(dirname, "/"); else dirname[len3] = '\0'; } else { if (strlen(dirname) == 1) sprintf(dirname, "%s%s", dirname, name); else sprintf(dirname, "%s/%s", dirname, name); } check_symlink(name); chdir(name); dentry=opendir("."); current = 0; print_dir(win); closedir(dentry); mvwprintw(win, FS_H-4, 1, "%-48s", "File:"); wattrset(win, A_BOLD); mvwaddch(win, FS_H-4, 1, 'F'); wattrset(win, A_NORMAL); } else if (S_ISREG(sbuf->st_mode)) { wattrset(win, (COLOR_PAIR(WHITE)|A_NORMAL)); strncpy(strbuf, dname[current], 42); strbuf[42] = '\0'; mvwprintw(win, FS_H-4, 1, "File: %-42s", strbuf); strcpy(modpath, name); wattrset(win, A_BOLD); mvwaddch(win, FS_H-4, 1, 'F'); wattrset(win, A_NORMAL); } } /*** File selector buttons. ***/ static int fs_buttons(WINDOW *win) { int c; int in_loop = 1; fs_val = 0; wattrset(win, A_REVERSE); mvwprintw(win, FS_H-2, 16, "[ OK ]"); wattrset(win, A_NORMAL); mvwprintw(win, FS_H-2, 34, "[ Cancel ]"); wnoutrefresh(win); doupdate(); while (in_loop) { switch ((c = wgetch(win))) { case KEY_RIGHT: wattrset(win, A_NORMAL); mvwprintw(win, FS_H-2, 16, "[ OK ]"); wattrset(win, A_REVERSE); mvwprintw(win, FS_H-2, 34, "[ Cancel ]"); fs_val = 1; break; case KEY_LEFT: wattrset(win, A_REVERSE); mvwprintw(win, FS_H-2, 16, "[ OK ]"); wattrset(win, A_NORMAL); mvwprintw(win, FS_H-2, 34, "[ Cancel ]"); fs_val = 0; break; case KEY_TAB: wattrset(win, A_NORMAL); mvwprintw(win, FS_H-2, 16, "[ OK ]"); mvwprintw(win, FS_H-2, 34, "[ Cancel ]"); fs_val = 2; in_loop = 0; continue; break; case KEY_ENTER: in_loop = 0; continue; break; } if (mod && playing) { refresh_info(); refresh_module_info(); doupdate(); update_panels(); MikMod_Update(); } } return fs_val; } /*** Enter file selector. ***/ static char *file_select(void) { int i; int in_loop = 1; int tabsw = 0; char strbuf[NAME_MAX+1]; WINDOW *tmpwin; struct stat sbuf; fswin = tmpwin = newwin(FS_H, FS_W, FS_Y, FS_X); keypad(tmpwin, TRUE); wtimeout(tmpwin, DELAY); box(tmpwin, 0, 0); fspan = new_panel(fswin); wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL)); mvwprintw(tmpwin, 0, 2, "[ ]"); wattrset(tmpwin, (COLOR_PAIR(YELLOW)|A_BOLD)); mvwprintw(tmpwin, 0, 4, "Select file"); wattrset(tmpwin, A_NORMAL); mvwprintw(tmpwin, FS_H-4, 1, "File: "); wattrset(tmpwin, A_BOLD); mvwaddch(tmpwin, FS_H-4, 1, 'F'); wattrset(tmpwin, A_NORMAL); mvwaddch(tmpwin, 4, 0, ACS_LTEE); mvwaddch(tmpwin, FS_H-3, 0, ACS_LTEE); mvwaddch(tmpwin, FS_H-5, 0, ACS_LTEE); for (i = 1; i < FS_W-1; i++) { mvwaddch(tmpwin, 4, i, ACS_HLINE); mvwaddch(tmpwin, FS_H-3, i, ACS_HLINE); mvwaddch(tmpwin, FS_H-5, i, ACS_HLINE); } mvwaddch(tmpwin, 4, FS_W-1, ACS_RTEE); mvwaddch(tmpwin, FS_H-3, FS_W-1, ACS_RTEE); mvwaddch(tmpwin, FS_H-5, FS_W-1, ACS_RTEE); wattrset(tmpwin, A_NORMAL); mvwprintw(tmpwin, FS_H-2, 16, "[ OK ]"); mvwprintw(tmpwin, FS_H-2, 34, "[ Cancel ]"); memset(modpath, 0, 256); /* Check and open dir. */ if (strlen(lastdir) == 0) sprintf(dirname, (getenv("PWD"))); else sprintf(dirname, lastdir); check_symlink(dirname); dentry = opendir(dirname); chdir(dirname); print_dir(tmpwin); closedir(dentry); update_panels(); doupdate(); /*** Loop ***/ fspage = lastpage = 0; while (in_loop) { switch ((wgetch(tmpwin))) { case ERR: break; case 'm': mp_move_panel(fspan); break; /* Edit directory name. */ case 'd': case 'D': stat(dname[current], &sbuf); if (S_ISREG(sbuf.st_mode) == 0) wattrset(tmpwin, A_BOLD); else wattrset(tmpwin, A_NORMAL); mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", strbuf); sprintf(lastdir, dirname); wattrset(tmpwin, A_REVERSE); get_string(tmpwin, 2, 1, "Dir: ", dirname); wattrset(tmpwin, A_NORMAL); if (chdir(dirname)) { sprintf(dirname, lastdir); mvwprintw(tmpwin, 2, 1, "Dir: %-52s", dirname); wattrset(tmpwin, A_BOLD); mvwaddch(tmpwin, 2, 1, 'D'); wattrset(tmpwin, A_REVERSE); strncpy(strbuf, dname[current], 48); mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", strbuf); beep(); break; } current = 0; check_symlink(dirname); dentry = opendir(dirname); print_dir(tmpwin); closedir(dentry); wattrset(tmpwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD); strncpy(strbuf, dname[current], 48); mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", strbuf); break; /* Edit file name. */ case 'f': case 'F': stat(dname[current], &sbuf); if (S_ISREG(sbuf.st_mode) == 0) wattrset(tmpwin, A_BOLD); else wattrset(tmpwin, A_NORMAL); mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", strbuf); wattrset(tmpwin, A_REVERSE); get_string(tmpwin,FS_H-4, 1, "File: ", modpath); wattrset(tmpwin, A_NORMAL); if (strlen(modpath) != 0 && getstrtab != 1) { fs_val = 0; /* OK */ in_loop = 0; continue; } mvwprintw(tmpwin, FS_H-4, 1, "File: %-52s", modpath); wattrset(tmpwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD); strncpy(strbuf, dname[current], 48); mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", strbuf); break; /* Enter buttons (OK, Cancel). */ case KEY_TAB: tabsw = 1-tabsw; if (tabsw == 1) { stat(dname[current], &sbuf); if (S_ISREG(sbuf.st_mode) == 0) wattrset(tmpwin, A_BOLD); else wattrset(tmpwin, A_NORMAL); strncpy(strbuf, dname[current], 48); strbuf[48] = '\0'; mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", strbuf); fs_buttons(tmpwin); if (fs_val != 2) { in_loop = 0; continue; } tabsw = 0; } if (tabsw == 0) { strncpy(strbuf, dname[current], 48); strbuf[48] = '\0'; wattrset(tmpwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD); mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", strbuf); } break; case KEY_ENTER: check_dentry(dname[current], tmpwin); break; /* Up. */ case KEY_UP: stat(dname[current], &sbuf); if (S_ISREG(sbuf.st_mode) == 0) wattrset(tmpwin, A_BOLD); else wattrset(tmpwin, A_NORMAL); strncpy(strbuf, dname[current], 48); strbuf[48] = '\0'; mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", strbuf); if (current > 0) current--; fspage = (current/(FS_H-10)); if (lastpage > fspage) { lastpage = fspage; list_dir(tmpwin); } wattrset(tmpwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD); strncpy(strbuf, dname[current], 48); strbuf[48] = '\0'; mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", strbuf); break; case KEY_PPAGE: wattrset(tmpwin, A_NORMAL); mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", dname[current]); if (((fspage-1)*(FS_H-10)) >= 0) current = (--fspage*(FS_H-10)); else current = 0; fspage = (current/(FS_H-10)); if (lastpage > fspage) { lastpage = fspage; list_dir(tmpwin); } wattrset(tmpwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD); mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", dname[current]); break; /* Down. */ case KEY_DOWN: stat(dname[current], &sbuf); if (S_ISREG(sbuf.st_mode) == 0) wattrset(tmpwin, A_BOLD); else wattrset(tmpwin, A_NORMAL); strncpy(strbuf, dname[current], 48); strbuf[48] = '\0'; mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", strbuf); if (current < nument-1) current++; fspage = (current/(FS_H-10)); if (lastpage < fspage) { lastpage = fspage; list_dir(tmpwin); } wattrset(tmpwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD); strncpy(strbuf, dname[current], 48); strbuf[48] = '\0'; mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", strbuf); break; case KEY_NPAGE: wattrset(tmpwin, A_NORMAL); mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", dname[current]); if (((fspage+1)*(FS_H-10)) < nument) current = ((fspage+1)*(FS_H-10)); else current = nument-1; fspage = (current/(FS_H-10)); lastpage = fspage; list_dir(tmpwin); wattrset(tmpwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD); mvwprintw(tmpwin, (current%(FS_H-10))+5, 1, "%-48s", dname[current]); break; } if (mod && playing) { refresh_info(); refresh_module_info(); update_panels(); doupdate(); MikMod_Update(); } update_panels(); doupdate(); } current = 0; sprintf(lastdir, dirname); sprintf(full_modname, "%s/%s", dirname, modpath); del_panel(fspan); delwin(fswin); update_panels(); doupdate(); if (fs_val == 0) return modpath; else return NULL; } /*****************************************************************************/ /*** Display the load message. ***/ static void loading(int on) { WINDOW *tmpwin = NULL; if (on == 0) { delwin(tmpwin); touchwin(dspwin); doupdate(); return; } tmpwin = newwin(5, 14, (LINES/2)-3, 33); box(tmpwin, 0, 0); wattrset(tmpwin, (COLOR_PAIR(GREEN)|A_BOLD)); mvwprintw(tmpwin, 2, 2, "Loading..."); wnoutrefresh(tmpwin); doupdate(); } /*** Display a message in a separate window and wait *** for user confirmation (OK). ***/ static void message(char *msg, int level) { int c; int len = strlen(msg); WINDOW *tmpwin; PANEL *tmppan; tmpwin = newwin(6, len+4, (LINES/2)-4, (COLS/2)-((len+4)/2)); wtimeout(tmpwin, DELAY); keypad(tmpwin, TRUE); box(tmpwin, 0, 0); tmppan = new_panel(tmpwin); if (level == ERROR_MSG) wattrset(tmpwin, (COLOR_PAIR(RED)|A_BOLD)); else wattrset(tmpwin, (COLOR_PAIR(GREEN)|A_BOLD)); mvwprintw(tmpwin, 1, 2, msg); wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE)); mvwprintw(tmpwin, 4, (((len+4)/2)-3), "[ OK ]"); while ((c = wgetch(tmpwin)) != KEY_ENTER) { if (mod && playing) { refresh_info(); refresh_module_info(); update_panels(); doupdate(); MikMod_Update(); } } del_panel(tmppan); delwin(tmpwin); update_panels(); doupdate(); } /*****************************************************************************/ /*** *** Playlist. ***/ int pl_val = 0; int pl_files = 0; int pl_cnt = 0; int pl_page = 0; int pl_entry = 0; int pl_playtime = 0; char need_to_clear = 0; typedef struct { int played; char dir[NAME_MAX+1]; char name[NAME_MAX+1]; char fname[NAME_MAX+1]; /* full path */ } list_entry; list_entry list_files[4096]; #define MP_PL_HEADER "MP PLAYING LIST" #define MP_PL_HEADER_SIZE 15 /*** Load playlist file. ***/ static int load_pl_file(char *name) { char c; int cnt; int len; FILE *file; char *fname; char buf[NAME_MAX+1]; /* Open file. */ file = fopen(name, "r"); if (file == NULL) { beep(); sprintf(buf, "Can't open '%s'.", name); message(buf, ERROR_MSG); return -1; } /* Check if it is an MP playlist file. */ fread(buf, MP_PL_HEADER_SIZE, 1, file); buf[MP_PL_HEADER_SIZE] = '\0'; if ((strncmp(buf, MP_PL_HEADER, MP_PL_HEADER_SIZE)) != 0) { beep(); sprintf(buf, "Not a playlist file."); message(buf, ERROR_MSG); return -1; } fread(buf, 1, 1, file); /* skip '\n' */ /* Read data... */ pl_files = 0; cnt = 0; memset(buf, 0, NAME_MAX); while ((fread(&c, 1, 1, file)) > 0) { if (c != '\n') { buf[cnt++] = c; continue; } cnt = 0; sprintf(list_files[pl_files].fname, buf); fname = rindex(buf, '/'); fname[(strlen(fname)+1)] = '\0'; sprintf(list_files[pl_files].name, fname+1); len = ((strlen(buf)) - (strlen(fname))); buf[len] = '\0'; sprintf(list_files[pl_files].dir, buf); pl_files++; memset(buf, 0, NAME_MAX); } /* Close file. */ fclose(file); return 0; } /*** Save playlist file. ***/ static int save_pl_file(char *name) { int i; FILE *file; char buf[NAME_MAX+1]; /* Open file. */ file = fopen(name, "w"); if (file == NULL) { beep(); sprintf(buf, "Can't open '%s'.", name); message(buf, ERROR_MSG); return -1; } /* Add header. */ fwrite(MP_PL_HEADER, MP_PL_HEADER_SIZE, 1, file); fwrite("\n", 1, 1, file); /* Write data... */ for (i = 0; i < pl_files; i++) { sprintf(buf, "%s/%s\n", list_files[i].dir, list_files[i].name); fwrite(buf, strlen(buf), 1, file); } /* Close file. */ fclose(file); sprintf(buf, "'%s' saved.", name); message(buf, INFO_MSG); return 0; } /*** Refresh playlist. ***/ static void refresh_list_entries(WINDOW *win) { int i; int offset = (pl_page * (PL_H-2)); wattrset(win, (COLOR_PAIR(CYAN)|A_NORMAL)); for (i = 0; i < PL_H-2; i++) { if (offset+i >= pl_files) { mvwprintw(win, i+1, 1, "%3d: %-48s", (pl_page * (PL_H-2))+i+1, "EMPTY"); continue; } mvwprintw(win, i+1, 1, "%-48s", ""); mvwprintw(win, i+1, 1, "%3d: %s/%s", offset+i+1, list_files[offset + i].dir, list_files[offset + i].name ); } wattrset(win, (COLOR_PAIR(WHITE)|A_NORMAL)); mvwprintw(win, PL_H-1, PL_W-34, "[ %5d entries ]", pl_files); } /*** Playlist module info. ***/ #define MINF_H 12 #define MINF_W 60 #define MINF_X ((COLS/2)-(MINF_W/2)) #define MINF_Y ((LINES/2)-(MINF_H/2)) static void pl_mod_info(char *path) { int c; int in_loop = 1; struct stat sbuf; WINDOW *tmpwin; PANEL *tmppan; MODULE *infomod; if (path == NULL) return; tmpwin = newwin(MINF_H, MINF_W, MINF_Y, MINF_X); wtimeout(tmpwin, DELAY); keypad(tmpwin, TRUE); box(tmpwin, 0, 0); tmppan = new_panel(tmpwin); wattrset(tmpwin, A_NORMAL); mvwprintw(tmpwin, 0, 2, "[ ]"); wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD); mvwprintw(tmpwin, 0, 4, "Module info"); wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD); mvwprintw(tmpwin, (MINF_H/2)-1, 16, "Please wait..."); wnoutrefresh(tmpwin); doupdate(); if ((infomod = Player_Load(path, 64, 0)) == NULL) { del_panel(tmppan); delwin(tmpwin); update_panels(); doupdate(); message(MikMod_strerror(MikMod_errno), ERROR_MSG); return; } wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL); stat(path, &sbuf); mvwprintw(tmpwin, (MINF_H/2)-1, 16, " "); mvwprintw(tmpwin, 1, 1, " File: %s - Size: %d", list_files[pl_entry].name, sbuf.st_size); mvwprintw(tmpwin, 2, 1, " Name: %s", infomod->songname); mvwprintw(tmpwin, 3, 1, " Type: %s", infomod->modtype); mvwprintw(tmpwin, 4, 1, " Chn: %d", infomod->numchn); mvwprintw(tmpwin, 5, 1, "Samples: %d", infomod->numsmp); mvwprintw(tmpwin, 6, 1, " Instr.: %d", infomod->numins); mvwprintw(tmpwin, 7, 1, " BMP: %d", infomod->bpm); mvwprintw(tmpwin, 8, 1, " Speed: %d", infomod->sngspd); mvwprintw(tmpwin, 9, 1, " Tempo: %d", infomod->inittempo); mvwprintw(tmpwin, 10, 1, " Vol: %d", infomod->initvolume); Player_Free(infomod); while (in_loop) { switch ((c = wgetch(tmpwin))) { case 'q': case KEY_ESCAPE: in_loop = 0; continue; break; } if (mod && playing) { refresh_info(); refresh_module_info(); update_panels(); doupdate(); MikMod_Update(); } } del_panel(tmppan); delwin(tmpwin); update_panels(); doupdate(); } /*** Delete playlist entry. ***/ #define PL_DEL 1 #define PL_UP 2 #define PL_DOWN 3 #define PL_INFO 4 static void handle_pl_entry(WINDOW *win, int action) { int i; int c; int in_loop = 1; int lastpage = pl_page; refresh_list_entries(win); wattrset(win, COLOR_PAIR(CYAN)|A_REVERSE); mvwprintw(win, (pl_entry % (PL_H-2))+1, 6, "%s", list_files[pl_entry].fname); wnoutrefresh(win); doupdate(); /*** Main loop. ***/ while (in_loop) { switch ((c = wgetch(win))) { /* Cancel. */ case KEY_ESCAPE: case KEY_TAB: in_loop = 0; continue; break; /* Action. */ case KEY_ENTER: if (action == PL_DEL) { memset(&list_files[pl_entry], 0, sizeof(list_entry)); if (pl_entry == pl_files-1) { if (pl_entry) pl_entry = 0; if (pl_files) pl_files--; in_loop = 0; continue; } for (i=pl_entry; i < pl_files-1; i++) { memcpy(&list_files[i], &list_files[i+1], (sizeof(list_entry))); } pl_files--; in_loop = 0; continue; } else if (action == PL_UP) { if (pl_entry > 0) { list_entry t; memcpy(&t, &list_files[pl_entry-1], (sizeof(list_entry))); memcpy(&list_files[pl_entry-1], &list_files[pl_entry], (sizeof(list_entry))); memcpy(&list_files[pl_entry], &t, (sizeof(list_entry))); } in_loop = 0; continue; } else if (action == PL_DOWN) { if (pl_entry < pl_files-1) { list_entry t; memcpy(&t, &list_files[pl_entry+1], (sizeof(list_entry))); memcpy(&list_files[pl_entry+1], &list_files[pl_entry], (sizeof(list_entry))); memcpy(&list_files[pl_entry], &t, (sizeof(list_entry))); } in_loop = 0; continue; } else if (action == PL_INFO) { if (playing) { message("Player is running.", ERROR_MSG); break; } pl_mod_info(list_files[pl_entry].fname); } break; /* Select entry (up/down). */ case KEY_UP: if (pl_entry > 0) { wattrset(win, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(win, (pl_entry % (PL_H-2))+1, 6, "%s", list_files[pl_entry].fname); pl_entry--; } else break; pl_page = (pl_entry / (PL_H-2)); if (lastpage != pl_page) { lastpage = pl_page; refresh_list_entries(win); } wattrset(win, COLOR_PAIR(CYAN)|A_REVERSE); mvwprintw(win, (pl_entry % (PL_H-2))+1, 6, "%s", list_files[pl_entry].fname); break; case KEY_PPAGE: if (pl_entry > 0) { wattrset(win, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(win, (pl_entry % (PL_H-2))+1, 6, "%s", list_files[pl_entry].fname); pl_entry--; } else break; if (((pl_page-1)*(PL_H-2)) > 0) { pl_page--; pl_entry = pl_page * (PL_H-2); } else pl_entry = 0; pl_page = (pl_entry / (PL_H-2)); if (lastpage != pl_page) { lastpage = pl_page; refresh_list_entries(win); } refresh_list_entries(win); wattrset(win, COLOR_PAIR(CYAN)|A_REVERSE); mvwprintw(win, (pl_entry % (PL_H-2))+1, 6, "%s", list_files[pl_entry].fname); break; case KEY_DOWN: if (pl_entry < pl_files-1) { wattrset(win, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(win, (pl_entry % (PL_H-2))+1, 6, "%s", list_files[pl_entry].fname); pl_entry++; } else break; pl_page = (pl_entry / (PL_H-2)); if (lastpage != pl_page) { lastpage = pl_page; refresh_list_entries(win); } wattrset(win, COLOR_PAIR(CYAN)|A_REVERSE); mvwprintw(win, (pl_entry % (PL_H-2))+1, 6, "%s", list_files[pl_entry].fname); break; case KEY_NPAGE: if (pl_entry < pl_files-1) { wattrset(win, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(win, (pl_entry % (PL_H-2))+1, 6, "%s", list_files[pl_entry].fname); pl_entry--; } else break; if (((pl_page+1)*(PL_H-2)) < pl_files-1) { pl_page++; pl_entry = pl_page * (PL_H-2); } else pl_entry = pl_files-1; pl_page = (pl_entry / (PL_H-2)); if (lastpage != pl_page) { lastpage = pl_page; refresh_list_entries(win); } refresh_list_entries(win); wattrset(win, COLOR_PAIR(CYAN)|A_REVERSE); mvwprintw(win, (pl_entry % (PL_H-2))+1, 6, "%s", list_files[pl_entry].fname); break; } if (mod && playing) { refresh_info(); refresh_module_info(); update_panels(); doupdate(); MikMod_Update(); } } wattrset(win, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(win, (pl_entry % (PL_H-2))+1, 6, "%s", list_files[pl_entry].fname); refresh_list_entries(win); wnoutrefresh(win); doupdate(); } /*** Playlist buttons. ***/ static int pl_buttons(WINDOW *win) { int i, c; int ys; int in_loop = 1; char *name; char *pl_btns[10] = { "[ Add file ]", "[ Add dir ]", "[ Remove ]", "[ Clear ]", "[ Move up ]", "[ Move down ]", "[ Info ]", "[ Load ]", "[ Save ]", "[ Done ]" }; struct stat sbuf; pl_val = 0; wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL); for (i = 0, ys = 0; i < 10; i++, ys++) { if (pl_val == i) wattrset(win, A_REVERSE); else wattrset(win, A_NORMAL); mvwprintw(win, 2+(ys*2), (PL_W-15), "%s", pl_btns[i]); } while (in_loop) { switch ((c = wgetch(win))) { /* Quit playlist. */ case 'q': pl_val = 255; in_loop = 0; continue; break; /* Move. */ case 'm': mp_move_panel(plpan); break; /* Down. */ case KEY_NPAGE: wattrset(win, A_NORMAL); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); pl_val = 9; wattrset(win, A_REVERSE); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); break; case KEY_DOWN: wattrset(win, A_NORMAL); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); if (pl_val < 9) pl_val++; wattrset(win, A_REVERSE); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); break; /* Up. */ case KEY_PPAGE: wattrset(win, A_NORMAL); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); pl_val = 0; wattrset(win, A_REVERSE); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); break; case KEY_UP: wattrset(win, A_NORMAL); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); if (pl_val > 0) pl_val--; wattrset(win, A_REVERSE); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); break; /* Visit playlist. */ case KEY_TAB: if (pl_files > 0) { wattrset(win, A_NORMAL); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); wnoutrefresh(win); doupdate(); handle_pl_entry(win, 0); wattrset(win, A_REVERSE); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); wnoutrefresh(win); doupdate(); } break; /* Action. */ case KEY_ENTER: /* Add file. */ if (pl_val == 0) { name = file_select(); if (name!=NULL && (strlen(name)) > 0) { sprintf(list_files[pl_files].fname, "%s/%s", lastdir, name); sprintf(list_files[pl_files].name, name); sprintf(list_files[pl_files].dir, lastdir); pl_files++; } touchwin(win); refresh_list_entries(win); /* Add dir. */ } else if (pl_val == 1) { file_select(); if (fs_val != 0) break; for (i = 0; i < nument; i++) { stat(dname[i], &sbuf); if (S_ISREG(sbuf.st_mode)) { sprintf( list_files[pl_files].fname, "%s/%s", lastdir, dname[i]); sprintf( list_files[pl_files].name, dname[i]); sprintf( list_files[pl_files].dir, lastdir); pl_files++; } } touchwin(win); refresh_list_entries(win); /* Remove. */ } else if (pl_val == 2) { if (pl_files > 0) { wattrset(win, A_NORMAL); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); wnoutrefresh(win); doupdate(); handle_pl_entry(win, PL_DEL); wattrset(win, A_REVERSE); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); wnoutrefresh(win); doupdate(); } /* Clear. */ } else if (pl_val == 3) { for (i = 0; i < pl_files; i++) { memset(&list_files[i], 0, sizeof(list_entry)); } pl_files = 0; refresh_list_entries(win); /* Move up. */ } else if (pl_val == 4) { if (pl_files > 0) { wattrset(win, A_NORMAL); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); wnoutrefresh(win); doupdate(); handle_pl_entry(win, PL_UP); wattrset(win, A_REVERSE); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); wnoutrefresh(win); doupdate(); } refresh_list_entries(win); /* Move down. */ } else if (pl_val == 5) { if (pl_files > 0) { wattrset(win, A_NORMAL); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); wnoutrefresh(win); doupdate(); handle_pl_entry(win, PL_DOWN); wattrset(win, A_REVERSE); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); wnoutrefresh(win); doupdate(); } refresh_list_entries(win); /* Info. */ } else if (pl_val == 6) { if (pl_files > 0) { wattrset(win, A_NORMAL); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); wnoutrefresh(win); doupdate(); handle_pl_entry(win, PL_INFO); wattrset(win, A_REVERSE); mvwprintw(win, 2+(pl_val*2), PL_W-15, "%s", pl_btns[pl_val]); wnoutrefresh(win); doupdate(); } refresh_list_entries(win); /* Load. */ } else if (pl_val == 7) { char *f = file_select(); if (f == NULL) { touchwin(win); break; } sprintf(pl_file, "%s/%s", lastdir, f); load_pl_file(pl_file); refresh_list_entries(win); touchwin(win); /* Save. */ } else if (pl_val == 8) { char *f = file_select(); if (f == NULL) { touchwin(win); break; } sprintf(pl_file, "%s/%s", lastdir, f); save_pl_file(pl_file); refresh_list_entries(win); touchwin(win); /* Done. */ } else if (pl_val == 9) { if (pl_files) in_playlist = 1; in_loop = 0; continue; } break; } if (mod && playing) { refresh_info(); refresh_module_info(); update_panels(); doupdate(); MikMod_Update(); } } return pl_val; } /*** Playlist handler (called with alarm(1)) ***/ void update_playlist(int unused) { int i; if (in_playlist) { if (mod->sngpos >= mod->numpos) { /* end of module */ wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); for (i = 1; i < 40; i++) mvwaddch(dspwin, DSP_H-1, i, ACS_HLINE); pl_playtime += mod->sngtime; if (!random_mode) { if (pl_cnt < pl_files-1) { pl_cnt++; refresh_pl_info(); loading(1); play_module(list_files[pl_cnt].fname); loading(0); touchwin(dspwin); } else { mvwprintw(dspwin, DSP_H-1, 2, "[ Playlist finished %3d/%3d (%02d:%02d) ]", pl_cnt+1, pl_files, (pl_playtime/1000)/60, (pl_playtime/1000)%60); in_playlist = 0; need_to_clear = 1; } } else { /* random_mode */ if (pl_cnt < pl_files-1) { int i = 1 + (((float) pl_files-1) * \ rand()) / (RAND_MAX+1.0); pl_cnt++; pl_playtime += mod->sngtime; refresh_pl_info(); loading(1); play_module(list_files[i].fname); loading(0); touchwin(dspwin); } } } } else { for (i = 1; i < 40; i++); /* reset last line */ // mvwaddch(dspwin, DSP_H-1, i, ACS_HLINE); } alarm(1); } /*** Install playlist handler ***/ void install_pl_handler(void) { pl_cnt = 0; signal(SIGALRM, update_playlist); alarm(1); } /*** Refresh playlist information (bottom of screen) ***/ static void refresh_pl_info(void) { int i; wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); for (i = 1; i < 48; i++) mvwaddch(dspwin, DSP_H-1, i, ACS_HLINE); mvwprintw(dspwin, DSP_H-1, 2, "[ ]"); wattrset(dspwin, COLOR_PAIR(YELLOW_BLUE)|A_BOLD); mvwprintw(dspwin, DSP_H-1, 4, "Playlist:"); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); mvwprintw(dspwin, DSP_H-1, 16, "%3d/%3d (%02d:%02d)", pl_cnt+1, pl_files, ((mod->sngtime+pl_playtime)/1000)/60, ((mod->sngtime+pl_playtime)/1000)%60); } /*** Enter playlist. ***/ static void playlist(void) { int i; WINDOW *tmpwin; plwin = tmpwin = newwin(PL_H, PL_W, PL_Y, PL_X); keypad(tmpwin, TRUE); wtimeout(tmpwin, DELAY); box(tmpwin, 0, 0); plpan = new_panel(plwin); wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL)); mvwprintw(tmpwin, 0, 2, "[ ]"); wattrset(tmpwin, (COLOR_PAIR(YELLOW)|A_BOLD)); mvwprintw(tmpwin, 0, 4, " Playlist (press 'q' to quit without starting)"); wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL)); for (i = 1; i < PL_H-1; i++) mvwaddch(tmpwin, i, PL_W-17, ACS_VLINE); mvwaddch(tmpwin, PL_H-1, PL_W-17, ACS_BTEE); refresh_list_entries(tmpwin); pl_buttons(tmpwin); del_panel(plpan); delwin(plwin); refresh_info(); refresh_module_info(); touchwin(dspwin); update_panels(); doupdate(); } /*****************************************************************************/ /*** Draw a gauge. ***/ static void draw_gauge(WINDOW *win, int x, int y, int pc, int vh, int style) { int i; int c = 0; int ipc = pc; if (pc > 100) pc = 100; if (style == 1 && vh == 1) { c = ' '; if (pc < 30) wattrset(win, COLOR_PAIR(GREEN)|A_REVERSE); else wattrset(win, COLOR_PAIR(CYAN)|A_REVERSE); } else if (style == 1 && vh == 0) { wattrset(win, COLOR_PAIR(BLUE)|A_REVERSE); c = ' '; } else if (style == 2) c = ACS_BULLET; else if (style == 3) { if (vh == 1) c = ACS_RARROW; else c = ACS_UARROW; } else if (style == 4) c = '*'; else if (style == 5) c = '#'; if (vh) { /* horizontal */ pc /= 5; for (i = 0; i < pc; i++) mvwaddch(win, y, x+i, c); if (style == 1) wattrset(win, COLOR_PAIR(GREEN)|A_NORMAL); for (; i < 20; i++) mvwaddch(win, y, x+i, ' '); if (pc == 20) { if (style == 1) { c = ' '; wattrset(win, COLOR_PAIR(RED_RED)|A_NORMAL); } else wattrset(win, COLOR_PAIR(RED)|A_BOLD); mvwaddch(win, y, x+i-1, c); wattrset(win, COLOR_PAIR(RED)|A_BOLD); wprintw(win, " %3d%%", ipc); } else { wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(win, " %3d%%", ipc); } } else { /* vertical */ pc /= 10; if (style == 1) wattrset(win, COLOR_PAIR(BLUE)|A_REVERSE); else wattrset(win, COLOR_PAIR(BLUE)|A_NORMAL); for (i = 0; i < pc; i++) mvwaddch(win, y-i, x, c); if (style == 1) wattrset(win, COLOR_PAIR(BLUE)|A_NORMAL); wattrset(win, COLOR_PAIR(BLUE)|A_BOLD); for (; i < 10; i++) mvwaddch(win, y-i, x, ACS_HLINE); if (pc == 10) { if (style == 1) { c = ' '; wattrset(win, COLOR_PAIR(RED_RED)|A_BOLD); } else wattrset(win, COLOR_PAIR(RED)|A_NORMAL); mvwaddch(win, y-i+1, x, c); } } } /*** Draw channel pointer. ***/ static void draw_pointer(void) { wattrset(dspwin, (COLOR_PAIR(WHITE|A_NORMAL))); mvwaddch(dspwin, (oldcurch%(DSP_H-CHN_START))+CHN_START-1, 0, oldc1); mvwaddch(dspwin, (oldcurch%(DSP_H-CHN_START))+CHN_START-1, 3, oldc2); oldc1 = mvwinch(dspwin, (curch%(DSP_H-CHN_START))+CHN_START-1, 0); oldc2 = mvwinch(dspwin, (curch%(DSP_H-CHN_START))+CHN_START-1, 3); oldcurch = curch; mvwaddch(dspwin, (curch%(DSP_H-CHN_START))+CHN_START-1, 0, '>'); mvwaddch(dspwin, (curch%(DSP_H-CHN_START))+CHN_START-1, 3, '<'); } /*** Display help. ***/ static void display_help(void) { int c, in_loop = 1; helpwin = newwin(HELP_H, HELP_W, HELP_Y, HELP_X); wtimeout(helpwin, DELAY); keypad(helpwin, TRUE); box(helpwin, 0, 0); helppan = new_panel(helpwin); top_panel(helppan); wattrset(helpwin, COLOR_PAIR(WHITE)|A_NORMAL); mvwprintw(helpwin, 0, 2, "[ ]"); wattrset(helpwin, COLOR_PAIR(YELLOW)|A_BOLD); mvwprintw(helpwin, 0, 4, "Help"); /* COL 1 */ wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 1, 2, "Play or pause............."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "p"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 2, 2, "Stop module..............."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "t"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 3, 2, "Module comment............"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "i"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 4, 2, "Restart pattern..........."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "a"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 5, 2, "Restart module............"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "A"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 7, 2, "Next position............."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "n"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 8, 2, "Next module..............."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "N"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 9, 2, "Prev position............."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "v"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 10, 2, "Prev module..............."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "V"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 12, 2, "File selector............."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "f"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 13, 2, "Quit MP or close panel...."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "q"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 15, 2, "Show all channels........."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "c"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 16, 2, "Show all voices..........."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "T"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 17, 2, "Voices position..........."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "Y"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 18, 2, "Voices frequency.........."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "y"); /* COL 2 */ wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 1, 34, "Bpm up/down..............."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "b/B"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 2, 34, "Reverb up/down............"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "r/R"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 3, 34, "Tempo up/down............."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "k/K"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 4, 34, "Speed up/down............."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "s/S"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 5, 34, "Volume up/down............"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "+/-"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 6, 34, "Reverse stereo............"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "!"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 7, 34, "Switch volume display....."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "u"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 9, 34, "Playlist panel............"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "l"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 10, 34, "Effects panel............."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "e"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 11, 34, "Options panel............."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "o"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 12, 34, "Samples panel............."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "w"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 13, 34, "Instruments panel........."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "W"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 15, 34, "Select channel............"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "UP/DOWN"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 16, 34, "Mute/unmute channel......."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "ENTER"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 17, 34, "Mute/unmute all channels.."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "M"); wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(helpwin, 18, 34, "About....................."); wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD); wprintw(helpwin, "?"); wnoutrefresh(helpwin); doupdate(); /*** Loop ***/ while (in_loop) { switch ((c = wgetch(helpwin))) { case 'q': case 'Q': case KEY_ESCAPE: in_loop = 0; continue; break; case 'm': mp_move_panel(helppan); break; } if (mod && playing) { refresh_info(); refresh_module_info(); MikMod_Update(); update_panels(); doupdate(); } } del_panel(helppan); update_panels(); doupdate(); } /******************************************************************************/ /*** Show voices position. ***/ static void show_voices_pos(void) { int i; /* counter */ int c; /* character */ int x; /* x position */ int step; /* x step */ int add; /* add to x */ int pc; /* percent */ unsigned char pan; /* panning */ float pos1, pos2; /* positions */ WINDOW *tmpwin; /* channel window (temporary) */ /* Create window. */ tmpwin = newwin(VPOS_H, VPOS_W, VPOS_Y, VPOS_X); vposwin = tmpwin; wtimeout(tmpwin, DELAY); keypad(tmpwin, TRUE); box(tmpwin, 0, 0); vpospan = new_panel(tmpwin); wattrset(tmpwin, (COLOR_PAIR(CYAN_BLUE)|A_BOLD)); mvwprintw(tmpwin, 0, 0, "%-68s", " Voices position"); wattrset(tmpwin, A_NORMAL); wattrset(tmpwin, (COLOR_PAIR(CYAN)|A_NORMAL)); /* Calculate x step and add. */ if (mod->numchn <= 32) step = 2; else step = 1; add = step == 1 ? 1 : 0; /* Display channel counter. */ for (c = 0; c < mod->numchn; c++) { if (c == 0) { mvwaddch(tmpwin, VPOS_H-3, 2, '|'); mvwprintw(tmpwin, VPOS_H-2, 2, "1"); continue; } if ((c % 4) == 0) { mvwaddch(tmpwin, VPOS_H-3, (c*step) + add, '|'); mvwprintw(tmpwin, VPOS_H-2, (c*step) + add, "%d", c); } } mvwaddch(tmpwin, VPOS_H-3, (c*step) + add, '|'); mvwprintw(tmpwin, VPOS_H-2, (c*step) + add, "%d", c); /*** Loop ***/ while ((c = wgetch(tmpwin)) != 'q') { if (c == KEY_ESCAPE) break; else if (c == 'e') effects(); else if (c == 'o') options(); else if (c == 'p') do_pause(); else if (c == 'm') mp_move_panel(vpospan); /* Draw voices. */ for (x = 0, i = 0; i < mod->numchn; x += step, i++) { pos1 = get_voice_pos(i); pos2 = maxfreq[i]; if (pos2 <= 0) pos2=1; pc = (int) (100.0 * (pos1 / pos2)); draw_gauge(tmpwin, x+2, VPOS_H-4, pc, 0, gauge_style); if (step == 2) draw_gauge(tmpwin, x+3, VPOS_H-4, pc, 0, gauge_style); /* Panning. */ pan = (unsigned char) get_voice_panning(i); if (pan == 128) wattrset(tmpwin, COLOR_PAIR(BLUE)|A_BOLD); else if (pan == 0 || (pan > 0 && pan < 128)) wattrset(tmpwin, COLOR_PAIR(MAGENTA)|A_BOLD); else wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD); mvwaddch(tmpwin, 2, x+2, (pan == 128 ? 'M' : (pan == 0 || (pan > 0 && pan < 128)) ? 'L' :'R') ); } if (mod && playing) { refresh_info(); refresh_module_info(); MikMod_Update(); } update_panels(); doupdate(); } del_panel(vpospan); touchwin(dspwin); wnoutrefresh(dspwin); doupdate(); update_panels(); } /*** Show voices frequency. ***/ static void show_voices_freq(void) { int i; /* counter */ int c; /* character */ int x; /* x position */ int step; /* x step */ int add; /* add to x */ int pc; /* percent */ unsigned char pan; /* panning */ float freq1, freq2; /* frequencies */ WINDOW *tmpwin; /* channel window (temporary) */ /* Create window. */ vfreqwin = tmpwin = newwin(VFREQ_H, VFREQ_W, VFREQ_Y, VFREQ_X); wtimeout(tmpwin, DELAY); keypad(tmpwin, TRUE); box(tmpwin, 0, 0); vfreqpan = new_panel(tmpwin); wattrset(tmpwin, (COLOR_PAIR(CYAN_BLUE)|A_BOLD)); mvwprintw(tmpwin, 0, 0, "%-68s", " Voices frequency"); /* Calculate x step and add. */ if (mod->numchn <= 32) step = 2; else step = 1; add = step == 1 ? 1 : 0; /* Display channel counter. */ wattrset(tmpwin, (COLOR_PAIR(CYAN)|A_NORMAL)); for (c = 0; c < mod->numchn; c++) { if (c == 0) { mvwaddch(tmpwin, VFREQ_H-3, 2, '|'); mvwprintw(tmpwin, VFREQ_H-2, 2, "1"); continue; } if ((c % 4) == 0) { mvwaddch(tmpwin, VFREQ_H-3, (c*step) + add, '|'); mvwprintw(tmpwin, VFREQ_H-2, (c*step) + add, "%d", c); } } mvwaddch(tmpwin, VFREQ_H-3, (c*step) + add, '|'); mvwprintw(tmpwin, VFREQ_H-2, (c*step) + add, "%d", c); /*** Loop ***/ while ((c = wgetch(tmpwin)) != 'q') { if (c == KEY_ESCAPE) break; else if (c == 'e') effects(); else if (c == 'o') options(); else if (c == 'p') do_pause(); else if (c == 'm') mp_move_panel(vfreqpan); /* Draw channels. */ for (x = 0, i = 0; i < mod->numchn; x += step, i++) { pan = (unsigned char) get_voice_panning(i); freq1 = get_voice_freq(i); freq2 = maxfreq[i]; if (freq2 <= 0) freq2 = 1; pc = (int) (100.0 * (freq1 / freq2)); draw_gauge(tmpwin, x+2, VFREQ_H-4, pc, 0, gauge_style); if (step == 2) draw_gauge(tmpwin, x+3, VFREQ_H-4, pc, 0, gauge_style); if (pan == 128) wattrset(tmpwin, COLOR_PAIR(BLUE)|A_BOLD); else if (pan == 0 || (pan > 0 && pan < 128)) wattrset(tmpwin, COLOR_PAIR(MAGENTA)|A_BOLD); else wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD); mvwaddch(tmpwin, 2, x+2, (pan == 128 ? 'M' : (pan == 0 || (pan > 0 && pan < 128)) ? 'L' :'R') ); } if (mod && playing) { refresh_info(); refresh_module_info(); MikMod_Update(); } update_panels(); doupdate(); } del_panel(vfreqpan); touchwin(dspwin); wnoutrefresh(dspwin); update_panels(); doupdate(); } /*** Show all channels. ***/ static void show_all_channels(void) { int i; /* counter */ int c; /* character */ int x; /* x position */ int step; /* x step */ int add; /* add to x */ int pc; /* percent */ int lastmod = 0; /* for playlist checking */ unsigned char pan; /* panning */ float vol1, vol2; /* volume */ WINDOW *tmpwin; /* channel window (temporary) */ /* Create window. */ acwin = tmpwin = newwin(AC_H, AC_W, AC_Y, AC_X); wtimeout(tmpwin, DELAY); keypad(tmpwin, TRUE); box(tmpwin, 0, 0); acpan = new_panel(tmpwin); wattrset(tmpwin, (COLOR_PAIR(CYAN_BLUE)|A_BOLD)); mvwprintw(tmpwin, 0, 0, "%-68s", " All channels"); /* Calculate x step and add. */ CHN_CNT: step = mod->numchn <= 32 ? 2 : 1; add = step == 1 ? 1 : 0; /* Print channel counter. */ wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL); for (i = 1; i < AC_H-1; i++) mvwprintw(tmpwin, i, 1, "%66s", ""); wattrset(tmpwin, COLOR_PAIR(CYAN)|A_NORMAL); for (c = 0; c < mod->numchn; c++) { if (c == 0) { mvwaddch(tmpwin, AC_H-3, 2, '|'); mvwprintw(tmpwin, AC_H-2, 2, "1"); continue; } if (!(c % 4)) { mvwaddch(tmpwin, AC_H-3, (c * step) + add, '|'); mvwprintw(tmpwin, AC_H-2, (c*step) + add, "%d", c); } } mvwaddch(tmpwin, AC_H-3, (c * step) + add, '|'); mvwprintw(tmpwin, AC_H-2, (c * step) + add, "%d", c); /*** Loop ***/ if (in_playlist) lastmod = pl_cnt; while ((c = wgetch(tmpwin)) != 'q') { if (c == KEY_ESCAPE) break; else if (c == 'e') effects(); else if (c == 'o') options(); else if (c == 'u') { real_volume = 1-real_volume; refresh_legend(); } else if (c == 'm') mp_move_panel(acpan); else module_control(c); if (c == '*') { if (gauge_style < 5) gauge_style++; else gauge_style = 1; } /* Draw channels. */ for (x = 0, i = 0; i < mod->numchn; x += step, i++) { if (real_volume) { vol1 = get_voice_realvol(i); vol2 = maxrvol[i]; if (vol2 <= 0) vol2=1; pc = (int) (100.0 * (vol1 / vol2)); draw_gauge(tmpwin, x+2, AC_H-4, pc, 0, gauge_style); } else { vol1 = get_voice_volume(i); vol2 = maxvol[i]; if (vol2 <= 0) vol2 = 1; pc = (int) (100.0 * (vol1 / vol2)); draw_gauge(tmpwin, x+2, AC_H-4, pc, 0, gauge_style); } if (step == 2) draw_gauge(tmpwin, x+3, AC_H-4, pc, 0, gauge_style); /* Volume. vol1 = get_voice_volume(i); if (vol1 > 0) wattrset(tmpwin, COLOR_PAIR(GREEN)|A_BOLD); else wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL); if (vol1 >= 128 && vol1 < MODVOL_LIMIT) wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD); else if (vol1 >= MODVOL_LIMIT) wattrset(tmpwin, COLOR_PAIR(RED)|A_BOLD); mvwaddch(tmpwin, 1, x+2, ACS_BLOCK);*/ /* Panning. */ pan = (unsigned char) get_voice_panning(i); if (pan == 128) wattrset(tmpwin, COLOR_PAIR(BLUE)|A_BOLD); else if (pan == 0 || (pan > 0 && pan < 128)) wattrset(tmpwin, COLOR_PAIR(MAGENTA)|A_BOLD); else wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD); mvwaddch(tmpwin, 2, x+2, (pan == 128 ? 'M' : (pan == 0 || (pan > 0 && pan < 128)) ? 'L' :'R') ); } wattrset(tmpwin, A_NORMAL); mvwprintw(tmpwin, AC_H-1, AC_W-18, "%s", (real_volume ? "[ Real volume ]":"[ Voice volume ]") ); if (mod && playing) { refresh_info(); refresh_module_info(); MikMod_Update(); if (in_playlist) { if (pl_cnt != lastmod) { lastmod = pl_cnt; goto CHN_CNT; } } } update_panels(); doupdate(); } del_panel(acpan); update_panels(); doupdate(); } /*** Show all voices. ***/ static void show_all_voices(void) { int i; /* counter */ int c; /* character */ int x; /* x position */ int step; /* x step */ int add; /* add to x */ int pc; /* percent */ int lastmod = 0; /* for playlist checking */ unsigned char pan; /* panning */ float vol1, vol2; /* volume */ WINDOW *tmpwin; /* channel window (temporary) */ /* Create window. */ acwin = tmpwin = newwin(AC_H+2, AC_W, AC_Y, AC_X); wtimeout(tmpwin, DELAY); keypad(tmpwin, TRUE); box(tmpwin, 0, 0); acpan = new_panel(tmpwin); wattrset(tmpwin, (COLOR_PAIR(CYAN_BLUE)|A_BOLD)); mvwprintw(tmpwin, 0, 0, "%-68s", " All voices"); /* Calculate x step and add. */ CHN_CNT: step = 1; add = 1; /* Print voices counter. */ wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL); for (i = 1; i < AC_H-1; i++) mvwprintw(tmpwin, i, 1, "%66s", ""); wattrset(tmpwin, COLOR_PAIR(CYAN)|A_NORMAL); for (c = 0; c < 64; c++) { if (c == 0) { mvwaddch(tmpwin, AC_H-2, 2, '|'); mvwprintw(tmpwin, AC_H-1, 2, "1"); continue; } if (!(c % 4)) { mvwaddch(tmpwin, AC_H-2, (c * step) + add, '|'); mvwprintw(tmpwin, AC_H-1, (c*step) + add, "%d", c); } } mvwaddch(tmpwin, AC_H-2, (c * step) + add, '|'); mvwprintw(tmpwin, AC_H-1, (c * step) + add, "%d", c); /*** Loop ***/ if (in_playlist) lastmod = pl_cnt; while ((c = wgetch(tmpwin)) != 'q') { if (c == KEY_ESCAPE) break; else if (c == 'e') effects(); else if (c == 'o') options(); else if (c == 'u') { real_volume = 1-real_volume; refresh_legend(); } else if (c == 'm') mp_move_panel(acpan); else module_control(c); if (c == '*') { if (gauge_style < 5) gauge_style++; else gauge_style = 1; } /* Draw voices. */ for (x = 0, i = 0; i < 64; x += step, i++) { if (real_volume) { vol1 = get_voice_realvol(i); vol2 = maxrvol[i]; if (vol2 <= 0) vol2=1; pc = (int) (100.0 * (vol1 / vol2)); draw_gauge(tmpwin, x+2, AC_H-4, pc, 0, gauge_style); } else { vol1 = get_voice_volume(i); vol2 = maxvol[i]; if (vol2 <= 0) vol2 = 1; pc = (int) (100.0 * (vol1 / vol2)); draw_gauge(tmpwin, x+2, AC_H-4, pc, 0, gauge_style); } /* Volume. */ vol1 = get_voice_volume(i); if (vol1 > 0) wattrset(tmpwin, COLOR_PAIR(GREEN)|A_BOLD); else wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL); if (vol1 >= 128 && vol1 < MODVOL_LIMIT) wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD); else if (vol1 >= MODVOL_LIMIT) wattrset(tmpwin, COLOR_PAIR(RED)|A_BOLD); mvwaddch(tmpwin, AC_H-3, x+2, ACS_BLOCK); /* Panning. */ pan = (unsigned char) get_voice_panning(i); if (pan == 128) wattrset(tmpwin, COLOR_PAIR(BLUE)|A_BOLD); else if (pan == 0 || (pan > 0 && pan < 128)) wattrset(tmpwin, COLOR_PAIR(MAGENTA)|A_BOLD); else wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD); mvwaddch(tmpwin, 2, x+2, (pan == 128 ? 'M' : (pan == 0 || (pan > 0 && pan < 128)) ? 'L' :'R') ); } wattrset(tmpwin, COLOR_PAIR(YELLOW_BLUE)|A_BOLD); mvwprintw(tmpwin, 0, AC_W-14, "%s", (real_volume ? " Real volume ":" Voice volume ") ); if (mod && playing) { refresh_info(); refresh_module_info(); MikMod_Update(); if (in_playlist) { if (pl_cnt != lastmod) { lastmod = pl_cnt; goto CHN_CNT; } } } update_panels(); doupdate(); } del_panel(acpan); update_panels(); doupdate(); } /*** Enter tracks view. ***/ void track_view(void) { int c; int i, j; int opcode; UBYTE *curtrk; WINDOW *tmpwin; PANEL *tmppan; /* Create window. */ tmpwin = newwin(22, 70, 1, 4); wtimeout(tmpwin, DELAY); keypad(tmpwin, TRUE); box(tmpwin, 0, 0); tmppan = new_panel(tmpwin); wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL)); mvwprintw(tmpwin, 0, 2, "[ ]"); wattrset(tmpwin, (COLOR_PAIR(YELLOW)|A_BOLD)); mvwprintw(tmpwin, 0, 4, "Pattern view"); wattrset(tmpwin, A_NORMAL); /*** Loop ***/ while ((c = wgetch(tmpwin)) != 'q') { if (c == 'p') do_pause(); if (c == 'm') mp_move_panel(tmppan); for (j = 0; j < 4 /* mod->numtrk */; j++) { curtrk = mod->tracks[j]; /* ptr to array of UBYTES */ for (i = 1; i < 21; i++) { wattrset(tmpwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(tmpwin, i, 1, "%3d", mod->patpos+i); if ((mod->patpos+i) > mod->numrow) { mvwprintw(tmpwin, i, (j*8)+6, "----"); continue; } opcode = curtrk[(i+mod->patpos)+ (mod->sngpos*mod->numpos)]; wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL); if (opcode) mvwprintw(tmpwin, i, (j*8)+6, "%04x", opcode); else mvwprintw(tmpwin, i, (j*8)+6, "----"); } } if (mod && playing) { refresh_info(); refresh_module_info(); update_panels(); doupdate(); MikMod_Update(); } } del_panel(tmppan); delwin(tmpwin); } /*** Display module info. ***/ int hidden = 1, hcnt = 0, hc[4] = { '-', '\\', '|', '/' }, pp = 0; static void refresh_module_info(void) { int i; if (mod->sngpos >= mod->numpos) return; wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD); mvwprintw(dspwin, MODINFO_Y, 1, "Ch:"); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(dspwin, "%2d/%2d", mod->realchn, mod->numchn); wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD); mvwprintw(dspwin, MODINFO_Y, 11, "Pat:"); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(dspwin, "%3d %3d/%3d", (mod->patterns[mod->sngpos]+1 > mod->numpos ? mod->numpos : mod->patterns[mod->sngpos]+1), (mod->sngpos+1 > mod->numpos ? mod->numpos : mod->sngpos+1), mod->numpos); wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD); mvwprintw(dspwin, MODINFO_Y, 28, "Pos:"); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(dspwin, "%3d", mod->patpos); wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD); mvwprintw(dspwin, MODINFO_Y, 37, "Bpm:"); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(dspwin, "%3d", mod->bpm); wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD); mvwprintw(dspwin, MODINFO_Y, 46, "Spd:"); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(dspwin, "%3d", mod->sngspd); wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD); mvwprintw(dspwin, MODINFO_Y, 55, "Tmp:"); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(dspwin, "%3d", mod->inittempo); wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD); mvwprintw(dspwin, MODINFO_Y, 64, "Rvb:"); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(dspwin, "%2d", md_reverb); wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD); mvwprintw(dspwin, MODINFO_Y, 72, "Vol:"); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(dspwin, "%3d", mod->volume); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); mvwprintw(dspwin, DSP_H-1, COLS-17, "[ ]"); wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD); mvwprintw(dspwin, DSP_H-1, COLS-15, "Time:"); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); mvwprintw(dspwin, DSP_H-1, COLS-9, "%02d:%02d", ((mod->sngtime/1000)/60), ((mod->sngtime/1000)%60)); if (in_playlist) refresh_pl_info(); else if (need_to_clear) { for (i = 1; i < 60; i++) mvwaddch(dspwin, DSP_H-1, i, ACS_HLINE); need_to_clear = 0; } if (!hidden && pp != mod->patpos) { wattrset(dspwin, COLOR_PAIR(GREEN_BLUE)|A_BOLD); mvwaddch(dspwin, 0, 1, hc[(hcnt) & 3]); mvwaddch(dspwin, 0, 2, hc[(hcnt+1) & 3]); mvwaddch(dspwin, 0, 9+strlen(VERSION), hc[(hcnt+2) & 3]); mvwaddch(dspwin, 0, 10+strlen(VERSION), hc[(hcnt+3) & 3]); hcnt++, pp = mod->patpos; wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); } } /*** Display channels info. ***/ static void refresh_info(void) { int i; int vol = 0, pc; int panc, panx; int period; float vol1, vol2; float f1, f2; unsigned char pan, vpan; chtype attr; if (mod == NULL) { for (i = (page*(DSP_H-CHN_START)); i < ((page+1)*(DSP_H-CHN_START)); i++) { int y = i%(DSP_H-CHN_START); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); mvwprintw(dspwin, y+4, 1, " %02d %6d %6d %6d %6d %3d ", y, 0, 0, 0, 0, 0); draw_gauge(dspwin, 52, y+CHN_START-1, 0, 1, gauge_style); } return; } for (i = (page*(DSP_H-CHN_START)); i < ((page+1)*(DSP_H-CHN_START)); i++) { int y = i%(DSP_H-CHN_START); if (i > mod->numchn-1) { if ((mod->sngpos == 0 && mod->patpos < 1) || lastpage < page) mvwprintw(dspwin, y+CHN_START-1, 1, "%78s", ""); continue; } /* Print line. */ if (muted[i] == 0) { period = get_channel_period(i); /* Channel # */ if (period == 0) vol = 0; else vol = get_voice_volume(get_channel_voice(i)); if (vol > 0) { wattrset(dspwin, (attr = COLOR_PAIR(CYAN_BLUE)|A_BOLD)); } else { wattrset(dspwin, (attr = COLOR_PAIR(WHITE)|A_NORMAL)); } mvwprintw(dspwin, y+CHN_START-1, 1, "%02d", i+1); /* Channel period. */ wattrset(dspwin, (attr = COLOR_PAIR(WHITE)|A_NORMAL)); mvwprintw(dspwin, y+CHN_START-1, 5, "%6d", period); /* Set line color from voice volume. */ if (period == 0) { vol = 0; wattrset(dspwin, (attr = COLOR_PAIR(WHITE)|A_NORMAL)); goto NO_VOLCLR; } vol = get_voice_volume(get_channel_voice(i)); if (vol > 0 && vol < 64) wattrset(dspwin, (attr = COLOR_PAIR(GREEN)|A_NORMAL)); else if (vol > 64 && vol < 128) wattrset(dspwin, (attr = COLOR_PAIR(GREEN)|A_BOLD)); else if (vol >= 128 && vol < 192) wattrset(dspwin, (attr = COLOR_PAIR(YELLOW)|A_BOLD)); else if (vol >= 192 && vol < 256) wattrset(dspwin, (attr = COLOR_PAIR(RED)|A_BOLD)); else if (vol == 256) wattrset(dspwin, (attr = COLOR_PAIR(WHITE_RED)|A_BOLD)); NO_VOLCLR: if (period != 0) { mvwprintw(dspwin, y+CHN_START-1, 13, "%2d %6d %6d", (get_channel_voice(i)+1), (get_voice_freq(get_channel_voice(i))), (get_voice_pos(get_channel_voice(i)))); } else { mvwprintw(dspwin, y+CHN_START-1, 13, "%2d %6d %6d", 0, 0, 0); } /* Panning. */ pan = (unsigned char) get_voice_panning( get_channel_voice(i)); if (period == 0) pan = 128; if (pan == 128) { wattrset(dspwin, COLOR_PAIR(BLUE)|A_BOLD); } else if (pan == 0 || (pan > 0 && pan < 128)) { wattrset(dspwin, COLOR_PAIR(MAGENTA)|A_BOLD); } else { wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD); } mvwprintw(dspwin, y+CHN_START-1, 33, "......."); if (pan == 0) { wattrset(dspwin, COLOR_PAIR(MAGENTA_MAGENTA)|A_BOLD); } else if (pan == 255) { wattrset(dspwin, COLOR_PAIR(CYAN_CYAN)|A_BOLD); } vpan = 0; panx = 0; panc = (pan == 128 ? 'M' : (pan == 0 || (pan > 0 && pan < 128) ? 'L' : 'R')); if (panc == 'M') { panx = 3; vpan = 128; } else if (panc == 'L') { if (pan == 0) { panx = 0; vpan = 127; } else if (pan == 127) { panx = 2; vpan = 0; } else { f1 = pan; f2 = 100.0 * (f1 / 127.0); f2 /= 33.0; panx = f2; vpan = 127 - pan; } } else if (panc == 'R') { pan -= 128; f1 = pan; f2 = 100.0 * (f1 / 127.0); f2 /= 33.0; panx = f2; if (panx > 2) panx = 2; panx += 4; vpan = pan; } mvwaddch(dspwin, y+CHN_START-1, 33+panx, panc); wattrset(dspwin, COLOR_PAIR(CYAN)|A_NORMAL); mvwprintw(dspwin, y+CHN_START-1, 41, "%3d", vpan); /* Volume. */ wattrset(dspwin, attr); mvwprintw(dspwin, y+CHN_START-1, 46, "%3d %c", vol, (lastvol[i] == vol ? '=' : (lastvol[i] < vol ? '+' : '-'))); lastvol[i] = vol; if (real_volume) { if (period == 0) { pc = 0; goto NO_CALC; } vol1 = get_voice_realvol( get_channel_voice(i)); vol2 = maxrvol[i]; if (vol2 <= 0) vol2 = 1; pc = (int) (100.0 * (vol1 / vol2)); if (pc > 100) pc = 100; NO_CALC: draw_gauge(dspwin, 54, y+CHN_START-1, pc, 1, gauge_style); } else { vol1 = vol; vol2 = maxvol[i]; if (vol2 <= 0) vol2 = 1; pc = (int) (100.0 * (vol1 / vol2)); draw_gauge(dspwin, 54, y+CHN_START-1, pc, 1, gauge_style); } } else { wattrset(dspwin, A_NORMAL); mvwprintw(dspwin, y+CHN_START-1, 1, "%02d ------ -- ------ ------- ------- --- MUTED", i+1); draw_gauge(dspwin, 54, y+CHN_START-1, 0, 1, gauge_style); } } draw_pointer(); } /*** Refresh driver info. ***/ static void refresh_driver_info(void) { int i; for (i = 1; i < COLS-1; i++) mvwaddch(dspwin, 3, i, ' '); wattrset(dspwin, COLOR_PAIR(WHITE)|A_BOLD); mvwprintw(dspwin, 3, 1, "Driver : "); wattrset(dspwin, COLOR_PAIR(MAGENTA)|A_BOLD); wprintw(dspwin, md_driver->Name); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); wprintw(dspwin, " - "); wattrset(dspwin, COLOR_PAIR(MAGENTA)|A_BOLD); wprintw(dspwin, "%s %s %s %s %s", (md_mode & DMODE_16BITS ? "16bit" : "8bit"), (md_mode & DMODE_REVERSE ? "!STEREO" : \ (md_mode & DMODE_STEREO ? "STEREO" : "MONO" )), (md_mode & DMODE_SURROUND ? "SURROUND" : "NORMAL" ), (md_mode & DMODE_HQMIXER ? "HQMIXER" : "LQMIXER" ), (md_mode & DMODE_SOFT_MUSIC ? "(soft)" : "(hard)")); wattrset(dspwin, COLOR_PAIR(YELLOW)|A_BOLD); wprintw(dspwin, " %d Hz", md_mixfreq); wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); } /*** Refresh legend bar. ***/ static void refresh_legend(void) { if (real_volume) { wattrset(dspwin, A_REVERSE); mvwprintw(dspwin, CHN_START-2, 0, "%-80s", " Ch Period Vc Freq Pos Panning Volume Real volume"); } else { wattrset(dspwin, A_REVERSE); mvwprintw(dspwin, CHN_START-2, 0, "%-80s", " Ch Period Vc Freq Pos Panning Volume Voice volume"); } } /******************************************************************************/ /*** Print the usual usage string. ***/ static void usage(void) { fprintf(stderr, ":: MP v%s ::\n", VERSION); fprintf(stderr, "Usage: mp [ -h | -v ]... [ module | playlist ]...\n"); fprintf(stderr, " -h help\n"); fprintf(stderr, " -v version\n"); fprintf(stderr, " module .xm, .it, .mod...\n"); fprintf(stderr, " playlist .pli\n"); } /*** Main control keys. ***/ void module_control(int c) { int i; switch (c) { /* * Next position. */ case 'n': if (pos < mod->numpos-1) { Player_NextPosition(); MikMod_Update(); pos = mod->sngpos; } break; /* * Next module. */ case 'N': if (in_playlist && pl_cnt < pl_files-1) { if (random_mode) { pl_cnt = (int) (((float)pl_files-1)*(rand()/ (RAND_MAX+1.0))); } else { pl_cnt++; } pl_playtime += mod->sngtime; Player_Stop(); loading(1); play_module( list_files[pl_cnt].fname); loading(0); refresh_pl_info(); } break; /* * Prev position. */ case 'v': if (mod->sngpos > 0) { mod->sngpos--; MikMod_Update(); pos = mod->sngpos; } break; /* * Prev module. */ case 'V': if (in_playlist && pl_cnt > 0) { pl_cnt--; Player_Stop(); loading(1); play_module( list_files[pl_cnt].fname); loading(0); refresh_pl_info(); } break; /* * Restart module. */ case 'A': if (playing == 0) playing = 1; Player_SetPosition(0); pos = 0; if (stopped) { stopped = 0; Player_Start(mod); } break; /* * Restart pattern. */ case 'a': mod->patpos = 0; MikMod_Update(); break; /* * Playlist. */ case 'l': playlist(); if (in_playlist && pl_files != 0 && pl_val != 255) { install_pl_handler(); pl_playtime = 0; Player_Stop(); loading(1); play_module(list_files[pl_cnt].fname); loading(0); refresh_pl_info(); } break; /* ;-) */ case KEY_F(12): hidden = 1-hidden; if (hidden) { wattrset(dspwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD); mvwprintw(dspwin, 0, 0, " :: MP v%s ::", VERSION); } break; /* * Play or pause. */ case 'p': if (stopped) { if (mod) { Player_Start(mod); stopped = 0; playing = 1; } } else { do_pause(); } break; /* * Stop. */ case 't': do_stop(); break; /* * Reverb +/- */ case 'r': if (md_reverb > 0) md_reverb--; break; case 'R': if (md_reverb < REVERB_LIMIT) md_reverb++; break; /* * Speed +/- */ case 's': if (mod->sngspd > 0) mod->sngspd--; break; case 'S': if (mod->sngspd < SPEED_LIMIT) mod->sngspd++; break; /* * BPM +/- */ case 'b': if (mod->bpm > 1) mod->bpm--; break; case 'B': if (mod->bpm < BPM_LIMIT) mod->bpm++; break; /* * Tempo +/- */ case 'k': if (mod->inittempo > 0) mod->inittempo--; break; case 'K': if (mod->inittempo < TEMPO_LIMIT) mod->inittempo++; break; /* * Volume +/- */ case '+': if (mod->volume < MODVOL_LIMIT) mod->volume++; break; case '-': if (mod->volume > 0) mod->volume--; break; /* * Reverse stereo */ case '!': if ((md_mode & DMODE_STEREO)) reverse_stereo = 1-reverse_stereo; else break; if (!reverse_stereo) { md_mode &= ~DMODE_REVERSE; } else md_mode |= DMODE_REVERSE; refresh_driver_info(); break; /* * Switch volume display. */ case 'u': real_volume = 1-real_volume; refresh_legend(); break; /* * Mute all channels. */ case 'M': for (i = 0; i < mod->numchn; i++) { if (output == 1) { muted[i] = 1; Player_Mute(i); } else { muted[i] = 0; Player_Unmute(i); } } output = 1-output; draw_pointer(); break; /* * Module info. */ case 'i': if (mod) module_info(mod); break; /* * Help. */ case 'h': case 'H': display_help(); break; /* * About. */ case '?': about(); break; } } /****************************************************************************** *** *** Start here. *** ******************************************************************************/ int main(int argc, char *argv[]) { /* Variables. */ int key; struct stat sbuf; char str[NAME_MAX+1]; char *modname; /* If called without arguments. */ if (argv[1] == NULL) { usage(); exit(-1); /* Help? */ } else if (strncmp(argv[1], "-h", 2) == 0) { usage(); exit(0); /* Version? */ } else if (strncmp(argv[1], "-v", 2) == 0) { fprintf(stderr, ":: MP v%s ::\n", VERSION); exit(0); /* Check file. */ } else if (access(argv[1], R_OK) != 0) { fprintf(stderr, "MP: Can't open '%s'\n", argv[1]); exit(-1); stat(argv[1], &sbuf); if (S_ISREG(sbuf.st_mode) == 0) { fprintf(stderr, "MP: Can't open '%s'\n", argv[1]); exit(-1); } } /* * Check for presence of the '.mp' directory * in the user homedir. */ sprintf(str, "%s/.mp", (getenv("HOME"))); if (access(str, R_OK) != 0) { fprintf(stderr, "MP: Can't access '%s', creating it.\n", str); mkdir(str, 0644); } else { read_options_file(); } /* Init sound. */ init_sound(); /* Init curses. */ init_nc(); read_options_file(); init_windows(); oldc1 = mvwinch(dspwin, curch+3, 0); oldc2 = mvwinch(dspwin, curch+3, 3); /* * Load module. */ if (argv[1] != NULL) { loading(1); if (play_module(argv[1])) { leave(0); usage(); exit(-1); } else playing = 1; loading(0); } else { wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL); mvwprintw(dspwin, 0, 1, " No module loaded. Press 'f' for file selector. "); playing = 0; } /* Create screen. */ refresh_driver_info(); refresh_info(); refresh_module_info(); doupdate(); /* Ensure we do a clean exit if those signals are received... */ signal(SIGTERM, leave); signal(SIGINT, leave); signal(SIGUSR1, leave); signal(SIGUSR2, leave); /*** Main loop ***/ while ((key = wgetch(dspwin)) != 'q') { module_control(key); switch (key) { /* * Show all channels. */ case 'c': case 'C': if (mod != NULL) show_all_channels(); else beep(); break; /* * Show voices frequency. */ case 'y': if (mod != NULL) show_voices_freq(); else beep(); break; /* * Show voices position. */ case 'Y': if (mod != NULL) show_voices_pos(); else beep(); break; /* * Select file. */ case 'f': modname = file_select(); touchwin(dspwin); wnoutrefresh(dspwin); doupdate(); if (modname != NULL && (strlen(modname)) > 0) { loading(1); if (!(play_module(full_modname))) { in_playlist = 0; need_to_clear = 1; } loading(0); touchwin(dspwin); } break; /* * Effects. */ case 'e': effects(); break; /* * Options. */ case 'o': options(); break; /* * Show samples. */ case 'w': show_samples(); break; /* * Show instruments. */ case 'W': show_instruments(); break; /* * Move up. */ case KEY_UP: if (mod == NULL) break; if (curch > 0) curch--; page = (curch/(DSP_H-CHN_START)); draw_pointer(); break; case KEY_PPAGE: if (mod == NULL) break; if (curch == 0) break; if (curch == (page*(DSP_H-CHN_START))) { curch = (--page*(DSP_H-CHN_START)); break; } curch = (page*(DSP_H-CHN_START)); draw_pointer(); break; /* * Move down. */ case KEY_DOWN: if (mod == NULL) break; if (curch < mod->numchn-1) curch++; page = (curch/(DSP_H-CHN_START)); draw_pointer(); break; case KEY_NPAGE: if (mod == NULL) break; if (((page+1)*(DSP_H-CHN_START)) >= mod->numchn) { curch = mod->numchn-1; draw_pointer(); break; } curch = ((page+1)*(DSP_H-CHN_START)); page = (curch/(DSP_H-CHN_START)); draw_pointer(); break; /* * Change gauge style. */ case '*': if (gauge_style < 5) gauge_style++; else gauge_style = 1; break; /* * Tracks view. */ case 'T': //track_view(); show_all_voices(); break; /* * Bass. */ case '<': if (bass) { bass--; ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_BASS), &bass); } break; case '>': if (bass < BASS_LIMIT) { bass++; ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_BASS), &bass); } break; /* * Treble. */ case 'x': if (treble) { treble--; ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_BASS), &treble); } break; case 'X': if (treble < TREBLE_LIMIT) { treble++; ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_BASS), &treble); } break; /* * Mute channel. */ case KEY_ENTER: if (muted[curch]) { muted[curch] = 0; Player_Unmute(curch); refresh_info(); } else { muted[curch] = 1; Player_Mute(curch); refresh_info(); } draw_pointer(); break; } if (mod && playing) { refresh_info(); refresh_module_info(); update_panels(); doupdate(); MikMod_Update(); } } /* Leaving... */ in_playlist = 0; /* End here. */ clear(); refresh(); leave(0); } /* EOF */