1 /***
2  ***
3  ***	MP - a free music module player based on ncurses (GUI)
4  ***	and mikmod (sound engine).
5  ***
6  ***
7  ***	Copyright (C) 2003-2004 Gael Gence <gael.gence@skynet.be>
8  ***	                        and Gregoire Welraeds
9  ***
10  ***
11  ***
12  ***	For licence, please refer to the COPYING file distributed
13  ***	with the archive.
14  ***
15  ***
16  ***
17  ***	Home site: http://mp.waw.cx/
18  ***
19  ***/
20 
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <signal.h>
25 #include <dirent.h>
26 #include <fcntl.h>
27 #include <sys/ioctl.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/soundcard.h>
31 
32 #include <curses.h>
33 #include <panel.h>
34 #include <mikmod.h>
35 
36 
37 /******************************************************************************
38  ***
39  ***				Defines.
40  ***
41  ******************************************************************************/
42 
43 #define VERSION		"0.6"		/* here it is */
44 #define NAME_MAX	255
45 
46 
47 /*** Various. ***/
48 #define MIN_FREQ	4000		/* minimum frequency */
49 #define MAX_FREQ	60000		/* maximum frequency */
50 #define MAX_CHANNELS	64		/* max # channels */
51 
52 #define CHN_START	7		/* display channel y start */
53 #define FILE_Y		1		/* module file y pos */
54 #define TITLE_Y		2		/* module title y pos */
55 #define DRIVER_Y	3		/* driver info y pos */
56 #define MODINFO_Y	4		/* module info y pos */
57 
58 #define EFFECTS		10		/* # of effects */
59 
60 /*** Options. ***/
61 #define OPTIONS		12		/* # of options */
62 #define _16BITS_OPT	0		/* option # */
63 #define STEREO_OPT	1		/* option # */
64 #define REVSTEREO_OPT	2		/* option # */
65 #define SURROUND_OPT	3		/* option # */
66 #define INTERPOLATE_OPT	4		/* option # */
67 #define HQMIXER_OPT	6		/* option # */
68 #define MIXFREQ_OPT	7		/* option # */
69 #define LOOP_OPT	9		/* option # */
70 #define FADE_OPT	10		/* option # */
71 #define RANDOM_OPT	11		/* option # */
72 #define DELAY_OPT	13		/* option # */
73 #define SAVE_OPT	15		/* option # */
74 
75 /*** Limits. ***/
76 #define SPEED_LIMIT	256
77 #define REVERB_LIMIT	15
78 #define STEREO_LIMIT	128
79 #define TEMPO_LIMIT	256
80 #define BPM_LIMIT	256
81 #define GENVOL_LIMIT	128
82 #define MODVOL_LIMIT	256
83 #define REALVOL_LIMIT	65535
84 #define MIXVOL_LIMIT	25700
85 #define BASS_LIMIT	256
86 #define TREBLE_LIMIT	256
87 
88 #define MAX_FILES	16384
89 
90 /*** Message IDs ***/
91 #define ERROR_MSG	1
92 #define INFO_MSG	2
93 
94 /*** Keys. ***/
95 #undef KEY_TAB
96 #define KEY_TAB         9
97 
98 #undef KEY_ENTER
99 #define KEY_ENTER       10
100 
101 #undef KEY_DELETE
102 #define KEY_DELETE      330
103 
104 #undef KEY_BACKSPACE
105 #define KEY_BACKSPACE   263
106 
107 #undef KEY_ESCAPE
108 #define KEY_ESCAPE	27
109 
110 #undef KEY_SPACE
111 #define KEY_SPACE	0
112 
113 /*** Windows coords. ***/
114 #define AC_W		68
115 #define AC_H		16
116 int AC_X;
117 int AC_Y;		/* all channels window */
118 
119 #define VFREQ_W		68
120 #define VFREQ_H		16
121 int VFREQ_X;
122 int VFREQ_Y;		/* all channels window */
123 
124 #define VPOS_W		68
125 #define VPOS_H		16
126 int VPOS_X;
127 int VPOS_Y;		/* voices position window */
128 
129 #define FS_W		60
130 #define FS_H		(LINES-3)
131 int FS_X;
132 int FS_Y;		/* file selector window */
133 
134 #define PL_W		72
135 #define PL_H		(LINES-2)
136 int PL_X;
137 int PL_Y;		/* playlist window */
138 
139 #define EFT_W		40
140 #define EFT_H		EFFECTS+4
141 int EFT_X;
142 int EFT_Y;		/* effect window */
143 
144 #define OPT_W		40
145 #define OPT_H		OPTIONS+8
146 int OPT_X;
147 int OPT_Y;		/* options window */
148 
149 #define SMP_W		54
150 #define SMP_H		15
151 int SMP_X;
152 int SMP_Y;		/* samples window */
153 
154 #define INS_W		54
155 #define INS_H		13
156 int INS_X;
157 int INS_Y;		/* instruments window */
158 
159 #define DSP_X		0
160 #define DSP_Y		0
161 int DSP_W;
162 int DSP_H;		/* display window */
163 
164 #define HELP_H		20
165 #define HELP_W		70
166 int HELP_X;
167 int HELP_Y;		/* help window */
168 
169 /*** Colors. ***/
170 #define WHITE			0
171 #define RED			1
172 #define GREEN			2
173 #define BLUE			3
174 #define YELLOW			4
175 #define CYAN			5
176 #define MAGENTA			6
177 #define BLUE_BLUE		7
178 #define CYAN_BLUE		8
179 #define GREEN_BLUE		9
180 #define YELLOW_BLUE		10
181 #define MAGENTA_MAGENTA		11
182 #define CYAN_CYAN		12
183 #define RED_RED			13
184 #define WHITE_RED		14
185 
186 
187 /******************************************************************************
188  ***
189  ***				Global variables.
190  ***
191  ******************************************************************************/
192 
193 /*** Various. ***/
194 int pos         = 0;			/* current position */
195 int page        = 0;			/* vertical page */
196 int gauge_style = 1;			/* block */
197 
198 int curch    = 0;			/* current channel number */
199 int oldcurch = 0;			/* last channel number */
200 chtype oldc1, oldc2;			/* previous characters (pointer) */
201 
202 MODULE *mod = NULL;			/* current module */
203 
204 int DELAY = 40;				/* screen refresh delay */
205 
206 /*** Mixer. ***/
207 char *mixerdev = "/dev/mixer";		/* mixer device */
208 int mixerfd    = 0;			/* mixer file descriptor */
209 int mixerok    = 0;			/* set to 1 of open succeeds */
210 int treble     = 0;
211 int bass       = 0;
212 int mixvol     = 0;
213 
214 /*** Options. ***/
215 char _16bits        = 1;
216 char stereo         = 1;
217 char surround       = 1;
218 char hq_mixer       = 1;
219 char loop_module    = 0;		/* yes by default in MikMod */
220 char fade_module    = 0;
221 char random_mode    = 0;
222 char reverse_stereo = 0;
223 char interpolate    = 0;
224 
225 /*** Flags. ***/
226 char stopped     = 0;			/* set to 1 when module stooped */
227 char in_playlist = 0;			/* set to 1 when playlist */
228 char output      = 1;			/* used for muting all channels */
229 char playing     = 0;			/* 1 playing module, 0 not playing */
230 char real_volume = 1;			/* real volume display switch */
231 char ptn_view    = 0;			/* pattern view */
232 
233 /*** Paths and names. ***/
234 char option_file[NAME_MAX+1];		/* option file path */
235 
236 char moddir[NAME_MAX+1];		/* module directory */
237 char full_modname[NAME_MAX+1];		/* full module path */
238 char *short_modname;			/* module name only */
239 
240 char pl_file[NAME_MAX+1];		/* playlist file */
241 
242 /*** Channels info arrays. ***/
243 int lastvol[MAX_CHANNELS];		/* last volume of each channel */
244 int  maxvol[MAX_CHANNELS];		/* max channels volume */
245 int maxrvol[MAX_CHANNELS];		/* max channels real volume */
246 int maxfreq[MAX_CHANNELS];		/* max channels frequency */
247 int  maxpos[MAX_CHANNELS];		/* max channels frequency */
248 char  muted[MAX_CHANNELS];		/* keep channels mute status */
249 int maxrvoli;
250 
251 /*** Current file size in bytes and KB. ***/
252 int file_sizeb;
253 float file_size;
254 
255 /*** Windows. ***/
256 WINDOW *dspwin;
257 PANEL *dsppan;
258 
259 WINDOW *eftwin;
260 PANEL *eftpan;
261 
262 WINDOW *optwin;
263 PANEL *optpan;
264 
265 WINDOW *acwin;
266 PANEL *acpan;
267 
268 WINDOW *vposwin;
269 PANEL *vpospan;
270 
271 WINDOW *vfreqwin;
272 PANEL *vfreqpan;
273 
274 WINDOW *poswin;
275 PANEL *pospan;
276 
277 WINDOW *helpwin;
278 PANEL *helppan;
279 
280 WINDOW *smpwin;
281 PANEL *smppan;
282 
283 WINDOW *inswin;
284 PANEL *inspan;
285 
286 WINDOW *fswin;
287 PANEL *fspan;
288 
289 WINDOW *plwin;
290 PANEL *plpan;
291 
292 
293 /******************************************************************************
294  ***
295  ***				Prototypes.
296  ***
297  ******************************************************************************/
298 
299 /* Used once. */
300 static void init_nc(void);			/* init ncurses */
301 static void init_windows(void);			/* init windows */
302 static void init_sound(void);			/* init mikmod */
303 static void leave(int ignored);			/* leave cleanly */
304 
305 /* Get voice information. */
306 static inline int get_voice_volume(int channel);
307 static inline int get_voice_realvol(int channel);
308 static inline int get_voice_panning(int channel);
309 static inline int get_voice_freq(int channel);
310 static inline int get_voice_pos(int channel);
311 static inline int get_channel_period(int channel);
312 
313 /* Module related. */
314 static int play_module(char *modname);
315 void module_control(int c);
316 static void do_pause(void);
317 static void do_stop(void);
318 
319 /* Windows. */
320 static void options(void);
321 static void effects(void);
322 
323 /* Info. */
324 static void refresh_driver_info(void);
325 static void refresh_info(void);
326 static void refresh_module_info(void);
327 static void refresh_legend(void);
328 static void refresh_pl_info(void);
329 
330 /* Utils. */
331 static void draw_pointer(void);
332 static void draw_gauge(WINDOW *win, int x, int y, int pc, int vh, int style);
333 static void get_string(WINDOW *win, int ys, int xs, char *prompt, char *str);
334 static char *file_select(void);
335 static void mp_move_panel(PANEL *pan);
336 static void message(char *msg, int level);
337 
338 
339 /******************************************************************************
340  ***
341  ***				Functions.
342  ***
343  ******************************************************************************/
344 
345 /*** . ***/
dot(void)346 static void dot(void)
347 {
348 	printf(".");
349 }
350 
351 /*** Initialize ncurses and colors. ***/
init_nc(void)352 static void init_nc(void)
353 {
354 	/* Init ncurses. */
355 	if ((initscr()) == NULL) {
356 		fprintf(stderr, "MP: Can't init ncurses.\n");
357 		exit(-1);
358 	}
359 
360 	/* Set display (main) window dimensions. */
361 	DSP_W = COLS;
362 	DSP_H = LINES;
363 
364 	/* Set window options. */
365 	cbreak();
366 	noecho();
367 	timeout(DELAY);
368 	curs_set(0);
369 	keypad(stdscr, TRUE);
370 
371 	/* Init colors. */
372 	if ((has_colors()) == FALSE) {
373 		endwin();
374 		fprintf(stderr, "mp: Terminal doesn't support colors.\n");
375 		exit(-1);
376 	}
377 	start_color();
378 
379 	init_pair(RED, COLOR_RED, COLOR_BLACK);
380 	init_pair(GREEN, COLOR_GREEN, COLOR_BLACK);
381 	init_pair(BLUE, COLOR_BLUE, COLOR_BLACK);
382 	init_pair(YELLOW, COLOR_YELLOW, COLOR_BLACK);
383 	init_pair(CYAN, COLOR_CYAN, COLOR_BLACK);
384 	init_pair(MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
385 
386 	init_pair(BLUE_BLUE, COLOR_BLUE, COLOR_BLUE);
387 	init_pair(CYAN_BLUE, COLOR_CYAN, COLOR_BLUE);
388 	init_pair(GREEN_BLUE, COLOR_GREEN, COLOR_BLUE);
389 	init_pair(YELLOW_BLUE, COLOR_YELLOW, COLOR_BLUE);
390 	init_pair(MAGENTA_MAGENTA, COLOR_MAGENTA, COLOR_MAGENTA);
391 	init_pair(CYAN_CYAN, COLOR_CYAN, COLOR_CYAN);
392 	init_pair(RED_RED, COLOR_RED, COLOR_RED);
393 	init_pair(WHITE_RED, COLOR_WHITE, COLOR_RED);
394 
395 	/* Calculate default windows coords. */
396 	AC_X = ((COLS/2)-(AC_W/2));
397 	AC_Y = ((LINES/2)-(AC_H/2));		/* all channels window */
398 
399 	VFREQ_X = ((COLS/2)-(VFREQ_W/2));
400 	VFREQ_Y = ((LINES/2)-(VFREQ_H/2));	/* voices frequency */
401 
402 	VPOS_X = ((COLS/2)-(VPOS_W/2));
403 	VPOS_Y = ((LINES/2)-(VPOS_H/2));	/* voices position */
404 
405 	FS_X = ((COLS/2)-(FS_W/2));
406 	FS_Y = ((LINES/2)-(FS_H/2));		/* file selector window */
407 
408 	PL_X = ((COLS/2)-(PL_W/2));
409 	PL_Y = ((LINES/2)-(PL_H/2));		/* playlist window */
410 
411 	EFT_X = ((COLS/2)-(EFT_W/2));
412 	EFT_Y = ((LINES/2)-(EFT_H/2));		/* effect window */
413 
414 	OPT_X = ((COLS/2)-(OPT_W/2));
415 	OPT_Y = ((LINES/2)-(OPT_H)/2);		/* options window */
416 
417 	SMP_X = ((COLS/2)-(SMP_W)/2);
418 	SMP_Y = ((LINES/2)-(SMP_H/2));		/* samples window */
419 
420 	INS_X = ((COLS/2)-(INS_W)/2);
421 	INS_Y = ((LINES/2)-(INS_H/2));		/* instruments window */
422 
423 	HELP_X = ((COLS/2)-(HELP_W)/2);
424 	HELP_Y = ((LINES/2)-(HELP_H/2));	/* help window */
425 }
426 
427 /*** Initialize windows. ***/
init_windows(void)428 static void init_windows(void)
429 {
430 	dspwin = newwin(DSP_H, DSP_W, DSP_Y, DSP_X);
431 	wtimeout(dspwin, DELAY);
432 	keypad(dspwin, TRUE);
433 	leaveok(dspwin, TRUE);
434 	box(dspwin, 0, 0);
435 	refresh_legend();
436 
437 	dsppan = new_panel(dspwin);
438 
439 	wattrset(dspwin, COLOR_PAIR(GREEN_BLUE)|A_BOLD);
440 	mvwprintw(dspwin, 0, 0, "%80s", "Press 'h' for help  ");
441 	wattrset(dspwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD);
442 	mvwprintw(dspwin, 0, 0, " :: MP v%s ::", VERSION);
443 
444 	update_panels();
445 	doupdate();
446 }
447 
448 /*** Initialize MikMod. ***/
init_sound(void)449 static void init_sound(void)
450 {
451 	/* Register loaders and drivers. */
452 	MikMod_RegisterAllDrivers();
453 	MikMod_RegisterAllLoaders();
454 
455 	/* Set options. */
456 	if (_16bits == 1)
457 		md_mode |= DMODE_16BITS;
458 	else
459 		md_mode &= ~DMODE_16BITS;
460 
461 	if (stereo == 1)
462 		md_mode |= DMODE_STEREO;
463 	else
464 		md_mode &= ~DMODE_STEREO;
465 
466 	if (reverse_stereo == 1)
467 		md_mode |= DMODE_REVERSE;
468 	else
469 		md_mode &= ~DMODE_REVERSE;
470 
471 	if (interpolate == 1)
472 		md_mode |= DMODE_INTERP;
473 	else
474 		md_mode &= ~DMODE_INTERP;
475 
476 	if (surround == 1)
477 		md_mode |= DMODE_SURROUND;
478 	else
479 		md_mode &= ~DMODE_SURROUND;
480 
481 	if (hq_mixer == 1)
482 		md_mode |= DMODE_HQMIXER;
483 	else
484 		md_mode &= ~DMODE_HQMIXER;
485 
486 	/* Initialize MikMod. */
487 	if (MikMod_Init("")) {
488 		fprintf(stderr, "\nMP: Couln't initialize sound, reason: %s.\n",
489 			MikMod_strerror(MikMod_errno));
490 		fprintf(stderr, "    Verify settings in $HOME/.mp/options\n");
491 		exit(-1);
492 	}
493 
494 	/* Open mixer (for volume, treble and bass). */
495 	if ((mixerfd = open(mixerdev, O_RDWR)) == -1)
496 		mixerok = 0;
497 	else
498 		mixerok = 1;
499 
500 	ioctl(mixerfd, MIXER_READ(SOUND_MIXER_VOLUME), &mixvol);
501 	ioctl(mixerfd, MIXER_READ(SOUND_MIXER_BASS), &bass);
502 	ioctl(mixerfd, MIXER_READ(SOUND_MIXER_TREBLE), &treble);
503 }
504 
505 /*** Close everything. ***/
leave(int ignored)506 static void leave(int ignored)
507 {
508 	/* Close mixer. */
509 	if (mixerok)
510 		close(mixerfd);
511 
512 	/* Close MikMod. */
513 	if (mod)
514 		Player_Free(mod);
515 	MikMod_Exit();
516 
517 	/* Close ncurses. */
518 	endwin();
519 
520 	/* Exit... */
521 	printf(":: MP v%s ::\n", VERSION);	/* ;) */
522 
523 	exit(0);
524 }
525 
526 /*** About window. ***/
about(void)527 static void about(void)
528 {
529 	WINDOW *tmpwin;
530 	PANEL *tmppan;
531 
532 	tmpwin = newwin(14, 40, (LINES/2)-6, (COLS/2)-20);
533 	wtimeout(tmpwin, DELAY);
534 	keypad(tmpwin, TRUE);
535 	tmppan = new_panel(tmpwin);
536 	box(tmpwin, 0, 0);
537 
538 	wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD);
539 	mvwprintw(tmpwin, 2, 12, ":: ");
540 	wattrset(tmpwin, COLOR_PAIR(GREEN)|A_BOLD);
541 	wprintw(tmpwin, "About ");
542 	wattrset(tmpwin, COLOR_PAIR(BLUE)|A_BOLD);
543 	wprintw(tmpwin, "MP ");
544 	wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD);
545 	wprintw(tmpwin, "::");
546 	wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD);
547 	mvwprintw(tmpwin, 4, 8, "Copyright (c) 2003-2004");
548 	wattrset(tmpwin, COLOR_PAIR(CYAN)|A_NORMAL);
549 	mvwprintw(tmpwin, 5, 4, "Gael Gence and Gregoire Welraeds");
550 	wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL);
551 	mvwprintw(tmpwin, 8, 5, "mp.c v%s (280104): 5984 lines", VERSION);
552 	wattrset(tmpwin, COLOR_PAIR(BLUE)|A_BOLD);
553 	mvwprintw(tmpwin, 11, 11, "http:");
554 	wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD);
555 	mvwprintw(tmpwin, 11, 16, "//         /");
556 	wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD);
557 	mvwprintw(tmpwin, 11, 18, "mp.waw.cx");
558 
559 	while ((wgetch(tmpwin)) != 'q') {
560 		if (mod && playing) {
561 			refresh_info();
562 			refresh_module_info();
563 			update_panels();
564 			doupdate();
565 			MikMod_Update();
566 		}
567 	}
568 
569 	del_panel(tmppan);
570 	delwin(tmpwin);
571 }
572 
573 /******************************************************************************/
574 
575 /*** Get voice volume. ***/
get_voice_volume(int channel)576 static inline int get_voice_volume(int channel)
577 {
578 	int i;
579 
580 	i = Voice_GetVolume(channel);
581 
582 	if (maxvol[channel] < i)
583 		maxvol[channel] = i;
584 
585 	return i;
586 }
587 
588 /*** Get playing volume. ***/
get_voice_realvol(int channel)589 static inline int get_voice_realvol(int channel)
590 {
591 	int i;
592 
593 	i = Voice_RealVolume(channel);
594 
595 	if (maxrvol[channel] < i)
596 		maxrvol[channel] = i;
597 
598 	if (maxrvoli < i)
599 		maxrvoli = i;
600 
601 	return i;
602 }
603 
604 /*** Get voice panning. ***/
get_voice_panning(int channel)605 static inline int get_voice_panning(int channel)
606 {
607 	return(Voice_GetPanning(channel));
608 }
609 
610 /*** Get voice frequency. ***/
get_voice_freq(int channel)611 static inline int get_voice_freq(int channel)
612 {
613 	int i;
614 
615 	i = Voice_GetFrequency(channel);
616 	if (maxfreq[channel] < i)
617 		maxfreq[channel] = i;
618 
619 	return i;
620 }
621 
622 /*** Get voice position. ***/
get_voice_pos(int channel)623 static inline int get_voice_pos(int channel)
624 {
625 	int i;
626 
627 	i = Voice_GetPosition(channel);
628 	if (maxpos[channel] < i)
629 		maxpos[channel] = i;
630 
631 	return i;
632 }
633 
634 /*** Get channel period. ***/
get_channel_period(int channel)635 static inline int get_channel_period(int channel)
636 {
637 	return(Player_GetChannelPeriod(channel));
638 }
639 
640 /*** Get channel voice. ***/
get_channel_voice(int channel)641 static inline int get_channel_voice(int channel)
642 {
643 	return(Player_GetChannelVoice(channel));
644 }
645 
646 /*****************************************************************************/
647 
648 /*** Show module info. ***/
649 #define CMT_H		21
650 #define CMT_W		73
651 int CMT_X;
652 int CMT_Y;
653 
module_info(MODULE * mod)654 static void module_info(MODULE *mod)
655 {
656 	int i;
657 	int c;
658 	int x, y, cnt, len, xoff = 0;
659 	WINDOW *tmpwin, *minfowin;
660 	PANEL *minfopan;
661 
662 	if (mod == NULL)
663 		return;
664 
665 	if (mod->comment == NULL) {
666 		message("No comment in this module.", INFO_MSG);
667 		return;
668 	}
669 
670 	CMT_X = ((COLS/2)-(CMT_W/2));
671 	CMT_Y = ((LINES/2)-(CMT_H/2));
672 
673 	tmpwin = newwin(CMT_H, CMT_W, CMT_Y, CMT_X);
674 	if (tmpwin == NULL)
675 		return;
676 	wtimeout(tmpwin, DELAY);
677 	keypad(tmpwin, TRUE);
678 	box(tmpwin, 0, 0);
679 	mvwprintw(tmpwin, 0, 2, "[         ]");
680 	wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD);
681 	mvwprintw(tmpwin, 0, 4, "Comment");
682 	wattrset(tmpwin, A_NORMAL);
683 
684 	minfopan = new_panel(tmpwin);
685 	minfowin = subwin(tmpwin, CMT_H-2, CMT_W-2, CMT_Y+1, CMT_X+1);
686 
687 	wattrset(minfowin, COLOR_PAIR(CYAN)|A_NORMAL);
688 	cnt = 0;
689 	len = strlen(mod->comment);
690 	for (y = 0; y < CMT_H; y++) {
691 		if (y == CMT_H-1 && xoff == 0) {
692 			for (i = 0; i < CMT_H-2; i++) {
693 				wattrset(minfowin, COLOR_PAIR(WHITE)|A_NORMAL);
694 				mvwaddch(minfowin, i, 34, '|');
695 				wattrset(minfowin, COLOR_PAIR(CYAN)|A_NORMAL);
696 			}
697 			y = 0;
698 			xoff = 36;
699 		}
700 		for (x = 0; x < (CMT_W/2)-3; x++, cnt++) {
701 			if (cnt >= len) break;
702 			mvwaddch(minfowin, y, x + xoff, mod->comment[cnt]);
703 		}
704 	}
705 
706 	/*** Loop ***/
707 	while ((c = wgetch(tmpwin)) != 'q') {
708 		module_control(c);
709 
710 		if (mod && playing) {
711 			refresh_info();
712 			refresh_module_info();
713 			update_panels();
714 			doupdate();
715 			MikMod_Update();
716 		}
717 	}
718 
719 	del_panel(minfopan);
720 	delwin(minfowin);
721 }
722 
723 /*** Load and start module. ***/
play_module(char * modname)724 static int play_module(char *modname)
725 {
726 	int i;
727 	struct stat sbuf;
728 	char buf[NAME_MAX+1];
729 	MODULE *new;
730 
731 	/* Check file. */
732 	if (access(modname, R_OK) != 0) {
733 		/* Avoid core dump if file can't be read. */
734 		playing = 0;
735 		beep();
736 		message("File can't be read.", ERROR_MSG);
737 		return -1;
738 	}
739 
740 	stat(modname, &sbuf);
741 	if (S_ISREG(sbuf.st_mode) == 0) {
742 		playing = 0;
743 		beep();
744 		message("Not a file.", ERROR_MSG);
745 		return -1;
746 	}
747 
748 	file_size = (((float) (sbuf.st_size)) / 1024.0);
749 	file_sizeb = sbuf.st_size;
750 	if ((short_modname = rindex(modname, '/')) != NULL)
751 		short_modname++;
752 	else
753 		short_modname = modname;
754 
755 	/* Load module. */
756 	new = Player_Load(modname, MAX_CHANNELS, 0);
757 	if (new != NULL) {
758 		if (mod != NULL)
759 			Player_Free(mod);
760 		mod = new;
761 
762 		wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
763 		for (i = 1; i < COLS-2; i++)
764 			mvwaddch(dspwin, TITLE_Y, i, ' ');
765 
766 		wattrset(dspwin, COLOR_PAIR(WHITE)|A_BOLD);
767 		mvwprintw(dspwin, 2, 1, "Title  : ");
768 		wattrset(dspwin, COLOR_PAIR(CYAN)|A_NORMAL);
769 		wprintw(dspwin, strlen(mod->songname) > 0 ?
770 				mod->songname : "");
771 
772 		wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
773 		wprintw(dspwin, " - " );
774 		wattrset(dspwin, COLOR_PAIR(WHITE)|A_BOLD);
775 		wprintw(dspwin, "Type: ");
776 		wattrset(dspwin, COLOR_PAIR(CYAN|A_NORMAL));
777 		wprintw(dspwin, strlen(mod->modtype) > 0 ?
778 				mod->modtype : "");
779 
780 	} else {
781 		beep();
782 		sprintf(buf, "%s.", MikMod_strerror(MikMod_errno));
783 		message(buf, ERROR_MSG);
784 		return -1;
785 	}
786 	curch = 0;
787 	memset(muted, 0, sizeof(muted));
788 
789 	refresh_module_info();
790 	refresh_info();
791 	draw_pointer();
792 
793 	/* Start the module. */
794 	if (mod != NULL) {
795 		pos = 0;
796 		mod->loop = loop_module;
797 		mod->fadeout = fade_module;
798 		for (i = 0; i < MAX_CHANNELS; maxvol[i] = MODVOL_LIMIT, i++);
799 
800 		wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
801 		for (i = 1; i < COLS-2; i++)
802 			mvwaddch(dspwin, FILE_Y, i, ' ');
803 
804 		wattrset(dspwin, COLOR_PAIR(WHITE)|A_BOLD);
805 		mvwprintw(dspwin, FILE_Y, 1, "File   : ");
806 		wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
807 		wprintw(dspwin, "%s  [ %d smp, %d ins, %d bytes, %.1f KB ]",
808 				short_modname,
809 				mod->numsmp,
810 				mod->numins,
811 				file_sizeb,
812 				file_size);
813 
814 		wnoutrefresh(dspwin);
815 		doupdate();
816 
817 		Player_Start(mod);
818 		playing = 1;
819 	}
820 
821 	return 0;
822 }
823 
824 /*** Pause the module. ***/
do_pause(void)825 static void do_pause(void)
826 {
827 	int c;
828 	WINDOW *tmpwin;
829 
830 	if (mod && playing) {
831 		tmpwin = newwin(5, 13, (LINES/2)-4, 34);
832 		box(tmpwin, 0, 0);
833 		wattrset(tmpwin, (COLOR_PAIR(YELLOW)|A_BOLD));
834 		mvwprintw(tmpwin, 2, 2, "Paused...");
835 
836 		Player_TogglePause();
837 
838 		wnoutrefresh(tmpwin);
839 		doupdate();
840 
841 		while ((c = wgetch(tmpwin)) != 'p');
842 
843 		Player_Start(mod);
844 		playing = 1;
845 
846 		delwin(tmpwin);
847 		touchwin(dspwin);
848 		doupdate();
849 
850 	} else {
851 		Player_Start(mod);
852 		playing = 1;
853 	}
854 }
855 
856 /*** Pause the module. ***/
do_stop(void)857 static void do_stop(void)
858 {
859 	WINDOW *tmpwin;
860 
861 	tmpwin = newwin(5, 15, (LINES/2)-4, 34);
862 	box(tmpwin, 0, 0);
863 	wattrset(tmpwin, (COLOR_PAIR(RED)|A_BOLD));
864 	mvwprintw(tmpwin, 2, 2, "Stopping...");
865 	wnoutrefresh(tmpwin);
866 	doupdate();
867 
868 	Player_SetPosition(0);
869 	Player_Stop();
870 	stopped = 1;
871 	playing = 0;
872 	mod->patpos = 0;
873 
874 	usleep(500000);
875 
876 	delwin(tmpwin);
877 	touchwin(dspwin);
878 	doupdate();
879 }
880 
881 /*****************************************************************************/
882 
883 /***
884  ***	Options window.
885  ***/
886 char *options_strings[OPTIONS+4] = {
887 	"16bit",
888 	"Stereo",
889 	"Reverse stereo",
890 	"Surround",
891 	"Interpolate",
892 	"",
893 	"High quality mixer",
894 	"Mixing frequency",
895 	"",
896 	"Loop module",
897 	"Fadeout module",
898 	"Random mode (playlist)",
899 	"",
900 	"Refresh delay",
901 	"",
902 	"Save options"
903 };
904 
905 /*** Print option and status. ***/
print_opt(WINDOW * win,int opt)906 static void print_opt(WINDOW *win, int opt)
907 {
908 	int c;
909 
910 	if (opt == MIXFREQ_OPT) {
911 		mvwprintw(win, opt+2, 3, " %s   [ %5d ] ",
912 				options_strings[opt], md_mixfreq);
913 
914 	} else if (opt == DELAY_OPT) {
915 		mvwprintw(win, opt+2, 3, " %s   [ %5d ] ",
916 				options_strings[opt], DELAY);
917 
918 	} else if (opt == SAVE_OPT) {
919 		mvwprintw(win, opt+2, 3, " %s ", options_strings[opt]);
920 
921 	} else {
922 		if (opt == HQMIXER_OPT && hq_mixer)
923 			c = 'X';
924 		else if (opt == _16BITS_OPT && _16bits)
925 			c = 'X';
926 		else if (opt == STEREO_OPT && stereo)
927 			c = 'X';
928 		else if (opt == REVSTEREO_OPT && reverse_stereo)
929 			c = 'X';
930 		else if (opt == SURROUND_OPT && surround)
931 			c = 'X';
932 		else if (opt == INTERPOLATE_OPT && interpolate)
933 			c = 'X';
934 
935 		else if (opt == LOOP_OPT && loop_module)
936 			c = 'X';
937 		else if (opt == FADE_OPT && fade_module)
938 			c = 'X';
939 		else if (opt == RANDOM_OPT && random_mode)
940 			c = 'X';
941 		else
942 			c = ' ';
943 
944 		mvwprintw(win, opt+2, 3, " [%c] %s ",
945 			c, options_strings[opt]);
946 	}
947 }
948 
949 /*** Get mix frequency from user. ***/
get_mix_freq(WINDOW * win)950 static void get_mix_freq(WINDOW *win)
951 {
952 	int c;
953 	int freq = md_mixfreq;
954 
955 	while ((c = wgetch(win)) != KEY_ENTER) {
956 		switch (c) {
957 			case ERR: break;
958 
959 			case KEY_RIGHT:
960 				  if (freq*2 < MAX_FREQ)
961 					  freq *= 2;
962 				  else
963 					  freq = MAX_FREQ;
964 			break;
965 
966 			case KEY_LEFT:
967 				  if (freq/2 > MIN_FREQ)
968 				  	freq /= 2;
969 				  else
970 					  freq = MIN_FREQ;
971 			break;
972 
973 			case KEY_UP:
974 				if (freq < MAX_FREQ)
975 					freq++;
976 			break;
977 			case KEY_PPAGE:
978 				if (freq+100 <= MAX_FREQ)
979 					freq += 100;
980 			break;
981 
982 			case KEY_DOWN:
983 				if (freq > MIN_FREQ)
984 					freq--;
985 			break;
986 			case KEY_NPAGE:
987 				if (freq-100 >= MIN_FREQ)
988 					freq -= 100;
989 			break;
990 		}
991 
992 		wattrset(win, A_NORMAL);
993 		mvwprintw(win, MIXFREQ_OPT+2, 3, " %s   [       ] ",
994 				options_strings[MIXFREQ_OPT]);
995 		wattrset(win, A_REVERSE);
996 		mvwprintw(win, MIXFREQ_OPT+2, 24, " %5d ", freq);
997 
998 		if (mod && playing) {
999 			refresh_info();
1000 			refresh_module_info();
1001 			update_panels();
1002 			doupdate();
1003 			MikMod_Update();
1004 		}
1005 	}
1006 
1007 	md_mixfreq = freq;
1008 	refresh_driver_info();
1009 }
1010 
1011 /*** Get DELAY from user. ***/
get_delay(WINDOW * win)1012 static void get_delay(WINDOW *win)
1013 {
1014 	int c;
1015 	int delay = DELAY;
1016 
1017 	while ((c = wgetch(win)) != KEY_ENTER) {
1018 		switch (c) {
1019 			case ERR: break;
1020 
1021 			case KEY_RIGHT:
1022 				  if (delay*2 < 10000)
1023 					  delay *= 2;
1024 				  else
1025 					  delay = 10000;
1026 			break;
1027 
1028 			case KEY_LEFT:
1029 				  if (delay/2 > 0)
1030 				  	delay /= 2;
1031 				  else
1032 					  delay = 0;
1033 			break;
1034 
1035 			case KEY_UP:
1036 				if (delay < 10000)
1037 					delay++;
1038 			break;
1039 			case KEY_PPAGE:
1040 				if (delay+5 <= 10000)
1041 					delay += 5;
1042 			break;
1043 
1044 			case KEY_DOWN:
1045 				if (delay > 0)
1046 					delay--;
1047 			break;
1048 			case KEY_NPAGE:
1049 				if (delay-5 >= 0)
1050 					delay -= 5;
1051 			break;
1052 		}
1053 
1054 		wattrset(win, A_NORMAL);
1055 		mvwprintw(win, DELAY_OPT+2, 3, " %s   [       ] ",
1056 				options_strings[DELAY_OPT]);
1057 		wattrset(win, A_REVERSE);
1058 		mvwprintw(win, DELAY_OPT+2, 21, " %5d ", delay);
1059 
1060 		if (mod && playing) {
1061 			refresh_info();
1062 			refresh_module_info();
1063 			update_panels();
1064 			doupdate();
1065 			MikMod_Update();
1066 		}
1067 	}
1068 
1069 	DELAY = delay;
1070 }
1071 
1072 /*** Read options file. ***/
read_options_file(void)1073 static void read_options_file(void)
1074 {
1075 	int cnt;
1076 	FILE *f;
1077 	char c;
1078 	char fixed_path[NAME_MAX+1];
1079 	char buf[NAME_MAX+1];
1080 	char *ptr1;
1081 
1082 	sprintf(fixed_path, "%s/%s", (getenv("HOME")), ".mp/options");
1083 	if ((f = fopen(fixed_path, "r")) == NULL)
1084 		return;
1085 
1086 	cnt = 0;
1087 	memset(buf, 0, NAME_MAX);
1088 	while ((fread(&c, 1, 1, f)) > 0) {
1089 		if (c != '\n') {
1090 			buf[cnt++] = c;
1091 			continue;
1092 		}
1093 
1094 		/* 16bits. */
1095 		if (!(strncmp(buf, "16bits", 5))) {
1096 			ptr1 = rindex(buf, '=');
1097 			ptr1++;
1098 			if (atoi(ptr1)) {
1099 				_16bits=1;
1100 			} else {
1101 				_16bits=0;
1102 			}
1103 
1104 		/* Stereo. */
1105 		} else if (!(strncmp(buf, "stereo", 6))) {
1106 			ptr1 = rindex(buf, '=');
1107 			ptr1++;
1108 			if (atoi(ptr1)) {
1109 				stereo=1;
1110 			} else {
1111 				stereo=0;
1112 			}
1113 
1114 		/* Reverse stereo. */
1115 		} else if (!(strncmp(buf, "reverse_stereo", 14))) {
1116 			ptr1 = rindex(buf, '=');
1117 			ptr1++;
1118 			if (atoi(ptr1)) {
1119 				reverse_stereo=1;
1120 			} else {
1121 				reverse_stereo=0;
1122 			}
1123 
1124 		/* Surround. */
1125 		} else if (!(strncmp(buf, "surround", 8))) {
1126 			ptr1 = rindex(buf, '=');
1127 			ptr1++;
1128 			if (atoi(ptr1)) {
1129 				surround=1;
1130 			} else {
1131 				surround=0;
1132 			}
1133 
1134 		/* Interpolate. */
1135 		} else if (!(strncmp(buf, "interpolate", 11))) {
1136 			ptr1 = rindex(buf, '=');
1137 			ptr1++;
1138 			if ((atoi(ptr1)) == 1) {
1139 				interpolate=1;
1140 			} else {
1141 				interpolate=0;
1142 			}
1143 
1144 		/* HQ mixer. */
1145 		} else if (!(strncmp(buf, "hq_mixer", 8))) {
1146 			ptr1 = rindex(buf, '=');
1147 			ptr1++;
1148 			if ((atoi(ptr1)) == 1) {
1149 				hq_mixer=1;
1150 			} else {
1151 				hq_mixer=0;
1152 			}
1153 
1154 		/* Loop module. */
1155 		} else if (!(strncmp(buf, "loop_module", 11))) {
1156 			ptr1 = rindex(buf, '=');
1157 			ptr1++;
1158 			if ((atoi(ptr1)) == 1) {
1159 				loop_module=1;
1160 			} else {
1161 				loop_module=0;
1162 			}
1163 
1164 		/* Fadeout module. */
1165 		} else if (!(strncmp(buf, "fade_module", 11))) {
1166 			ptr1 = rindex(buf, '=');
1167 			ptr1++;
1168 			if ((atoi(ptr1)) == 1) {
1169 				fade_module=1;
1170 			} else {
1171 				fade_module=0;
1172 			}
1173 
1174 		/* Random mode (playlist). */
1175 		} else if (!(strncmp(buf, "random_mode", 11))) {
1176 			ptr1 = rindex(buf, '=');
1177 			ptr1++;
1178 			if (atoi(ptr1)) {
1179 				random_mode=1;
1180 			} else {
1181 				random_mode=0;
1182 			}
1183 
1184 		/* Screen refresh delay. */
1185 		} else if (!(strncmp(buf, "delay", 5))) {
1186 			ptr1 = rindex(buf, '=');
1187 			ptr1++;
1188 			DELAY = atoi(ptr1);
1189 
1190 		/*** Windows coords. ***/
1191 		} else if (!(strncmp(buf, "AC_X", 4))) {
1192 			ptr1 = rindex(buf, '=');
1193 			ptr1++;
1194 			AC_X=atoi(ptr1);
1195 		} else if (!(strncmp(buf, "AC_Y", 4))) {
1196 			ptr1 = rindex(buf, '=');
1197 			ptr1++;
1198 			AC_Y=atoi(ptr1);
1199 
1200 		} else if (!(strncmp(buf, "VFREQ_X", 7))) {
1201 			ptr1 = rindex(buf, '=');
1202 			ptr1++;
1203 			VFREQ_X=atoi(ptr1);
1204 		} else if (!(strncmp(buf, "VFREQ_Y", 7))) {
1205 			ptr1 = rindex(buf, '=');
1206 			ptr1++;
1207 			VFREQ_Y=atoi(ptr1);
1208 
1209 		} else if (!(strncmp(buf, "VPOS_X", 6))) {
1210 			ptr1 = rindex(buf, '=');
1211 			ptr1++;
1212 			VPOS_X=atoi(ptr1);
1213 		} else if (!(strncmp(buf, "VPOS_Y", 6))) {
1214 			ptr1 = rindex(buf, '=');
1215 			ptr1++;
1216 			VPOS_Y=atoi(ptr1);
1217 
1218 		} else if (!(strncmp(buf, "OPT_X", 5))) {
1219 			ptr1 = rindex(buf, '=');
1220 			ptr1++;
1221 			OPT_X=atoi(ptr1);
1222 		} else if (!(strncmp(buf, "OPT_Y", 5))) {
1223 			ptr1 = rindex(buf, '=');
1224 			ptr1++;
1225 			OPT_Y=atoi(ptr1);
1226 
1227 		} else if (!(strncmp(buf, "EFT_X", 5))) {
1228 			ptr1 = rindex(buf, '=');
1229 			ptr1++;
1230 			EFT_X=atoi(ptr1);
1231 		} else if (!(strncmp(buf, "EFT_Y", 5))) {
1232 			ptr1 = rindex(buf, '=');
1233 			ptr1++;
1234 			EFT_Y=atoi(ptr1);
1235 		}
1236 
1237 		cnt = 0;
1238 		memset(buf, 0, NAME_MAX);
1239 	}
1240 
1241 	/* Check coords. */
1242 	if (EFT_Y+EFT_H >= LINES)
1243 		EFT_Y = 2;
1244 
1245 	if (OPT_Y+OPT_H >= LINES)
1246 		OPT_Y = 2;
1247 
1248 	if (VFREQ_Y+VFREQ_H >= LINES)
1249 		VFREQ_Y = 2;
1250 
1251 	if (VPOS_Y+VPOS_H >= LINES)
1252 		VPOS_Y = 2;
1253 
1254 	if (AC_Y+AC_H >= LINES)
1255 		AC_Y = 2;
1256 
1257 	fclose(f);
1258 }
1259 
1260 /*** Save options file. ***/
save_options_file(void)1261 static void save_options_file(void)
1262 {
1263 	FILE *f;
1264 	char fixed_path[NAME_MAX+1];
1265 	char buf[NAME_MAX+1];
1266 
1267 	sprintf(fixed_path, "%s/%s", (getenv("HOME")), ".mp/options");
1268 
1269 	f = fopen(fixed_path, "w");
1270 	if (f == NULL) {
1271 		sprintf(buf, "Can't open '%s'.", fixed_path);
1272 		message(buf, ERROR_MSG);
1273 		return;
1274 	}
1275 
1276 	/* 16bits. */
1277 	if (_16bits) {
1278 		sprintf(buf, "16bits=1\n");
1279 		fwrite(buf, strlen(buf), 1, f);
1280 	} else {
1281 		sprintf(buf, "16bits=0\n");
1282 		fwrite(buf, strlen(buf), 1, f);
1283 	}
1284 
1285 	/* Stereo. */
1286 	if (stereo) {
1287 		sprintf(buf, "stereo=1\n");
1288 		fwrite(buf, strlen(buf), 1, f);
1289 	} else {
1290 		sprintf(buf, "stereo=0\n");
1291 		fwrite(buf, strlen(buf), 1, f);
1292 	}
1293 
1294 	/* Stereo. */
1295 	if (reverse_stereo) {
1296 		sprintf(buf, "reverse_stereo=1\n");
1297 		fwrite(buf, strlen(buf), 1, f);
1298 	} else {
1299 		sprintf(buf, "reverse_stereo=0\n");
1300 		fwrite(buf, strlen(buf), 1, f);
1301 	}
1302 
1303 	/* Surround. */
1304 	if (surround) {
1305 		sprintf(buf, "surround=1\n");
1306 		fwrite(buf, strlen(buf), 1, f);
1307 	} else {
1308 		sprintf(buf, "surround=0\n");
1309 		fwrite(buf, strlen(buf), 1, f);
1310 	}
1311 
1312 	/* Interpolate. */
1313 	if (interpolate) {
1314 		sprintf(buf, "interpolate=1\n");
1315 		fwrite(buf, strlen(buf), 1, f);
1316 	} else {
1317 		sprintf(buf, "interpolate=0\n");
1318 		fwrite(buf, strlen(buf), 1, f);
1319 	}
1320 
1321 	/* HQ/LQ mixer. */
1322 	if (hq_mixer) {
1323 		sprintf(buf, "hq_mixer=1\n");
1324 		fwrite(buf, strlen(buf), 1, f);
1325 	} else {
1326 		sprintf(buf, "hq_mixer=0\n");
1327 		fwrite(buf, strlen(buf), 1, f);
1328 	}
1329 
1330 	/* Loop module. */
1331 	if (loop_module) {
1332 		sprintf(buf, "loop_module=1\n");
1333 		fwrite(buf, strlen(buf), 1, f);
1334 	} else {
1335 		sprintf(buf, "loop_module=0\n");
1336 		fwrite(buf, strlen(buf), 1, f);
1337 	}
1338 
1339 	/* Fadeout module. */
1340 	if (fade_module) {
1341 		sprintf(buf, "fade_module=1\n");
1342 		fwrite(buf, strlen(buf), 1, f);
1343 	} else {
1344 		sprintf(buf, "fade_module=0\n");
1345 		fwrite(buf, strlen(buf), 1, f);
1346 	}
1347 
1348 	/* Random mode. */
1349 	if (random_mode) {
1350 		sprintf(buf, "random_mode=1\n");
1351 		fwrite(buf, strlen(buf), 1, f);
1352 	} else {
1353 		sprintf(buf, "random_mode=0\n");
1354 		fwrite(buf, strlen(buf), 1, f);
1355 	}
1356 
1357 	/* Screen refresh delay. */
1358 	sprintf(buf, "delay=%d\n", DELAY);
1359 	fwrite(buf, strlen(buf), 1, f);
1360 
1361 	/* Windows coords. */
1362 	sprintf(buf, "AC_X=%d\n", AC_X);
1363 	fwrite(buf, strlen(buf), 1, f);
1364 	sprintf(buf, "AC_Y=%d\n", AC_Y);
1365 	fwrite(buf, strlen(buf), 1, f);
1366 
1367 	sprintf(buf, "VPOS_X=%d\n", VPOS_X);
1368 	fwrite(buf, strlen(buf), 1, f);
1369 	sprintf(buf, "VPOS_Y=%d\n", VPOS_Y);
1370 	fwrite(buf, strlen(buf), 1, f);
1371 
1372 	sprintf(buf, "VFREQ_X=%d\n", VFREQ_X);
1373 	fwrite(buf, strlen(buf), 1, f);
1374 	sprintf(buf, "VFREQ_Y=%d\n", VFREQ_Y);
1375 	fwrite(buf, strlen(buf), 1, f);
1376 
1377 	sprintf(buf, "OPT_X=%d\n", OPT_X);
1378 	fwrite(buf, strlen(buf), 1, f);
1379 	sprintf(buf, "OPT_Y=%d\n", OPT_Y);
1380 	fwrite(buf, strlen(buf), 1, f);
1381 
1382 	sprintf(buf, "EFT_X=%d\n", EFT_X);
1383 	fwrite(buf, strlen(buf), 1, f);
1384 	sprintf(buf, "EFT_Y=%d\n", EFT_Y);
1385 	fwrite(buf, strlen(buf), 1, f);
1386 
1387 	fclose(f);
1388 
1389 	sprintf(buf, "'%s' saved.", fixed_path);
1390 	message(buf, INFO_MSG);
1391 }
1392 
1393 /*** Enter options window. ***/
options(void)1394 static void options(void)
1395 {
1396 	int c, opt = 0;
1397 	WINDOW *tmpwin;
1398 
1399 	optwin = tmpwin = newwin(OPT_H, OPT_W, OPT_Y, OPT_X);
1400 	wtimeout(tmpwin, DELAY);
1401 	keypad(tmpwin, TRUE);
1402 	box(tmpwin, 0, 0);
1403 	optpan = new_panel(tmpwin);
1404 
1405 	wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL);
1406 	mvwprintw(tmpwin, 0, 2, "[         ]");
1407 	wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD);
1408 	mvwprintw(tmpwin, 0, 4, "Options");
1409 
1410 	/* Prepare display. */
1411 	for (c = 0; c < OPTIONS+4; c++) {
1412 		if (strlen(options_strings[c]) == 0) {
1413 			mvwprintw(tmpwin, c+2, 1, "");
1414 			continue;
1415 		}
1416 
1417 		if (c == 0)
1418 			wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE));
1419 		else
1420 			wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL));
1421 
1422 		print_opt(tmpwin, c);
1423 	}
1424 
1425 	wnoutrefresh(tmpwin);
1426 	doupdate();
1427 
1428 	/*** Loop. ***/
1429 	while ((c = wgetch(tmpwin)) != 'q') {
1430 		if (c == KEY_ESCAPE)
1431 			break;
1432 
1433 		if (c == 'm')
1434 			mp_move_panel(optpan);
1435 
1436 		switch (c) {
1437 			case ERR: case KEY_ESCAPE: break;
1438 
1439 			case KEY_ENTER:
1440 				/* HQ/LQ mixer. */
1441 				if (opt == HQMIXER_OPT) {
1442 					hq_mixer = 1-hq_mixer;
1443 					if (!hq_mixer) {
1444 						md_mode &= ~DMODE_HQMIXER;
1445 					} else
1446 						md_mode |= DMODE_HQMIXER;
1447 
1448 					refresh_driver_info();
1449 
1450 				/* 16 bit */
1451 				} else if (opt == _16BITS_OPT) {
1452 					_16bits = 1-_16bits;
1453 					if (!_16bits)
1454 						md_mode &= ~DMODE_16BITS;
1455 					else
1456 						md_mode |= DMODE_16BITS;
1457 
1458 					refresh_driver_info();
1459 
1460 				/* Stereo */
1461 				} else if (opt == STEREO_OPT) {
1462 					stereo = 1-stereo;
1463 					if (!stereo) {
1464 						md_mode &= ~DMODE_STEREO;
1465 						if (reverse_stereo) {
1466 							md_mode &=
1467 							    ~DMODE_REVERSE;
1468 							reverse_stereo =
1469 							    1-reverse_stereo;
1470 						}
1471 					} else
1472 						md_mode |= DMODE_STEREO;
1473 
1474 					refresh_driver_info();
1475 
1476 				/* Surround */
1477 				} else if (opt == SURROUND_OPT) {
1478 					surround = 1-surround;
1479 					if (!surround) {
1480 						md_mode &= ~DMODE_SURROUND;
1481 					} else
1482 						md_mode |= DMODE_SURROUND;
1483 
1484 					refresh_driver_info();
1485 
1486 				/* Mix freqency */
1487 				} else if (opt == MIXFREQ_OPT) {
1488 					get_mix_freq(tmpwin);
1489 
1490 				/* Loop module */
1491 				} else if (opt == LOOP_OPT) {
1492 					loop_module = 1-loop_module;
1493 					mod->loop = loop_module;
1494 
1495 				/* Fadeout */
1496 				} else if (opt == FADE_OPT) {
1497 					fade_module = 1-fade_module;
1498 					mod->fadeout = fade_module;
1499 
1500 				/* Reverse stereo */
1501 				} else if (opt == REVSTEREO_OPT) {
1502 					if (md_mode & DMODE_STEREO)
1503 						reverse_stereo =
1504 							1-reverse_stereo;
1505 					else
1506 						break;
1507 
1508 					if (!reverse_stereo) {
1509 						md_mode &= ~DMODE_REVERSE;
1510 					} else
1511 						md_mode |= DMODE_REVERSE;
1512 
1513 					refresh_driver_info();
1514 
1515 				/* Interpolate */
1516 				} else if (opt == INTERPOLATE_OPT) {
1517 					interpolate = 1-interpolate;
1518 					if (!interpolate) {
1519 						md_mode &= ~DMODE_INTERP;
1520 					} else
1521 						md_mode |= DMODE_INTERP;
1522 
1523 				/* Random */
1524 				} else if (opt == RANDOM_OPT) {
1525 					random_mode = 1-random_mode;
1526 
1527 				/* Delay */
1528 				} else if (opt == DELAY_OPT) {
1529 					get_delay(tmpwin);
1530 
1531 				/* Save file */
1532 				} else if (opt == SAVE_OPT) {
1533 					save_options_file();
1534 				}
1535 
1536 				wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE));
1537 				print_opt(tmpwin, opt);
1538 			break;
1539 
1540 			/* Select option. */
1541 			case KEY_UP:
1542 				wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL));
1543 				print_opt(tmpwin, opt);
1544 				if (opt == 6 || opt == 9 ||
1545 						opt == 13 || opt == 15)
1546 					opt -= 2;
1547 				else
1548 					if (opt > 0) opt--;
1549 				wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE));
1550 				print_opt(tmpwin, opt);
1551 			break;
1552 			case KEY_PPAGE:
1553 				wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL));
1554 				print_opt(tmpwin, opt);
1555 				opt = 0;
1556 				wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE));
1557 				print_opt(tmpwin, opt);
1558 			break;
1559 
1560 			case KEY_DOWN:
1561 				wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL));
1562 				print_opt(tmpwin, opt);
1563 				if (opt == 4 || opt == 7 ||
1564 						opt == 11 || opt == 13)
1565 					opt += 2;
1566 				else
1567 					if (opt < (OPTIONS+3)-1) opt++;
1568 				wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE));
1569 				print_opt(tmpwin, opt);
1570 			break;
1571 			case KEY_NPAGE:
1572 				wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL));
1573 				print_opt(tmpwin, opt);
1574 				opt = 15;
1575 				wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE));
1576 				print_opt(tmpwin, opt);
1577 			break;
1578 		}
1579 
1580 		if (mod && playing) {
1581 			refresh_info();
1582 			refresh_module_info();
1583 			MikMod_Update();
1584 		}
1585 
1586 		update_panels();
1587 		doupdate();
1588 	}
1589 
1590 	del_panel(optpan);
1591 	update_panels();
1592 	doupdate();
1593 }
1594 
1595 
1596 /***
1597  ***	Effects panel.
1598  ***/
effects(void)1599 static void effects(void)
1600 {
1601 	int i;
1602 	int c;
1603 	int pc;
1604 	int effect = 0;
1605 	float f1, f2;
1606 	char *effect_strings[EFFECTS] = {
1607 		"   Speed ",
1608 		"   Tempo ",
1609 		"     BPM ",
1610 		"  Reverb ",
1611 		"  Stereo ",
1612 		" Gen Vol ",
1613 		" Mod Vol ",
1614 		" Mix Vol ",
1615 		"    Bass ",
1616 		"  Treble "
1617 	};
1618 
1619 	eftwin = newwin(EFT_H, EFT_W, EFT_Y, EFT_X);
1620 	wtimeout(eftwin, DELAY);
1621 	keypad(eftwin, TRUE);
1622 	box(eftwin, 0, 0);
1623 	eftpan = new_panel(eftwin);
1624 	top_panel(eftpan);
1625 
1626 	wattrset(eftwin, (COLOR_PAIR(WHITE)|A_NORMAL));
1627 	mvwprintw(eftwin, 0, 2, "[         ]");
1628 	wattrset(eftwin, COLOR_PAIR(YELLOW)|A_BOLD);
1629 	mvwprintw(eftwin, 0, 4, "Effects");
1630 
1631 	/* Prepare display. */
1632 	for (c = 0; c < EFFECTS; c++) {
1633 		wattrset(eftwin, (COLOR_PAIR(WHITE)|A_NORMAL));
1634 		if (c == 0)
1635 			wattrset(eftwin, (COLOR_PAIR(WHITE)|A_REVERSE));
1636 		mvwprintw(eftwin, c+2, 1, effect_strings[c]);
1637 		switch (c) {
1638 			case 0:		/* speed */
1639 				f1 = mod->sngspd;
1640 				f2 = SPEED_LIMIT;
1641 				pc = 100*(f1/f2);
1642 				pc = 100-pc;
1643 				draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style);
1644 			break;
1645 			case 1:		/* tempo */
1646 				f1 = mod->inittempo;
1647 				f2 = TEMPO_LIMIT;
1648 				pc = 100*(f1/f2);
1649 				draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style);
1650 			break;
1651 			case 2:		/* BPM */
1652 				f1 = mod->bpm;
1653 				f2 = BPM_LIMIT;
1654 				pc = 100*(f1/f2);
1655 				draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style);
1656 			break;
1657 			case 3:		/* reverb */
1658 				f1 = md_reverb;
1659 				f2 = REVERB_LIMIT;
1660 				pc = 100*(f1/f2);
1661 				draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style);
1662 			break;
1663 			case 4:		/* stereo */
1664 				f1 = md_pansep;
1665 				f2 = STEREO_LIMIT;
1666 				pc = 100*(f1/f2);
1667 				draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style);
1668 			break;
1669 			case 5:		/* general volume */
1670 				f1 = md_volume;
1671 				f2 = GENVOL_LIMIT;
1672 				pc = 100*(f1/f2);
1673 				draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style);
1674 			break;
1675 			case 6:		/* module volume */
1676 				f1 = mod->volume;
1677 				f2 = MODVOL_LIMIT;
1678 				pc = 100*(f1/f2);
1679 				draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style);
1680 			break;
1681 			case 7:		/* mixer volume */
1682 				f1 = mixvol;
1683 				f2 = MIXVOL_LIMIT;
1684 				pc = 100*(f1/f2);
1685 				draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style);
1686 			break;
1687 			case 8:		/* bass level */
1688 				f1 = bass;
1689 				f2 = BASS_LIMIT;
1690 				pc = 100*(f1/f2);
1691 				draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style);
1692 			break;
1693 			case 9:		/* treble level */
1694 				f1 = treble;
1695 				f2 = TREBLE_LIMIT;
1696 				pc = 100*(f1/f2);
1697 				draw_gauge(eftwin, 12, c+2, pc, 1, gauge_style);
1698 			break;
1699 		}
1700 	}
1701 
1702 	/*** Loop ***/
1703 	while ((c = wgetch(eftwin)) != 'q') {
1704 		if (c == KEY_ESCAPE)
1705 			break;
1706 
1707 		if (c == 'm')
1708 			mp_move_panel(eftpan);
1709 
1710 		switch (c) {
1711 			case ERR: break;
1712 
1713 			/* UP */
1714 			case KEY_UP:
1715 				wattrset(eftwin, (COLOR_PAIR(WHITE)|A_NORMAL));
1716 				mvwprintw(eftwin, effect+2, 1,
1717 						effect_strings[effect]);
1718 				if (effect > 0) effect--;
1719 				wattrset(eftwin, (COLOR_PAIR(WHITE)|A_REVERSE));
1720 				mvwprintw(eftwin, effect+2, 1,
1721 						effect_strings[effect]);
1722 			break;
1723 			case KEY_PPAGE:
1724 				wattrset(eftwin, (COLOR_PAIR(WHITE)|A_NORMAL));
1725 				mvwprintw(eftwin, effect+2, 1,
1726 						effect_strings[effect]);
1727 				effect = 0;
1728 				wattrset(eftwin, (COLOR_PAIR(WHITE)|A_REVERSE));
1729 				mvwprintw(eftwin, effect+2, 1,
1730 						effect_strings[effect]);
1731 			break;
1732 
1733 			/* DOWN */
1734 			case KEY_DOWN:
1735 				wattrset(eftwin, (COLOR_PAIR(WHITE)|A_NORMAL));
1736 				mvwprintw(eftwin, effect+2, 1,
1737 						effect_strings[effect]);
1738 				if (effect < EFFECTS-1) effect++;
1739 				wattrset(eftwin, (COLOR_PAIR(WHITE)|A_REVERSE));
1740 				mvwprintw(eftwin, effect+2, 1,
1741 						effect_strings[effect]);
1742 			break;
1743 			case KEY_NPAGE:
1744 				wattrset(eftwin, (COLOR_PAIR(WHITE)|A_NORMAL));
1745 				mvwprintw(eftwin, effect+2, 1,
1746 						effect_strings[effect]);
1747 				effect = EFFECTS-1;
1748 				wattrset(eftwin, (COLOR_PAIR(WHITE)|A_REVERSE));
1749 				mvwprintw(eftwin, effect+2, 1,
1750 						effect_strings[effect]);
1751 			break;
1752 
1753 			case KEY_LEFT:
1754 				switch (effect) {
1755 					case 0:		/* speed */
1756 						if (mod->sngspd < SPEED_LIMIT)
1757 							mod->sngspd++;
1758 						f1 = mod->sngspd;
1759 						f2 = SPEED_LIMIT;
1760 						pc = 100*(f1/f2);
1761 						pc = 100-pc;
1762 						draw_gauge(eftwin, 12, effect+2,
1763 							pc, 1, gauge_style);
1764 					break;
1765 					case 1:		/* tempo */
1766 						if (mod->inittempo > 0)
1767 							mod->inittempo--;
1768 						f1 = mod->inittempo;
1769 						f2 = TEMPO_LIMIT;
1770 						pc = 100*(f1/f2);
1771 						draw_gauge(eftwin, 12, effect+2,
1772 							pc, 1, gauge_style);
1773 					break;
1774 					case 2:		/* BPM */
1775 						if (mod->bpm > 1)
1776 							mod->bpm--;
1777 						f1 = mod->bpm;
1778 						f2 = BPM_LIMIT;
1779 						pc = 100*(f1/f2);
1780 						draw_gauge(eftwin, 12, effect+2,
1781 							pc, 1, gauge_style);
1782 					break;
1783 					case 3:		/* reverb */
1784 						if (md_reverb > 0)
1785 							md_reverb--;
1786 						f1 = md_reverb;
1787 						f2 = REVERB_LIMIT;
1788 						pc = 100*(f1/f2);
1789 						draw_gauge(eftwin, 12, effect+2,
1790 							pc, 1, gauge_style);
1791 					break;
1792 					case 4:		/* stereo */
1793 						if (md_pansep > 0)
1794 							md_pansep--;
1795 						f1 = md_pansep;
1796 						f2 = STEREO_LIMIT;
1797 						pc = 100*(f1/f2);
1798 						draw_gauge(eftwin, 12, effect+2,
1799 							pc, 1, gauge_style);
1800 					break;
1801 					case 5:		/* general volume */
1802 						if (md_volume > 0)
1803 							md_volume--;
1804 						f1 = md_volume;
1805 						f2 = GENVOL_LIMIT;
1806 						pc = 100*(f1/f2);
1807 						draw_gauge(eftwin, 12, effect+2,
1808 							pc, 1, gauge_style);
1809 					break;
1810 					case 6:		/* module volume */
1811 						if (mod->volume > 0)
1812 							mod->volume--;
1813 						f1 = mod->volume;
1814 						f2 = MODVOL_LIMIT;
1815 						pc = 100*(f1/f2);
1816 						draw_gauge(eftwin, 12, effect+2,
1817 							pc, 1, gauge_style);
1818 					break;
1819 					case 7:		/* mixer volume */
1820 						if (mixvol > 771)
1821 							mixvol -= 771;
1822 						else
1823 							mixvol = 0;
1824 						f1 = mixvol;
1825 						f2 = MIXVOL_LIMIT;
1826 						pc = 100*(f1/f2);
1827 						draw_gauge(eftwin, 12, effect+2,
1828 							pc, 1, gauge_style);
1829 						ioctl(
1830 						mixerfd,
1831 						MIXER_WRITE(SOUND_MIXER_VOLUME),
1832 						&mixvol
1833 						);
1834 					break;
1835 					case 8:		/* mixer bass */
1836 						if (bass > 0)
1837 							bass--;
1838 						f1 = bass;
1839 						f2 = BASS_LIMIT;
1840 						pc = 100*(f1/f2);
1841 						draw_gauge(eftwin, 12, effect+2,
1842 							pc, 1, gauge_style);
1843 						ioctl(
1844 						mixerfd,
1845 						MIXER_WRITE(SOUND_MIXER_BASS),
1846 						&bass
1847 						);
1848 					break;
1849 					case 9:		/* mixer treble */
1850 						if (treble > 0)
1851 							treble--;
1852 						f1 = treble;
1853 						f2 = TREBLE_LIMIT;
1854 						pc = 100*(f1/f2);
1855 						draw_gauge(eftwin, 12, effect+2,
1856 							pc, 1, gauge_style);
1857 						ioctl(
1858 						mixerfd,
1859 						MIXER_WRITE(SOUND_MIXER_TREBLE),
1860 						&treble
1861 						);
1862 					break;
1863 
1864 				}
1865 			break;
1866 
1867 			case KEY_RIGHT:
1868 				switch (effect) {
1869 					case 0:		/* speed */
1870 						if (mod->sngspd > 0)
1871 							mod->sngspd--;
1872 						f1 = mod->sngspd;
1873 						f2 = SPEED_LIMIT;
1874 						pc = 100*(f1/f2);
1875 						pc = 100-pc;
1876 						draw_gauge(eftwin, 12, effect+2,
1877 							pc, 1, gauge_style);
1878 					break;
1879 					case 1:		/* tempo */
1880 						if (mod->inittempo<TEMPO_LIMIT)
1881 							mod->inittempo++;
1882 						f1 = mod->inittempo;
1883 						f2 = TEMPO_LIMIT;
1884 						pc = 100*(f1/f2);
1885 						draw_gauge(eftwin, 12, effect+2,
1886 							pc, 1, gauge_style);
1887 					break;
1888 					case 2:		/* BPM */
1889 						if (mod->bpm < BPM_LIMIT)
1890 							mod->bpm++;
1891 						f1 = mod->bpm;
1892 						f2 = BPM_LIMIT;
1893 						pc = 100*(f1/f2);
1894 						draw_gauge(eftwin, 12, effect+2,
1895 							pc, 1, gauge_style);
1896 					break;
1897 					case 3:		/* reverb */
1898 						if (md_reverb < REVERB_LIMIT)
1899 							md_reverb++;
1900 						f1 = md_reverb;
1901 						f2 = REVERB_LIMIT;
1902 						pc = 100*(f1/f2);
1903 						draw_gauge(eftwin, 12, effect+2,
1904 							pc, 1, gauge_style);
1905 					break;
1906 					case 4:		/* stereo */
1907 						if (md_pansep < STEREO_LIMIT)
1908 							md_pansep++;
1909 						f1 = md_pansep;
1910 						f2 = STEREO_LIMIT;
1911 						pc = 100*(f1/f2);
1912 						draw_gauge(eftwin, 12, effect+2,
1913 							pc, 1, gauge_style);
1914 					break;
1915 					case 5:		/* general volume */
1916 						if (md_volume < GENVOL_LIMIT)
1917 							md_volume++;
1918 						f1 = md_volume;
1919 						f2 = GENVOL_LIMIT;
1920 						pc = 100*(f1/f2);
1921 						draw_gauge(eftwin, 12, effect+2,
1922 							pc, 1, gauge_style);
1923 					break;
1924 					case 6:		/* module volume */
1925 						if (mod->volume < MODVOL_LIMIT)
1926 							mod->volume++;
1927 						f1 = mod->volume;
1928 						f2 = MODVOL_LIMIT;
1929 						pc = 100*(f1/f2);
1930 						draw_gauge(eftwin, 12, effect+2,
1931 							pc, 1, gauge_style);
1932 					break;
1933 					case 7:		/* mixer volume */
1934 						if (mixvol < MIXVOL_LIMIT)
1935 							mixvol += 771;
1936 						f1 = mixvol;
1937 						f2 = MIXVOL_LIMIT;
1938 						pc = 100*(f1/f2);
1939 						draw_gauge(eftwin, 12, effect+2,
1940 							pc, 1, gauge_style);
1941 						ioctl(
1942 						mixerfd,
1943 						MIXER_WRITE(SOUND_MIXER_VOLUME),
1944 						&mixvol
1945 						);
1946 					break;
1947 					case 8:		/* mixer bass */
1948 						if (bass < BASS_LIMIT)
1949 							bass++;
1950 						f1 = bass;
1951 						f2 = BASS_LIMIT;
1952 						pc = 100*(f1/f2);
1953 						draw_gauge(eftwin, 12, effect+2,
1954 							pc, 1, gauge_style);
1955 						i = (bass * 16);
1956 						ioctl(
1957 						mixerfd,
1958 						MIXER_WRITE(SOUND_MIXER_BASS),
1959 						&i
1960 						);
1961 					break;
1962 					case 9:		/* mixer treble */
1963 						if (treble < TREBLE_LIMIT)
1964 							treble++;
1965 						f1 = treble;
1966 						f2 = TREBLE_LIMIT;
1967 						pc = 100*(f1/f2);
1968 						draw_gauge(eftwin, 12, effect+2,
1969 							pc, 1, gauge_style);
1970 						ioctl(
1971 						mixerfd,
1972 						MIXER_WRITE(SOUND_MIXER_TREBLE),
1973 						&treble
1974 						);
1975 					break;
1976 				}
1977 			break;
1978 		}
1979 
1980 		if (mod && playing) {
1981 			refresh_info();
1982 			refresh_module_info();
1983 			MikMod_Update();
1984 		}
1985 
1986 		update_panels();
1987 		doupdate();
1988 	}
1989 
1990 	del_panel(eftpan);
1991 	touchwin(dspwin);
1992 	doupdate();
1993 }
1994 
1995 /*****************************************************************************/
1996 
1997 /***
1998  ***	Instruments panel.
1999  ***/
2000 int insnum;				/* instrument number */
2001 INSTRUMENT *curins;			/* pointer to current instrument */
2002 
2003 int ins_val;				/* used for buttons */
2004 
2005 /*** Show instrument. ***/
show_instrument(WINDOW * win,INSTRUMENT * ins,int num)2006 static void show_instrument(WINDOW *win, INSTRUMENT *ins, int num)
2007 {
2008 	if (mod->instruments == NULL) {
2009 		message("No instruments in this module.", ERROR_MSG);
2010 		return;
2011 	}
2012 
2013 	wattrset(win, A_BOLD);
2014 	mvwprintw(win, 2, 1, "     #: ");
2015 	wattrset(win, A_NORMAL);
2016 	wprintw(win, "%-4d/%4d", num, mod->numins);
2017 
2018 	wattrset(win, A_BOLD);
2019 	mvwprintw(win, 3, 1, "  Name: ");
2020 	wattrset(win, A_NORMAL);
2021 	wprintw(win, "%-40s", ins->insname);
2022 
2023 	wattrset(win, A_BOLD);
2024 	mvwprintw(win, 4, 1, " Flags: ");
2025 	wattrset(win, A_NORMAL);
2026 	wprintw(win, "0x%04x", ins->flags);
2027 
2028 	wattrset(win, A_BOLD);
2029 	mvwprintw(win, 5, 1, "   Pan: ");
2030 	wattrset(win, A_NORMAL);
2031 	wprintw(win, "%-3d", ins->panning);
2032 
2033 	wattrset(win, A_BOLD);
2034 	mvwprintw(win, 6, 1, "   Vol: ");
2035 	wattrset(win, A_NORMAL);
2036 	wprintw(win, "%-4d", ins->globvol);
2037 }
2038 
2039 /*** Instruments window buttons. ***/
ins_buttons(WINDOW * win)2040 static int ins_buttons(WINDOW *win)
2041 {
2042 	int i, c;
2043 	int in_loop = 1;
2044 	char *ins_btns[3] = {
2045 		"[ Next ]",
2046 		"[ Prev ]",
2047 //		"[ Play ]",
2048 //		"[ Stop ]",
2049 		"[ Quit ]"
2050 	};
2051 
2052 	ins_val = 0;
2053 
2054 	wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL);
2055 	for (i = 0; i < 3; i++) {
2056 		if (ins_val == i)
2057 			wattrset(win, A_REVERSE);
2058 		else
2059 			wattrset(win, A_NORMAL);
2060 
2061 		mvwprintw(win, INS_H-3, 5+(i*18), "%s", ins_btns[i]);
2062 	}
2063 
2064 	while (in_loop) {
2065 		switch ((c = wgetch(win))) {
2066 			case KEY_ESCAPE:
2067 			case 'q':
2068 				ins_val = 2;
2069 				in_loop = 0;
2070 			break;
2071 
2072 			case KEY_RIGHT:
2073 				wattrset(win, A_NORMAL);
2074 				mvwprintw(win, INS_H-3, 5+(ins_val*18),
2075 					"%s", ins_btns[ins_val]);
2076 				if (ins_val < 2) ins_val++;
2077 				wattrset(win, A_REVERSE);
2078 				mvwprintw(win, INS_H-3, 5+(ins_val*18),
2079 					"%s", ins_btns[ins_val]);
2080 			break;
2081 			case KEY_LEFT:
2082 				wattrset(win, A_NORMAL);
2083 				mvwprintw(win, INS_H-3, 5+(ins_val*18),
2084 					"%s", ins_btns[ins_val]);
2085 				if (ins_val > 0) ins_val--;
2086 				wattrset(win, A_REVERSE);
2087 				mvwprintw(win, INS_H-3, 5+(ins_val*18),
2088 					"%s", ins_btns[ins_val]);
2089 			break;
2090 			case KEY_ENTER:
2091 				/* Next. */
2092 				if (ins_val == 0) {
2093 					if (insnum < mod->numins-1) {
2094 						insnum++;
2095 						curins++;
2096 						show_instrument(win,
2097 							curins, insnum+1);
2098 					}
2099 
2100 				/* Previous. */
2101 				} else if (ins_val == 1) {
2102 					if (insnum > 0) {
2103 						insnum--;
2104 						curins--;
2105 						show_instrument(win,
2106 							curins, insnum+1);
2107 					}
2108 
2109 				/* Play. */
2110 				/*} else if (ins_val == 2) {
2111 					int i = Sample_Play(cursmp, 1, 0);
2112 					fprintf(stderr, "%d\n", i);*/
2113 
2114 				/* Stop. */
2115 				/*} else if (ins_val == 3) {*/
2116 
2117 				/* Quit. */
2118 				} else if (ins_val == 2) {
2119 					in_loop = 0;
2120 					continue;
2121 				}
2122 			break;
2123 		}
2124 
2125 
2126 		if (mod && playing) {
2127 			refresh_module_info();
2128 			refresh_info();
2129 			update_panels();
2130 			doupdate();
2131 			MikMod_Update();
2132 		}
2133 	}
2134 
2135 	return ins_val;
2136 }
2137 
2138 /*** Open instruments window. ***/
show_instruments(void)2139 void show_instruments(void)
2140 {
2141 	int i;
2142 	WINDOW *tmpwin;
2143 
2144 	inswin = tmpwin = newwin(INS_H, INS_W, INS_Y, INS_X);
2145 	wtimeout(tmpwin, DELAY);
2146 	keypad(tmpwin, TRUE);
2147 	box(tmpwin, 0, 0);
2148 	inspan = new_panel(inswin);
2149 
2150 	wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL);
2151 	mvwprintw(tmpwin, 0, 2, "[             ]");
2152 	wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD);
2153 	mvwprintw(tmpwin, 0, 4, "Instruments");
2154 
2155 	wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL);
2156 	for (i = 1; i < INS_W-1; i++)
2157 		mvwaddch(tmpwin, INS_H-5, i, ACS_HLINE);
2158 	mvwaddch(tmpwin, INS_H-5, 0, ACS_LTEE);
2159 	mvwaddch(tmpwin, INS_H-5, INS_W-1, ACS_RTEE);
2160 
2161 	insnum = 0;
2162 	curins = mod->instruments;
2163 	show_instrument(tmpwin, mod->instruments, insnum+1);
2164 	ins_buttons(tmpwin);
2165 
2166 	del_panel(inspan);
2167 	touchwin(dspwin);
2168 	update_panels();
2169 	doupdate();
2170 
2171 }
2172 
2173 /*****************************************************************************/
2174 
2175 /***
2176  ***	Sample window.
2177  ***/
2178 int smpnum;			/* sample number */
2179 SAMPLE *cursmp;			/* pointer to current sample */
2180 
2181 int smp_val;			/* used for buttons */
2182 
2183 /*** Show sample. ***/
show_sample(WINDOW * win,SAMPLE * smp,int num)2184 static void show_sample(WINDOW *win, SAMPLE *smp, int num)
2185 {
2186 	wattrset(win, A_BOLD);
2187 	mvwprintw(win, 2, 1, "     #: ");
2188 	wattrset(win, A_NORMAL);
2189 	wprintw(win, "%-4d/%4d", num, mod->numsmp);
2190 
2191 	wattrset(win, A_BOLD);
2192 	mvwprintw(win, 3, 1, "  Name: ");
2193 	wattrset(win, A_NORMAL);
2194 	wprintw(win, "%-40s", smp->samplename);
2195 
2196 	wattrset(win, A_BOLD);
2197 	mvwprintw(win, 4, 1,
2198 		"                                                    ");
2199 	mvwprintw(win, 4, 1, " Flags: ");
2200 	wattrset(win, A_NORMAL);
2201 	if (smp->flags & SF_16BITS)
2202 		wprintw(win, "16bit ");
2203 	if (smp->flags & SF_STEREO)
2204 		wprintw(win, "stereo ");
2205 	if (smp->flags & SF_SIGNED)
2206 		wprintw(win, "signed ");
2207 	if (smp->flags & SF_ITPACKED)
2208 		wprintw(win, "IT_packed ");
2209 	if (smp->flags & SF_BIDI)
2210 		wprintw(win, "bidir ");
2211 	if (smp->flags & SF_LOOP)
2212 		wprintw(win, "loop ");
2213 	if (smp->flags & SF_REVERSE)
2214 		wprintw(win, "reverse ");
2215 	if (smp->flags & SF_OWNPAN)
2216 		wprintw(win, "own_pan ");
2217 	wprintw(win, "(0x%04x)", smp->flags);
2218 
2219 	wattrset(win, A_BOLD);
2220 	mvwprintw(win, 5, 1, "Length: ");
2221 	wattrset(win, A_NORMAL);
2222 	wprintw(win, "%-8d", smp->length);
2223 
2224 	wattrset(win, A_BOLD);
2225 	mvwprintw(win, 6, 1, "   Pan: ");
2226 	wattrset(win, A_NORMAL);
2227 	wprintw(win, "%-3d", smp->panning);
2228 
2229 	wattrset(win, A_BOLD);
2230 	mvwprintw(win, 7, 1, " Speed: ");
2231 	wattrset(win, A_NORMAL);
2232 	wprintw(win, "%-6d", smp->speed);
2233 
2234 	wattrset(win, A_BOLD);
2235 	mvwprintw(win, 8, 1, "   Vol: ");
2236 	wattrset(win, A_NORMAL);
2237 	wprintw(win, "%-4d (glob. %-4d)",
2238 			smp->volume,
2239 			smp->globvol);
2240 
2241 }
2242 
2243 /*** Samples window buttons. ***/
smp_buttons(WINDOW * win)2244 static int smp_buttons(WINDOW *win)
2245 {
2246 	int i, c;
2247 	int in_loop = 1;
2248 	char *smp_btns[3] = {
2249 		"[ Next ]",
2250 		"[ Prev ]",
2251 //		"[ Play ]",
2252 //		"[ Stop ]",
2253 		"[ Quit ]"
2254 	};
2255 
2256 	smp_val = 0;
2257 
2258 	wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL);
2259 	for (i = 0; i < 3; i++) {
2260 		if (smp_val == i)
2261 			wattrset(win, A_REVERSE);
2262 		else
2263 			wattrset(win, A_NORMAL);
2264 
2265 		mvwprintw(win, SMP_H-3, 5+(i*18), "%s", smp_btns[i]);
2266 	}
2267 
2268 	while (in_loop) {
2269 		switch ((c = wgetch(win))) {
2270 			case KEY_ESCAPE:
2271 			case 'q':
2272 				smp_val = 2;
2273 				in_loop = 0;
2274 			break;
2275 
2276 			case 'm':
2277 				mp_move_panel(smppan);
2278 			break;
2279 
2280 			case KEY_RIGHT:
2281 				wattrset(win, A_NORMAL);
2282 				mvwprintw(win, SMP_H-3, 5+(smp_val*18),
2283 					"%s", smp_btns[smp_val]);
2284 				if (smp_val < 2) smp_val++;
2285 				wattrset(win, A_REVERSE);
2286 				mvwprintw(win, SMP_H-3, 5+(smp_val*18),
2287 					"%s", smp_btns[smp_val]);
2288 			break;
2289 			case KEY_LEFT:
2290 				wattrset(win, A_NORMAL);
2291 				mvwprintw(win, SMP_H-3, 5+(smp_val*18),
2292 					"%s", smp_btns[smp_val]);
2293 				if (smp_val > 0) smp_val--;
2294 				wattrset(win, A_REVERSE);
2295 				mvwprintw(win, SMP_H-3, 5+(smp_val*18),
2296 					"%s", smp_btns[smp_val]);
2297 			break;
2298 			case KEY_ENTER:
2299 				/* Next. */
2300 				if (smp_val == 0) {
2301 					if (smpnum < mod->numsmp-1) {
2302 						smpnum++;
2303 						cursmp++;
2304 						show_sample(win,
2305 							cursmp, smpnum+1);
2306 					}
2307 
2308 				/* Previous. */
2309 				} else if (smp_val == 1) {
2310 					if (smpnum > 0) {
2311 						smpnum--;
2312 						cursmp--;
2313 						show_sample(win,
2314 							cursmp, smpnum+1);
2315 					}
2316 
2317 				/* Play. */
2318 				/*} else if (smp_val == 2) {
2319 					int i = Sample_Play(cursmp, 1, 0);
2320 					fprintf(stderr, "%d\n", i);*/
2321 
2322 				/* Stop. */
2323 				/*} else if (smp_val == 3) {*/
2324 
2325 				/* Quit. */
2326 				} else if (smp_val == 2) {
2327 					in_loop = 0;
2328 					continue;
2329 				}
2330 			break;
2331 		}
2332 
2333 
2334 		if (mod && playing) {
2335 			refresh_module_info();
2336 			refresh_info();
2337 			update_panels();
2338 			doupdate();
2339 			MikMod_Update();
2340 		}
2341 	}
2342 
2343 	return smp_val;
2344 }
2345 
2346 /*** Open samples window. ***/
show_samples(void)2347 void show_samples(void)
2348 {
2349 	int i;
2350 	WINDOW *tmpwin;
2351 
2352 	smpwin = tmpwin = newwin(SMP_H, SMP_W, SMP_Y, SMP_X);
2353 	wtimeout(tmpwin, DELAY);
2354 	keypad(tmpwin, TRUE);
2355 	box(tmpwin, 0, 0);
2356 	smppan = new_panel(tmpwin);
2357 	wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL);
2358 	mvwprintw(tmpwin, 0, 2, "[         ]");
2359 	wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD);
2360 	mvwprintw(tmpwin, 0, 4, "Samples");
2361 
2362 	wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL);
2363 	for (i = 1; i < SMP_W-1; i++)
2364 		mvwaddch(tmpwin, SMP_H-5, i, ACS_HLINE);
2365 	mvwaddch(tmpwin, SMP_H-5, 0, ACS_LTEE);
2366 	mvwaddch(tmpwin, SMP_H-5, SMP_W-1, ACS_RTEE);
2367 
2368 	smpnum = 0;
2369 	cursmp = mod->samples;
2370 	show_sample(tmpwin, mod->samples, smpnum+1);
2371 	smp_buttons(tmpwin);
2372 
2373 	del_panel(smppan);
2374 	delwin(smpwin);
2375 	touchwin(dspwin);
2376 	update_panels();
2377 	doupdate();
2378 
2379 }
2380 
2381 
2382 
2383 /*****************************************************************************/
2384 
2385 /***
2386  ***	Various functions.
2387  ***/
2388 
2389 /*** Get a string from anywhere in a window. ***/
2390 char getstrtab = 0;
2391 
get_string(WINDOW * win,int ys,int xs,char * prompt,char * str)2392 static void get_string(WINDOW *win, int ys, int xs, char *prompt, char *str)
2393 {
2394 	int slen = strlen(prompt) + strlen(str);
2395 	int c, i, j, k;
2396 	int piece;
2397 	int in_loop = 1;
2398 	int x = xs + slen;
2399 	int maxlen = 57 - strlen(prompt);
2400 	char strbuf[NAME_MAX+1], *bufp = strbuf;
2401 
2402 	k = i = strlen(str);
2403 	mvwprintw(win, ys, xs, "%s%s", prompt, str); curs_set(TRUE);
2404 
2405 	wnoutrefresh(win);
2406 	doupdate();
2407 
2408 	/*** Loop ***/
2409 	getstrtab = 0;
2410 	while (in_loop) {
2411 		switch ((c = wgetch(win))) {
2412 			case ERR: break;
2413 
2414 			case KEY_ENTER:
2415 				in_loop = 0;
2416 				continue;
2417 			break;
2418 
2419 			case KEY_DELETE:
2420 			case KEY_BACKSPACE:
2421 				if (x == xs+strlen(prompt)) {
2422 					beep();
2423 					break;
2424 				}
2425 
2426 				if (i == 1 || (k % maxlen-1)) {
2427 					str[--i] = 0;
2428 					mvwaddch(win, ys, x--, '\b');
2429 					waddch(win, ' ');
2430 					waddch(win, '\b');
2431 					k--;
2432 
2433 				} else {
2434 					piece = (i / maxlen);
2435 					bufp = strbuf;
2436 					sprintf(bufp, str);
2437 					bufp += (piece * maxlen);
2438 					bufp[maxlen] = '\0';
2439 
2440 					if (piece > 0)
2441 						bufp[0] = '~';
2442 					k = strlen(bufp);
2443 
2444 					j = strlen(prompt);
2445 					for (; j < FS_W-2; j++)
2446 						mvwaddch(win, ys, j, ' ');
2447 					x = xs + (strlen(prompt)
2448 						+ strlen(bufp));
2449 					mvwprintw(win, ys, xs,
2450 						"%s%s", prompt, bufp);
2451 				}
2452 			break;
2453 
2454 			/*
2455 			case KEY_LEFT:
2456 				if (x == xs+strlen(prompt)+1) {
2457 					beep();
2458 					break;
2459 				}
2460 				wmove(win, ys, --x);
2461 				i--;
2462 			break;
2463 
2464 			case KEY_RIGHT:
2465 				if (x == 48) {
2466 					beep();
2467 					break;
2468 				}
2469 				wmove(win, ys, --x);
2470 				i++;
2471 			break;
2472 			*/
2473 
2474 			case KEY_ESCAPE:
2475 				in_loop = 0;
2476 				continue;
2477 			break;
2478 
2479 			case KEY_TAB:
2480 				getstrtab = 1;
2481 				in_loop = 0;
2482 				continue;
2483 			break;
2484 
2485 			/* Ignored characters. */
2486 			case KEY_UP:
2487 			case KEY_DOWN:
2488 			case KEY_LEFT:
2489 			case KEY_RIGHT:
2490 			break;
2491 
2492 			/* Add character. */
2493 			default:
2494 				if (i >= NAME_MAX) {
2495 					beep();
2496 					break;
2497 				}
2498 
2499 				if (i == 0 || (k % maxlen)) {
2500 					str[i++] = (char ) c;
2501                 	                mvwaddch(win, ys, x++, c);
2502 					k++;
2503 
2504 				} else {
2505 					bufp = strbuf;
2506 					sprintf(bufp, str);
2507 					bufp += i-4;
2508 					bufp[0] = '~';
2509 					bufp[5] = '\0';
2510 					k = 5;
2511 
2512 					j = strlen(prompt);
2513 					for (; j < FS_W-2; j++)
2514 						mvwaddch(win, ys, j, ' ');
2515 					x = xs + (strlen(prompt)
2516 						+ strlen(bufp));
2517 					mvwprintw(win, ys, xs,
2518 						"%s%s", prompt, bufp);
2519 
2520 					str[i++] = (char ) c;
2521                 	                mvwaddch(win, ys, x++, c);
2522 				}
2523 			break;
2524 		}
2525 
2526 		if (mod && playing) {
2527 			refresh_info();
2528 			refresh_module_info();
2529 			update_panels();
2530 			doupdate();
2531 			MikMod_Update();
2532 		}
2533 
2534 	}
2535 	str[i] = '\0';
2536 
2537 	curs_set(FALSE);
2538 	touchwin(dspwin);
2539 	doupdate();
2540 }
2541 
2542 /*** Move panel. ***/
mp_move_panel(PANEL * pan)2543 static void mp_move_panel(PANEL *pan)
2544 {
2545 	int c;
2546 	int x = pan->win->_begx, y = pan->win->_begy;
2547 
2548 	while ((c = wgetch(pan->win)) != KEY_ENTER ||
2549 			c == KEY_ESCAPE) {
2550 		switch (c) {
2551 			case KEY_UP:
2552 				if (y)
2553 					move_panel(pan, --y, x);
2554 			break;
2555 			case KEY_DOWN:
2556 				if (y < (LINES-(pan->win->_maxy+1)))
2557 					move_panel(pan, ++y, x);
2558 			break;
2559 			case KEY_LEFT:
2560 				if (x)
2561 					move_panel(pan, y, --x);
2562 			break;
2563 			case KEY_RIGHT:
2564 				if (x < (COLS-(pan->win->_maxx+1)))
2565 					move_panel(pan, y, ++x);
2566 			break;
2567 		}
2568 
2569 		if (mod && playing) {
2570 			refresh_info();
2571 			refresh_module_info();
2572 			MikMod_Update();
2573 		}
2574 
2575 		update_panels();
2576 		doupdate();
2577 	}
2578 
2579 	if (pan->win == acwin) {
2580 		AC_X = acwin->_begx;
2581 		AC_Y = acwin->_begy;
2582 
2583 	} else if (pan->win == helpwin) {
2584 		HELP_X = helpwin->_begx;
2585 		HELP_Y = helpwin->_begy;
2586 
2587 	} else if (pan->win == vfreqwin) {
2588 		VFREQ_X = vfreqwin->_begx;
2589 		VFREQ_Y = vfreqwin->_begy;
2590 
2591 	} else if (pan->win == vposwin) {
2592 		VPOS_X = vposwin->_begx;
2593 		VPOS_Y = vposwin->_begy;
2594 
2595 	} else if (pan->win == eftwin) {
2596 		EFT_X = eftwin->_begx;
2597 		EFT_Y = eftwin->_begy;
2598 
2599 	} else if (pan->win == optwin) {
2600 		OPT_X = optwin->_begx;
2601 		OPT_Y = optwin->_begy;
2602 
2603 	} else if (pan->win == smpwin) {
2604 		SMP_X = smpwin->_begx;
2605 		SMP_Y = smpwin->_begy;
2606 	}
2607 }
2608 
2609 /*****************************************************************************/
2610 
2611 /***
2612  ***			File selector.
2613  ***/
2614 
2615 /*** Variables. ***/
2616 int fs_val;
2617 int current, nument;
2618 int fspage = 0, lastpage = 0;
2619 
2620 struct dirent *drent[MAX_FILES];
2621 char dname[MAX_FILES][NAME_MAX+1];
2622 char dnamed[MAX_FILES][NAME_MAX+1];
2623 char dnamef[MAX_FILES][NAME_MAX+1];
2624 DIR *dentry = NULL;
2625 
2626 char modpath[NAME_MAX+1];
2627 char dirname[NAME_MAX+1];
2628 char filename[NAME_MAX+1];
2629 char lastdir[NAME_MAX+1];
2630 
2631 /*** List directory content in window win (without reading). ***/
list_dir(WINDOW * win)2632 static void list_dir(WINDOW *win)
2633 {
2634 	int y;
2635 	int cnt = fspage*(FS_H-10);
2636 	struct stat sbuf;
2637 	char strbuf[NAME_MAX+1];
2638 
2639 	for (y = 5; y < FS_H-5; y++, cnt++) {
2640 		if ((drent[cnt]) == NULL) break;
2641 
2642 		strncpy(strbuf, dname[cnt], 48);
2643 		strbuf[48] = '\0';
2644 
2645 		stat(dname[cnt], &sbuf);
2646 		file_size =
2647 			(((float)(sbuf.st_size)) / 1024.0);
2648 		file_sizeb = sbuf.st_size;
2649 
2650 		if (S_ISDIR(sbuf.st_mode)) {
2651 			wattrset(win, COLOR_PAIR(WHITE)|A_BOLD);
2652 			mvwprintw(win, y, 1, "%-48s", strbuf);
2653 			wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL);
2654 			wprintw(win, "          ");
2655 
2656 		} else {
2657 			wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL);
2658 			mvwprintw(win, y, 1, "%-48s %9d", strbuf, file_sizeb);
2659 		}
2660 	}
2661 
2662 	for (; y < FS_H-5; y++)
2663 		mvwprintw(win, y, 1, "%-58s", "");
2664 }
2665 
2666 /*** Print the directory content in window win. ***/
print_dir(WINDOW * win)2667 static void print_dir(WINDOW *win)
2668 {
2669 	int i;
2670 	int y;
2671 	int cnt;
2672 	int d = 0, f = 0;
2673 	char strbuf[NAME_MAX+1];
2674 	struct stat _sbuf, *sbuf = &_sbuf;
2675 
2676 	wattrset(win, A_NORMAL);
2677 	mvwprintw(win, 2, 1, "Dir: %-52s", dirname);
2678 	wattrset(win, A_BOLD);
2679 	mvwaddch(win, 2, 1, 'D');
2680 	wattrset(win, A_NORMAL);
2681 
2682 	/* Read dir. */
2683 	cnt = 0, nument = 0;
2684 	while ((drent[cnt] = readdir(dentry)) != NULL) {
2685 		if ((strcmp(drent[cnt]->d_name, ".")) == 0) continue;
2686 
2687 		stat(drent[cnt]->d_name, sbuf);
2688 		if (S_ISDIR(sbuf->st_mode))
2689 			strcpy(dnamed[d++], drent[cnt]->d_name);
2690 		else
2691 			strcpy(dnamef[f++], drent[cnt]->d_name);
2692 
2693 		cnt++, nument++;
2694 	}
2695 	drent[cnt] = NULL;
2696 
2697 	/* Copy dir and file name to entries name buffer
2698 	 * (this is needed by list_dir). */
2699 	for (i = 0, cnt = 0; i < d; i++, cnt++)
2700 		strcpy(dname[cnt], dnamed[i]);
2701 	for (i = 0; i < f; i++, cnt++)
2702 		strcpy(dname[cnt], dnamef[i]);
2703 
2704 	/* Print entries. */
2705 	for (y = 0, i = 0; i < FS_H-10; i++, y++) {
2706 		if (i == nument) break;
2707 
2708 		strncpy(strbuf, dname[i+current], 48);
2709 		strbuf[48] = '\0';
2710 
2711 		stat(dname[i+current], sbuf);
2712 		file_size =
2713 			(((float)(sbuf->st_size)) / 1024.0);
2714 		file_sizeb = sbuf->st_size;
2715 		if (S_ISDIR(sbuf->st_mode)) {
2716 			if (i == current)
2717 				wattrset(win, COLOR_PAIR(CYAN_BLUE)|A_BOLD);
2718 			else
2719 				wattrset(win, COLOR_PAIR(WHITE)|A_BOLD);
2720 			mvwprintw(win, y+5, 1, "%-48s", strbuf);
2721 			wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL);
2722 			wprintw(win, "          ");
2723 
2724 		} else {
2725 			if (i == current)
2726 				wattrset(win, COLOR_PAIR(CYAN_BLUE)|A_BOLD);
2727 			else
2728 				wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL);
2729 
2730 			mvwprintw(win, y+5, 1, "%-48s %9d", strbuf,
2731 					file_sizeb);
2732 		}
2733 
2734 	}
2735 
2736 	wattrset(win, A_NORMAL);
2737 	for (; y < FS_H-10; y++)
2738 		mvwprintw(win, y+5, 1, "%-58s", "");
2739 
2740 	wnoutrefresh(win);
2741 }
2742 
2743 /*** Check symlink. ***/
check_symlink(char * dir)2744 static int check_symlink(char *dir)
2745 {
2746 	int i;
2747 	char strbuf[NAME_MAX+1], *ptr;
2748 
2749 	i = readlink(dir, strbuf, NAME_MAX);
2750 	switch (i) {
2751 		case 0:
2752 		case -1:
2753 			return -1;
2754 		break;
2755 
2756 		default:
2757 			/* not added by readlink */
2758 			if (strbuf[i-1] == '/')
2759 				strbuf[i-1] = '\0';
2760 			else {
2761 				strbuf[i] = '\0';
2762 			}
2763 
2764 			if (strbuf[0] == '/') {	/* absolute path */
2765 				sprintf(dirname, strbuf);
2766 			} else {
2767 				i = strlen((ptr = rindex(dir, '/')));
2768 				fprintf(stderr, "%s\n", strbuf);
2769 				sprintf(ptr+1, strbuf);
2770 			}
2771 		break;
2772 	}
2773 
2774 	return 0;
2775 }
2776 
2777 /*** Check directory entry. ***/
check_dentry(char * name,WINDOW * win)2778 static void check_dentry(char *name, WINDOW *win)
2779 {
2780 	char *tmpstr;
2781 	char strbuf[NAME_MAX+1];
2782 	int len1, len2, len3;
2783 	struct stat _sbuf, *sbuf = &_sbuf;
2784 
2785 	check_symlink(dirname);
2786 	stat(name, sbuf);
2787 	if (S_ISDIR(sbuf->st_mode)) {
2788 		if (strcmp(name, "..") == 0) {
2789 			len1 = strlen(dirname);
2790 			len2 = strlen(tmpstr = rindex(dirname, '/'));
2791 			len3 = len1 - len2;
2792 			if (len3 == 0)
2793 				sprintf(dirname, "/");
2794 			else
2795 				dirname[len3] = '\0';
2796 		} else {
2797 			if (strlen(dirname) == 1)
2798 				sprintf(dirname, "%s%s", dirname, name);
2799 			else
2800 				sprintf(dirname, "%s/%s", dirname, name);
2801 		}
2802 
2803 		check_symlink(name);
2804 		chdir(name);
2805 		dentry=opendir(".");
2806 		current = 0;
2807 		print_dir(win);
2808 		closedir(dentry);
2809 
2810 		mvwprintw(win, FS_H-4, 1, "%-48s", "File:");
2811 		wattrset(win, A_BOLD);
2812 		mvwaddch(win, FS_H-4, 1, 'F');
2813 		wattrset(win, A_NORMAL);
2814 
2815 	} else if (S_ISREG(sbuf->st_mode)) {
2816 		wattrset(win, (COLOR_PAIR(WHITE)|A_NORMAL));
2817 		strncpy(strbuf, dname[current], 42);
2818 		strbuf[42] = '\0';
2819 
2820 		mvwprintw(win, FS_H-4, 1, "File: %-42s", strbuf);
2821 		strcpy(modpath, name);
2822 		wattrset(win, A_BOLD);
2823 		mvwaddch(win, FS_H-4, 1, 'F');
2824 		wattrset(win, A_NORMAL);
2825 	}
2826 }
2827 
2828 /*** File selector buttons. ***/
fs_buttons(WINDOW * win)2829 static int fs_buttons(WINDOW *win)
2830 {
2831 	int c;
2832 	int in_loop = 1;
2833 	fs_val = 0;
2834 
2835 	wattrset(win, A_REVERSE);
2836 	mvwprintw(win, FS_H-2, 16, "[ OK ]");
2837 	wattrset(win, A_NORMAL);
2838 	mvwprintw(win, FS_H-2, 34, "[ Cancel ]");
2839 
2840 	wnoutrefresh(win);
2841 	doupdate();
2842 
2843 	while (in_loop) {
2844 		switch ((c = wgetch(win))) {
2845 			case KEY_RIGHT:
2846 				wattrset(win, A_NORMAL);
2847 				mvwprintw(win, FS_H-2, 16, "[ OK ]");
2848 				wattrset(win, A_REVERSE);
2849 				mvwprintw(win, FS_H-2, 34, "[ Cancel ]");
2850 				fs_val = 1;
2851 			break;
2852 			case KEY_LEFT:
2853 				wattrset(win, A_REVERSE);
2854 				mvwprintw(win, FS_H-2, 16, "[ OK ]");
2855 				wattrset(win, A_NORMAL);
2856 				mvwprintw(win, FS_H-2, 34, "[ Cancel ]");
2857 				fs_val = 0;
2858 			break;
2859 			case KEY_TAB:
2860 				wattrset(win, A_NORMAL);
2861 				mvwprintw(win, FS_H-2, 16, "[ OK ]");
2862 				mvwprintw(win, FS_H-2, 34, "[ Cancel ]");
2863 				fs_val = 2;
2864 				in_loop = 0;
2865 				continue;
2866 			break;
2867 			case KEY_ENTER:
2868 				in_loop = 0;
2869 				continue;
2870 			break;
2871 		}
2872 
2873 
2874 		if (mod && playing) {
2875 			refresh_info();
2876 			refresh_module_info();
2877 			doupdate();
2878 			update_panels();
2879 			MikMod_Update();
2880 		}
2881 	}
2882 
2883 	return fs_val;
2884 }
2885 
2886 /*** Enter file selector. ***/
file_select(void)2887 static char *file_select(void)
2888 {
2889 	int i;
2890 	int in_loop = 1;
2891 	int tabsw = 0;
2892 	char strbuf[NAME_MAX+1];
2893 	WINDOW *tmpwin;
2894 	struct stat sbuf;
2895 
2896         fswin = tmpwin = newwin(FS_H, FS_W, FS_Y, FS_X);
2897 	keypad(tmpwin, TRUE);
2898 	wtimeout(tmpwin, DELAY);
2899         box(tmpwin, 0, 0);
2900 	fspan = new_panel(fswin);
2901 
2902 	wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL));
2903 	mvwprintw(tmpwin, 0, 2, "[             ]");
2904 	wattrset(tmpwin, (COLOR_PAIR(YELLOW)|A_BOLD));
2905 	mvwprintw(tmpwin, 0, 4, "Select file");
2906 
2907 	wattrset(tmpwin, A_NORMAL);
2908 	mvwprintw(tmpwin, FS_H-4, 1, "File: ");
2909 	wattrset(tmpwin, A_BOLD);
2910 	mvwaddch(tmpwin, FS_H-4, 1, 'F');
2911 	wattrset(tmpwin, A_NORMAL);
2912 
2913 	mvwaddch(tmpwin, 4, 0, ACS_LTEE);
2914 	mvwaddch(tmpwin, FS_H-3, 0, ACS_LTEE);
2915 	mvwaddch(tmpwin, FS_H-5, 0, ACS_LTEE);
2916 	for (i = 1; i < FS_W-1; i++) {
2917 		mvwaddch(tmpwin, 4, i, ACS_HLINE);
2918 		mvwaddch(tmpwin, FS_H-3, i, ACS_HLINE);
2919 		mvwaddch(tmpwin, FS_H-5, i, ACS_HLINE);
2920 	}
2921 	mvwaddch(tmpwin, 4, FS_W-1, ACS_RTEE);
2922 	mvwaddch(tmpwin, FS_H-3, FS_W-1, ACS_RTEE);
2923 	mvwaddch(tmpwin, FS_H-5, FS_W-1, ACS_RTEE);
2924 
2925 	wattrset(tmpwin, A_NORMAL);
2926 	mvwprintw(tmpwin, FS_H-2, 16, "[ OK ]");
2927 	mvwprintw(tmpwin, FS_H-2, 34, "[ Cancel ]");
2928 
2929 	memset(modpath, 0, 256);
2930 
2931 	/* Check and open dir. */
2932 	if (strlen(lastdir) == 0)
2933 		sprintf(dirname, (getenv("PWD")));
2934 	else
2935 		sprintf(dirname, lastdir);
2936 
2937 	check_symlink(dirname);
2938 	dentry = opendir(dirname);
2939 	chdir(dirname);
2940 	print_dir(tmpwin);
2941 	closedir(dentry);
2942 
2943 	update_panels();
2944 	doupdate();
2945 
2946 	/*** Loop ***/
2947 	fspage = lastpage = 0;
2948 	while (in_loop) {
2949 		switch ((wgetch(tmpwin))) {
2950 			case ERR: break;
2951 
2952 			case 'm':
2953 				  mp_move_panel(fspan);
2954 			break;
2955 
2956 			/* Edit directory name. */
2957 			case 'd': case 'D':
2958 				stat(dname[current], &sbuf);
2959 				if (S_ISREG(sbuf.st_mode) == 0)
2960 					wattrset(tmpwin, A_BOLD);
2961 				else
2962 					wattrset(tmpwin, A_NORMAL);
2963 				mvwprintw(tmpwin,
2964 					(current%(FS_H-10))+5, 1,
2965 					"%-48s", strbuf);
2966 
2967 				sprintf(lastdir, dirname);
2968 				wattrset(tmpwin, A_REVERSE);
2969 				get_string(tmpwin, 2, 1, "Dir: ", dirname);
2970 				wattrset(tmpwin, A_NORMAL);
2971 
2972 				if (chdir(dirname)) {
2973 					sprintf(dirname, lastdir);
2974 					mvwprintw(tmpwin, 2, 1,
2975 						"Dir: %-52s", dirname);
2976 					wattrset(tmpwin, A_BOLD);
2977 					mvwaddch(tmpwin, 2, 1, 'D');
2978 
2979 					wattrset(tmpwin, A_REVERSE);
2980 					strncpy(strbuf, dname[current], 48);
2981 					mvwprintw(tmpwin,
2982 						(current%(FS_H-10))+5, 1,
2983 						"%-48s", strbuf);
2984 
2985 					beep();
2986 					break;
2987 				}
2988 
2989 				current = 0;
2990 				check_symlink(dirname);
2991 				dentry = opendir(dirname);
2992 				print_dir(tmpwin);
2993 				closedir(dentry);
2994 
2995 				wattrset(tmpwin,
2996 					COLOR_PAIR(CYAN_BLUE)|A_BOLD);
2997 				strncpy(strbuf, dname[current], 48);
2998 				mvwprintw(tmpwin,
2999 					(current%(FS_H-10))+5, 1,
3000 					"%-48s", strbuf);
3001 			break;
3002 
3003 			/* Edit file name. */
3004 			case 'f': case 'F':
3005 				stat(dname[current], &sbuf);
3006 				if (S_ISREG(sbuf.st_mode) == 0)
3007 					wattrset(tmpwin, A_BOLD);
3008 				else
3009 					wattrset(tmpwin, A_NORMAL);
3010 				mvwprintw(tmpwin,
3011 					(current%(FS_H-10))+5, 1,
3012 					"%-48s", strbuf);
3013 
3014 				wattrset(tmpwin, A_REVERSE);
3015 				get_string(tmpwin,FS_H-4, 1,
3016 						"File: ", modpath);
3017 				wattrset(tmpwin, A_NORMAL);
3018 
3019 				if (strlen(modpath) != 0 &&
3020 						getstrtab != 1) {
3021 					fs_val  = 0;	/* OK */
3022 					in_loop = 0;
3023 					continue;
3024 				}
3025 
3026 				mvwprintw(tmpwin, FS_H-4, 1,
3027 					"File: %-52s", modpath);
3028 
3029 				wattrset(tmpwin,
3030 					COLOR_PAIR(CYAN_BLUE)|A_BOLD);
3031 				strncpy(strbuf, dname[current], 48);
3032 				mvwprintw(tmpwin,
3033 					(current%(FS_H-10))+5, 1,
3034 					"%-48s", strbuf);
3035 
3036 			break;
3037 
3038 			/* Enter buttons (OK, Cancel). */
3039 			case KEY_TAB:
3040 				tabsw = 1-tabsw;
3041 				if (tabsw == 1) {
3042 					stat(dname[current], &sbuf);
3043 					if (S_ISREG(sbuf.st_mode) == 0)
3044 						wattrset(tmpwin, A_BOLD);
3045 					else
3046 						wattrset(tmpwin, A_NORMAL);
3047 
3048 					strncpy(strbuf, dname[current], 48);
3049 					strbuf[48] = '\0';
3050 					mvwprintw(tmpwin,
3051 						(current%(FS_H-10))+5, 1,
3052 						"%-48s", strbuf);
3053 
3054 					fs_buttons(tmpwin);
3055 
3056 					if (fs_val != 2) {
3057 						in_loop = 0;
3058 						continue;
3059 					}
3060 					tabsw = 0;
3061 				}
3062 
3063 				if (tabsw == 0) {
3064 					strncpy(strbuf, dname[current], 48);
3065 					strbuf[48] = '\0';
3066 					wattrset(tmpwin,
3067 						COLOR_PAIR(CYAN_BLUE)|A_BOLD);
3068 					mvwprintw(tmpwin,
3069 						(current%(FS_H-10))+5, 1,
3070 						"%-48s", strbuf);
3071 				}
3072 			break;
3073 
3074 			case KEY_ENTER:
3075 				check_dentry(dname[current], tmpwin);
3076 			break;
3077 
3078 			/* Up. */
3079 			case KEY_UP:
3080 				stat(dname[current], &sbuf);
3081 
3082 				if (S_ISREG(sbuf.st_mode) == 0)
3083 					wattrset(tmpwin, A_BOLD);
3084 				else
3085 					wattrset(tmpwin, A_NORMAL);
3086 
3087 				strncpy(strbuf, dname[current], 48);
3088 				strbuf[48] = '\0';
3089 				mvwprintw(tmpwin, (current%(FS_H-10))+5, 1,
3090 					"%-48s", strbuf);
3091 
3092 				if (current > 0) current--;
3093 				fspage = (current/(FS_H-10));
3094 				if (lastpage > fspage) {
3095 					lastpage = fspage;
3096 					list_dir(tmpwin);
3097 				}
3098 
3099 				wattrset(tmpwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD);
3100 				strncpy(strbuf, dname[current], 48);
3101 				strbuf[48] = '\0';
3102 				mvwprintw(tmpwin, (current%(FS_H-10))+5, 1,
3103 					"%-48s", strbuf);
3104 			break;
3105 			case KEY_PPAGE:
3106 				wattrset(tmpwin, A_NORMAL);
3107 				mvwprintw(tmpwin, (current%(FS_H-10))+5, 1,
3108 					"%-48s", dname[current]);
3109 				if (((fspage-1)*(FS_H-10)) >= 0)
3110 					current = (--fspage*(FS_H-10));
3111 				else
3112 					current = 0;
3113 
3114 				fspage = (current/(FS_H-10));
3115 				if (lastpage > fspage) {
3116 					lastpage = fspage;
3117 					list_dir(tmpwin);
3118 				}
3119 
3120 				wattrset(tmpwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD);
3121 				mvwprintw(tmpwin, (current%(FS_H-10))+5, 1,
3122 					"%-48s", dname[current]);
3123 			break;
3124 
3125 			/* Down. */
3126 			case KEY_DOWN:
3127 				stat(dname[current], &sbuf);
3128 
3129 				if (S_ISREG(sbuf.st_mode) == 0)
3130 					wattrset(tmpwin, A_BOLD);
3131 				else
3132 					wattrset(tmpwin, A_NORMAL);
3133 
3134 				strncpy(strbuf, dname[current], 48);
3135 				strbuf[48] = '\0';
3136 				mvwprintw(tmpwin, (current%(FS_H-10))+5, 1,
3137 					"%-48s", strbuf);
3138 
3139 				if (current < nument-1) current++;
3140 				fspage = (current/(FS_H-10));
3141 				if (lastpage < fspage) {
3142 					lastpage = fspage;
3143 					list_dir(tmpwin);
3144 				}
3145 
3146 				wattrset(tmpwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD);
3147 				strncpy(strbuf, dname[current], 48);
3148 				strbuf[48] = '\0';
3149 				mvwprintw(tmpwin, (current%(FS_H-10))+5, 1,
3150 					"%-48s", strbuf);
3151 			break;
3152 			case KEY_NPAGE:
3153 				wattrset(tmpwin, A_NORMAL);
3154 				mvwprintw(tmpwin, (current%(FS_H-10))+5, 1,
3155 					"%-48s", dname[current]);
3156 
3157 				if (((fspage+1)*(FS_H-10)) < nument)
3158 					current = ((fspage+1)*(FS_H-10));
3159 				else
3160 					current = nument-1;
3161 
3162 				fspage = (current/(FS_H-10));
3163 				lastpage = fspage;
3164 
3165 				list_dir(tmpwin);
3166 				wattrset(tmpwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD);
3167 				mvwprintw(tmpwin, (current%(FS_H-10))+5, 1,
3168 					"%-48s", dname[current]);
3169 			break;
3170 		}
3171 
3172 		if (mod && playing) {
3173 			refresh_info();
3174 			refresh_module_info();
3175 			update_panels();
3176 			doupdate();
3177 
3178 			MikMod_Update();
3179 		}
3180 
3181 		update_panels();
3182 		doupdate();
3183 	}
3184 	current = 0;
3185 	sprintf(lastdir, dirname);
3186 	sprintf(full_modname, "%s/%s", dirname, modpath);
3187 
3188 	del_panel(fspan);
3189 	delwin(fswin);
3190 	update_panels();
3191 	doupdate();
3192 
3193 	if (fs_val == 0)
3194 		return modpath;
3195 	else
3196 		return NULL;
3197 }
3198 
3199 /*****************************************************************************/
3200 
3201 /*** Display the load message. ***/
loading(int on)3202 static void loading(int on)
3203 {
3204 	WINDOW *tmpwin = NULL;
3205 
3206 	if (on == 0) {
3207 		delwin(tmpwin);
3208 		touchwin(dspwin);
3209 		doupdate();
3210 
3211 		return;
3212 	}
3213 
3214 	tmpwin = newwin(5, 14, (LINES/2)-3, 33);
3215 	box(tmpwin, 0, 0);
3216 	wattrset(tmpwin, (COLOR_PAIR(GREEN)|A_BOLD));
3217 	mvwprintw(tmpwin, 2, 2, "Loading...");
3218 	wnoutrefresh(tmpwin);
3219 	doupdate();
3220 }
3221 
3222 /*** Display a message in a separate window and wait
3223  *** for user confirmation (OK). ***/
message(char * msg,int level)3224 static void message(char *msg, int level)
3225 {
3226 	int c;
3227 	int len = strlen(msg);
3228 	WINDOW *tmpwin;
3229 	PANEL *tmppan;
3230 
3231 	tmpwin = newwin(6, len+4, (LINES/2)-4, (COLS/2)-((len+4)/2));
3232 	wtimeout(tmpwin, DELAY);
3233 	keypad(tmpwin, TRUE);
3234 	box(tmpwin, 0, 0);
3235 	tmppan = new_panel(tmpwin);
3236 
3237 	if (level == ERROR_MSG)
3238 		wattrset(tmpwin, (COLOR_PAIR(RED)|A_BOLD));
3239 	else
3240 		wattrset(tmpwin, (COLOR_PAIR(GREEN)|A_BOLD));
3241 	mvwprintw(tmpwin, 1, 2, msg);
3242 	wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_REVERSE));
3243 	mvwprintw(tmpwin, 4, (((len+4)/2)-3), "[ OK ]");
3244 
3245 	while ((c = wgetch(tmpwin)) != KEY_ENTER) {
3246 		if (mod && playing) {
3247 			refresh_info();
3248 			refresh_module_info();
3249 			update_panels();
3250 			doupdate();
3251 			MikMod_Update();
3252 		}
3253 	}
3254 
3255 	del_panel(tmppan);
3256 	delwin(tmpwin);
3257 	update_panels();
3258 	doupdate();
3259 }
3260 
3261 /*****************************************************************************/
3262 
3263 /***
3264  ***				Playlist.
3265  ***/
3266 int pl_val	   = 0;
3267 int pl_files	   = 0;
3268 int pl_cnt	   = 0;
3269 int pl_page	   = 0;
3270 int pl_entry	   = 0;
3271 int pl_playtime    = 0;
3272 char need_to_clear = 0;
3273 
3274 typedef struct {
3275 	int played;
3276 	char dir[NAME_MAX+1];
3277 	char name[NAME_MAX+1];
3278 	char fname[NAME_MAX+1];		/* full path */
3279 } list_entry;
3280 
3281 list_entry list_files[4096];
3282 
3283 #define MP_PL_HEADER		"MP PLAYING LIST"
3284 #define MP_PL_HEADER_SIZE	15
3285 
3286 /*** Load playlist file. ***/
load_pl_file(char * name)3287 static int load_pl_file(char *name)
3288 {
3289 	char c;
3290 	int cnt;
3291 	int len;
3292 
3293 	FILE *file;
3294 	char *fname;
3295 	char buf[NAME_MAX+1];
3296 
3297 	/* Open file. */
3298 	file = fopen(name, "r");
3299 	if (file == NULL) {
3300 		beep();
3301 		sprintf(buf, "Can't open '%s'.", name);
3302 		message(buf, ERROR_MSG);
3303 		return -1;
3304 	}
3305 
3306 	/* Check if it is an MP playlist file. */
3307 	fread(buf, MP_PL_HEADER_SIZE, 1, file);
3308 	buf[MP_PL_HEADER_SIZE] = '\0';
3309 	if ((strncmp(buf, MP_PL_HEADER, MP_PL_HEADER_SIZE)) != 0) {
3310 		beep();
3311 		sprintf(buf, "Not a playlist file.");
3312 		message(buf, ERROR_MSG);
3313 		return -1;
3314 	}
3315 	fread(buf, 1, 1, file);		/* skip '\n' */
3316 
3317 	/* Read data... */
3318 	pl_files = 0;
3319 	cnt = 0;
3320 	memset(buf, 0, NAME_MAX);
3321 	while ((fread(&c, 1, 1, file)) > 0) {
3322 		if (c != '\n') {
3323 			buf[cnt++] = c;
3324 			continue;
3325 		}
3326 		cnt = 0;
3327 
3328 		sprintf(list_files[pl_files].fname, buf);
3329 
3330 		fname = rindex(buf, '/');
3331 		fname[(strlen(fname)+1)] = '\0';
3332 		sprintf(list_files[pl_files].name, fname+1);
3333 
3334 		len = ((strlen(buf)) - (strlen(fname)));
3335 		buf[len] = '\0';
3336 
3337 		sprintf(list_files[pl_files].dir, buf);
3338 
3339 		pl_files++;
3340 
3341 		memset(buf, 0, NAME_MAX);
3342 	}
3343 
3344 	/* Close file. */
3345 	fclose(file);
3346 
3347 	return 0;
3348 }
3349 
3350 /*** Save playlist file. ***/
save_pl_file(char * name)3351 static int save_pl_file(char *name)
3352 {
3353 	int i;
3354 
3355 	FILE *file;
3356 	char buf[NAME_MAX+1];
3357 
3358 	/* Open file. */
3359 	file = fopen(name, "w");
3360 	if (file == NULL) {
3361 		beep();
3362 		sprintf(buf, "Can't open '%s'.", name);
3363 		message(buf, ERROR_MSG);
3364 		return -1;
3365 	}
3366 
3367 	/* Add header. */
3368 	fwrite(MP_PL_HEADER, MP_PL_HEADER_SIZE, 1, file);
3369 	fwrite("\n", 1, 1, file);
3370 
3371 	/* Write data... */
3372 	for (i = 0; i < pl_files; i++) {
3373 		sprintf(buf, "%s/%s\n",
3374 			list_files[i].dir,
3375 			list_files[i].name);
3376 
3377 		fwrite(buf, strlen(buf), 1, file);
3378 	}
3379 
3380 	/* Close file. */
3381 	fclose(file);
3382 
3383 	sprintf(buf, "'%s' saved.", name);
3384 	message(buf, INFO_MSG);
3385 
3386 	return 0;
3387 }
3388 
3389 /*** Refresh playlist. ***/
refresh_list_entries(WINDOW * win)3390 static void refresh_list_entries(WINDOW *win)
3391 {
3392 	int i;
3393 	int offset = (pl_page * (PL_H-2));
3394 
3395 	wattrset(win, (COLOR_PAIR(CYAN)|A_NORMAL));
3396 	for (i = 0; i < PL_H-2; i++) {
3397 		if (offset+i >= pl_files) {
3398 			mvwprintw(win, i+1, 1,
3399 				"%3d: %-48s",
3400 				(pl_page * (PL_H-2))+i+1, "EMPTY");
3401 				continue;
3402 		}
3403 		mvwprintw(win, i+1, 1, "%-48s", "");
3404 		mvwprintw(win, i+1, 1, "%3d: %s/%s",
3405 				offset+i+1,
3406 				list_files[offset + i].dir,
3407 				list_files[offset + i].name
3408 		);
3409 	}
3410 
3411 	wattrset(win, (COLOR_PAIR(WHITE)|A_NORMAL));
3412 	mvwprintw(win, PL_H-1, PL_W-34, "[ %5d entries ]", pl_files);
3413 }
3414 
3415 /*** Playlist module info. ***/
3416 #define MINF_H		12
3417 #define MINF_W		60
3418 #define MINF_X		((COLS/2)-(MINF_W/2))
3419 #define MINF_Y		((LINES/2)-(MINF_H/2))
pl_mod_info(char * path)3420 static void pl_mod_info(char *path)
3421 {
3422 	int c;
3423 	int in_loop = 1;
3424 	struct stat sbuf;
3425 	WINDOW *tmpwin;
3426 	PANEL *tmppan;
3427 	MODULE *infomod;
3428 
3429 	if (path == NULL)
3430 		return;
3431 
3432 	tmpwin = newwin(MINF_H, MINF_W, MINF_Y, MINF_X);
3433 	wtimeout(tmpwin, DELAY);
3434 	keypad(tmpwin, TRUE);
3435 	box(tmpwin, 0, 0);
3436 	tmppan = new_panel(tmpwin);
3437 
3438 	wattrset(tmpwin, A_NORMAL);
3439 	mvwprintw(tmpwin, 0, 2, "[             ]");
3440 	wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD);
3441 	mvwprintw(tmpwin, 0, 4, "Module info");
3442 
3443 	wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD);
3444 	mvwprintw(tmpwin, (MINF_H/2)-1, 16, "Please wait...");
3445 	wnoutrefresh(tmpwin);
3446 	doupdate();
3447 	if ((infomod = Player_Load(path, 64, 0)) == NULL) {
3448 		del_panel(tmppan);
3449 		delwin(tmpwin);
3450 		update_panels();
3451 		doupdate();
3452 		message(MikMod_strerror(MikMod_errno), ERROR_MSG);
3453 
3454 		return;
3455 	}
3456 	wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL);
3457 	stat(path, &sbuf);
3458 	mvwprintw(tmpwin, (MINF_H/2)-1, 16, "              ");
3459 	mvwprintw(tmpwin, 1, 1, "   File: %s - Size: %d",
3460 			list_files[pl_entry].name,
3461 			sbuf.st_size);
3462 	mvwprintw(tmpwin, 2, 1, "   Name: %s", infomod->songname);
3463 	mvwprintw(tmpwin, 3, 1, "   Type: %s", infomod->modtype);
3464 	mvwprintw(tmpwin, 4, 1, "    Chn: %d", infomod->numchn);
3465 	mvwprintw(tmpwin, 5, 1, "Samples: %d", infomod->numsmp);
3466 	mvwprintw(tmpwin, 6, 1, " Instr.: %d", infomod->numins);
3467 	mvwprintw(tmpwin, 7, 1, "    BMP: %d", infomod->bpm);
3468 	mvwprintw(tmpwin, 8, 1, "  Speed: %d", infomod->sngspd);
3469 	mvwprintw(tmpwin, 9, 1, "  Tempo: %d", infomod->inittempo);
3470 	mvwprintw(tmpwin, 10, 1, "    Vol: %d", infomod->initvolume);
3471 	Player_Free(infomod);
3472 
3473 	while (in_loop) {
3474 		switch ((c = wgetch(tmpwin))) {
3475 			case 'q': case KEY_ESCAPE:
3476 				in_loop = 0;
3477 				continue;
3478 			break;
3479 		}
3480 
3481 		if (mod && playing) {
3482 			refresh_info();
3483 			refresh_module_info();
3484 			update_panels();
3485 			doupdate();
3486 			MikMod_Update();
3487 		}
3488 	}
3489 
3490 	del_panel(tmppan);
3491 	delwin(tmpwin);
3492 	update_panels();
3493 	doupdate();
3494 }
3495 
3496 /*** Delete playlist entry. ***/
3497 #define PL_DEL		1
3498 #define PL_UP		2
3499 #define PL_DOWN		3
3500 #define PL_INFO		4
3501 
handle_pl_entry(WINDOW * win,int action)3502 static void handle_pl_entry(WINDOW *win, int action)
3503 {
3504 	int i;
3505 	int c;
3506 	int in_loop  = 1;
3507 	int lastpage = pl_page;
3508 
3509 	refresh_list_entries(win);
3510 	wattrset(win, COLOR_PAIR(CYAN)|A_REVERSE);
3511 	mvwprintw(win, (pl_entry % (PL_H-2))+1, 6,
3512 		"%s", list_files[pl_entry].fname);
3513 	wnoutrefresh(win);
3514 	doupdate();
3515 
3516 	/*** Main loop. ***/
3517 	while (in_loop) {
3518 		switch ((c = wgetch(win))) {
3519 			/* Cancel. */
3520 			case KEY_ESCAPE:
3521 			case KEY_TAB:
3522 				in_loop = 0;
3523 				continue;
3524 			break;
3525 
3526 			/* Action. */
3527 			case KEY_ENTER:
3528 				if (action == PL_DEL) {
3529 					memset(&list_files[pl_entry], 0,
3530 							sizeof(list_entry));
3531 
3532 					if (pl_entry == pl_files-1) {
3533 						if (pl_entry)
3534 							pl_entry = 0;
3535 						if (pl_files)
3536 							pl_files--;
3537 
3538 						in_loop = 0;
3539 						continue;
3540 					}
3541 
3542 					for (i=pl_entry; i < pl_files-1; i++) {
3543 						memcpy(&list_files[i],
3544 							&list_files[i+1],
3545 							(sizeof(list_entry)));
3546 					}
3547 					pl_files--;
3548 
3549 					in_loop = 0;
3550 					continue;
3551 
3552 				} else if (action == PL_UP) {
3553 					if (pl_entry > 0) {
3554 						list_entry t;
3555 						memcpy(&t,
3556 							&list_files[pl_entry-1],
3557 							(sizeof(list_entry)));
3558 						memcpy(&list_files[pl_entry-1],
3559 							&list_files[pl_entry],
3560 							(sizeof(list_entry)));
3561 						memcpy(&list_files[pl_entry],
3562 							&t,
3563 							(sizeof(list_entry)));
3564 					}
3565 
3566 					in_loop = 0;
3567 					continue;
3568 
3569 				} else if (action == PL_DOWN) {
3570 					if (pl_entry < pl_files-1) {
3571 						list_entry t;
3572 						memcpy(&t,
3573 							&list_files[pl_entry+1],
3574 							(sizeof(list_entry)));
3575 						memcpy(&list_files[pl_entry+1],
3576 							&list_files[pl_entry],
3577 							(sizeof(list_entry)));
3578 						memcpy(&list_files[pl_entry],
3579 							&t,
3580 							(sizeof(list_entry)));
3581 					}
3582 
3583 					in_loop = 0;
3584 					continue;
3585 
3586 				} else if (action == PL_INFO) {
3587 					if (playing) {
3588 						message("Player is running.",
3589 								ERROR_MSG);
3590 						break;
3591 					}
3592 					pl_mod_info(list_files[pl_entry].fname);
3593 				}
3594 			break;
3595 
3596 			/* Select entry (up/down). */
3597 			case KEY_UP:
3598 				if (pl_entry > 0) {
3599 					wattrset(win,
3600 						COLOR_PAIR(CYAN)|A_NORMAL);
3601 					mvwprintw(win,
3602 						(pl_entry % (PL_H-2))+1,
3603 						6, "%s",
3604 						list_files[pl_entry].fname);
3605 					pl_entry--;
3606 				} else
3607 					break;
3608 
3609 				pl_page = (pl_entry / (PL_H-2));
3610 				if (lastpage != pl_page) {
3611 					lastpage = pl_page;
3612 					refresh_list_entries(win);
3613 				}
3614 
3615 				wattrset(win,
3616 					COLOR_PAIR(CYAN)|A_REVERSE);
3617 				mvwprintw(win,
3618 					(pl_entry % (PL_H-2))+1, 6, "%s",
3619 					list_files[pl_entry].fname);
3620 
3621 			break;
3622 			case KEY_PPAGE:
3623 				if (pl_entry > 0) {
3624 					wattrset(win,
3625 						COLOR_PAIR(CYAN)|A_NORMAL);
3626 					mvwprintw(win,
3627 						(pl_entry % (PL_H-2))+1,
3628 						6, "%s",
3629 						list_files[pl_entry].fname);
3630 					pl_entry--;
3631 				} else
3632 					break;
3633 
3634 				if (((pl_page-1)*(PL_H-2)) > 0) {
3635 					pl_page--;
3636 					pl_entry = pl_page * (PL_H-2);
3637 				} else
3638 					pl_entry = 0;
3639 				pl_page = (pl_entry / (PL_H-2));
3640 				if (lastpage != pl_page) {
3641 					lastpage = pl_page;
3642 					refresh_list_entries(win);
3643 				}
3644 
3645 				refresh_list_entries(win);
3646 
3647 				wattrset(win,
3648 					COLOR_PAIR(CYAN)|A_REVERSE);
3649 				mvwprintw(win,
3650 					(pl_entry % (PL_H-2))+1, 6, "%s",
3651 					list_files[pl_entry].fname);
3652 
3653 			break;
3654 
3655 			case KEY_DOWN:
3656 				if (pl_entry < pl_files-1) {
3657 					wattrset(win,
3658 						COLOR_PAIR(CYAN)|A_NORMAL);
3659 					mvwprintw(win,
3660 						(pl_entry % (PL_H-2))+1,
3661 						6, "%s",
3662 						list_files[pl_entry].fname);
3663 					pl_entry++;
3664 				} else
3665 					break;
3666 
3667 				pl_page = (pl_entry / (PL_H-2));
3668 				if (lastpage != pl_page) {
3669 					lastpage = pl_page;
3670 					refresh_list_entries(win);
3671 				}
3672 
3673 				wattrset(win,
3674 					COLOR_PAIR(CYAN)|A_REVERSE);
3675 				mvwprintw(win,
3676 					(pl_entry % (PL_H-2))+1, 6, "%s",
3677 					list_files[pl_entry].fname);
3678 
3679 			break;
3680 			case KEY_NPAGE:
3681 				if (pl_entry < pl_files-1) {
3682 					wattrset(win,
3683 						COLOR_PAIR(CYAN)|A_NORMAL);
3684 					mvwprintw(win,
3685 						(pl_entry % (PL_H-2))+1,
3686 						6, "%s",
3687 						list_files[pl_entry].fname);
3688 					pl_entry--;
3689 				} else
3690 					break;
3691 
3692 				if (((pl_page+1)*(PL_H-2)) < pl_files-1) {
3693 					pl_page++;
3694 					pl_entry = pl_page * (PL_H-2);
3695 				} else
3696 					pl_entry = pl_files-1;
3697 				pl_page = (pl_entry / (PL_H-2));
3698 				if (lastpage != pl_page) {
3699 					lastpage = pl_page;
3700 					refresh_list_entries(win);
3701 				}
3702 
3703 				refresh_list_entries(win);
3704 
3705 				wattrset(win,
3706 					COLOR_PAIR(CYAN)|A_REVERSE);
3707 				mvwprintw(win,
3708 					(pl_entry % (PL_H-2))+1, 6, "%s",
3709 					list_files[pl_entry].fname);
3710 
3711 			break;
3712 		}
3713 
3714 		if (mod && playing) {
3715 			refresh_info();
3716 			refresh_module_info();
3717 			update_panels();
3718 			doupdate();
3719 			MikMod_Update();
3720 		}
3721 	}
3722 
3723 	wattrset(win, COLOR_PAIR(CYAN)|A_NORMAL);
3724 	mvwprintw(win, (pl_entry % (PL_H-2))+1, 6,
3725 		"%s", list_files[pl_entry].fname);
3726 
3727 	refresh_list_entries(win);
3728 	wnoutrefresh(win);
3729 	doupdate();
3730 }
3731 
3732 /*** Playlist buttons. ***/
pl_buttons(WINDOW * win)3733 static int pl_buttons(WINDOW *win)
3734 {
3735 	int i, c;
3736 	int ys;
3737 	int in_loop = 1;
3738 	char *name;
3739 	char *pl_btns[10] = {
3740 		"[ Add file  ]",
3741 		"[  Add dir  ]",
3742 		"[  Remove   ]",
3743 		"[   Clear   ]",
3744 		"[  Move up  ]",
3745 		"[ Move down ]",
3746 		"[   Info    ]",
3747 		"[   Load    ]",
3748 		"[   Save    ]",
3749 		"[   Done    ]"
3750 	};
3751 	struct stat sbuf;
3752 
3753 	pl_val = 0;
3754 
3755 	wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL);
3756 	for (i = 0, ys = 0; i < 10; i++, ys++) {
3757 		if (pl_val == i)
3758 			wattrset(win, A_REVERSE);
3759 		else
3760 			wattrset(win, A_NORMAL);
3761 
3762 		mvwprintw(win, 2+(ys*2), (PL_W-15), "%s", pl_btns[i]);
3763 	}
3764 
3765 	while (in_loop) {
3766 		switch ((c = wgetch(win))) {
3767 			/* Quit playlist. */
3768 			case 'q':
3769 				pl_val = 255;
3770 				in_loop = 0;
3771 				continue;
3772 			break;
3773 
3774 			/* Move. */
3775 			case 'm':
3776 				mp_move_panel(plpan);
3777 			break;
3778 
3779 			/* Down. */
3780 			case KEY_NPAGE:
3781 				wattrset(win, A_NORMAL);
3782 				mvwprintw(win, 2+(pl_val*2), PL_W-15,
3783 					"%s", pl_btns[pl_val]);
3784 				pl_val = 9;
3785 				wattrset(win, A_REVERSE);
3786 				mvwprintw(win, 2+(pl_val*2), PL_W-15,
3787 					"%s", pl_btns[pl_val]);
3788 			break;
3789 			case KEY_DOWN:
3790 				wattrset(win, A_NORMAL);
3791 				mvwprintw(win, 2+(pl_val*2), PL_W-15,
3792 					"%s", pl_btns[pl_val]);
3793 				if (pl_val < 9) pl_val++;
3794 				wattrset(win, A_REVERSE);
3795 				mvwprintw(win, 2+(pl_val*2), PL_W-15,
3796 					"%s", pl_btns[pl_val]);
3797 			break;
3798 
3799 			/* Up. */
3800 			case KEY_PPAGE:
3801 				wattrset(win, A_NORMAL);
3802 				mvwprintw(win, 2+(pl_val*2), PL_W-15,
3803 					"%s", pl_btns[pl_val]);
3804 				pl_val = 0;
3805 				wattrset(win, A_REVERSE);
3806 				mvwprintw(win, 2+(pl_val*2), PL_W-15,
3807 					"%s", pl_btns[pl_val]);
3808 			break;
3809 			case KEY_UP:
3810 				wattrset(win, A_NORMAL);
3811 				mvwprintw(win, 2+(pl_val*2), PL_W-15,
3812 					"%s", pl_btns[pl_val]);
3813 				if (pl_val > 0) pl_val--;
3814 				wattrset(win, A_REVERSE);
3815 				mvwprintw(win, 2+(pl_val*2), PL_W-15,
3816 					"%s", pl_btns[pl_val]);
3817 			break;
3818 
3819 			/* Visit playlist. */
3820 			case KEY_TAB:
3821 				if (pl_files > 0) {
3822 					wattrset(win, A_NORMAL);
3823 					mvwprintw(win, 2+(pl_val*2), PL_W-15,
3824 						"%s", pl_btns[pl_val]);
3825 					wnoutrefresh(win);
3826 					doupdate();
3827 
3828 					handle_pl_entry(win, 0);
3829 
3830 					wattrset(win, A_REVERSE);
3831 					mvwprintw(win, 2+(pl_val*2), PL_W-15,
3832 						"%s", pl_btns[pl_val]);
3833 					wnoutrefresh(win);
3834 					doupdate();
3835 				}
3836 			break;
3837 
3838 			/* Action. */
3839 			case KEY_ENTER:
3840 				/* Add file. */
3841 				if (pl_val == 0) {
3842 					name = file_select();
3843 					if (name!=NULL && (strlen(name)) > 0) {
3844 					    sprintf(list_files[pl_files].fname,
3845 						"%s/%s", lastdir, name);
3846 					    sprintf(list_files[pl_files].name,
3847 						name);
3848 					    sprintf(list_files[pl_files].dir,
3849 						lastdir);
3850 
3851 					    pl_files++;
3852 					}
3853 
3854 					touchwin(win);
3855 					refresh_list_entries(win);
3856 
3857 				/* Add dir. */
3858 				} else if (pl_val == 1) {
3859 					file_select();
3860 					if (fs_val != 0) break;
3861 
3862 					for (i = 0; i < nument; i++) {
3863 					    stat(dname[i], &sbuf);
3864 					    if (S_ISREG(sbuf.st_mode)) {
3865 						    sprintf(
3866 						    list_files[pl_files].fname,
3867 						    "%s/%s", lastdir, dname[i]);
3868 						    sprintf(
3869 						    list_files[pl_files].name,
3870 						    dname[i]);
3871 						    sprintf(
3872 						    list_files[pl_files].dir,
3873 						    lastdir);
3874 					   	    pl_files++;
3875 					    }
3876 				        }
3877 
3878 					touchwin(win);
3879 					refresh_list_entries(win);
3880 
3881 				/* Remove. */
3882 				} else if (pl_val == 2) {
3883 					if (pl_files > 0) {
3884 						wattrset(win, A_NORMAL);
3885 						mvwprintw(win, 2+(pl_val*2),
3886 							PL_W-15,
3887 							"%s", pl_btns[pl_val]);
3888 						wnoutrefresh(win);
3889 						doupdate();
3890 
3891 						handle_pl_entry(win, PL_DEL);
3892 
3893 						wattrset(win, A_REVERSE);
3894 						mvwprintw(win, 2+(pl_val*2),
3895 							PL_W-15,
3896 							"%s", pl_btns[pl_val]);
3897 						wnoutrefresh(win);
3898 						doupdate();
3899 					}
3900 
3901 				/* Clear. */
3902 				} else if (pl_val == 3) {
3903 					for (i = 0; i < pl_files; i++) {
3904 						memset(&list_files[i],
3905 							0, sizeof(list_entry));
3906 					}
3907 					pl_files = 0;
3908 					refresh_list_entries(win);
3909 
3910 				/* Move up. */
3911 				} else if (pl_val == 4) {
3912 					if (pl_files > 0) {
3913 						wattrset(win, A_NORMAL);
3914 						mvwprintw(win, 2+(pl_val*2),
3915 							PL_W-15,
3916 							"%s", pl_btns[pl_val]);
3917 						wnoutrefresh(win);
3918 						doupdate();
3919 
3920 						handle_pl_entry(win, PL_UP);
3921 
3922 						wattrset(win, A_REVERSE);
3923 						mvwprintw(win, 2+(pl_val*2),
3924 							PL_W-15,
3925 							"%s", pl_btns[pl_val]);
3926 
3927 						wnoutrefresh(win);
3928 						doupdate();
3929 					}
3930 					refresh_list_entries(win);
3931 
3932 				/* Move down. */
3933 				} else if (pl_val == 5) {
3934 					if (pl_files > 0) {
3935 						wattrset(win, A_NORMAL);
3936 						mvwprintw(win, 2+(pl_val*2),
3937 							PL_W-15,
3938 							"%s", pl_btns[pl_val]);
3939 						wnoutrefresh(win);
3940 						doupdate();
3941 
3942 						handle_pl_entry(win, PL_DOWN);
3943 
3944 						wattrset(win, A_REVERSE);
3945 						mvwprintw(win, 2+(pl_val*2),
3946 							PL_W-15,
3947 							"%s", pl_btns[pl_val]);
3948 
3949 						wnoutrefresh(win);
3950 						doupdate();
3951 					}
3952 					refresh_list_entries(win);
3953 
3954 				/* Info. */
3955 				} else if (pl_val == 6) {
3956 					if (pl_files > 0) {
3957 						wattrset(win, A_NORMAL);
3958 						mvwprintw(win, 2+(pl_val*2),
3959 							PL_W-15,
3960 							"%s", pl_btns[pl_val]);
3961 						wnoutrefresh(win);
3962 						doupdate();
3963 
3964 						handle_pl_entry(win, PL_INFO);
3965 
3966 						wattrset(win, A_REVERSE);
3967 						mvwprintw(win, 2+(pl_val*2),
3968 							PL_W-15,
3969 							"%s", pl_btns[pl_val]);
3970 						wnoutrefresh(win);
3971 						doupdate();
3972 					}
3973 					refresh_list_entries(win);
3974 
3975 				/* Load. */
3976 				} else if (pl_val == 7) {
3977 					char *f = file_select();
3978 					if (f == NULL) {
3979 						touchwin(win);
3980 						break;
3981 					}
3982 					sprintf(pl_file, "%s/%s",
3983 							lastdir, f);
3984 					load_pl_file(pl_file);
3985 
3986 					refresh_list_entries(win);
3987 					touchwin(win);
3988 
3989 				/* Save. */
3990 				} else if (pl_val == 8) {
3991 					char *f = file_select();
3992 					if (f == NULL) {
3993 						touchwin(win);
3994 						break;
3995 					}
3996 					sprintf(pl_file, "%s/%s",
3997 							lastdir, f);
3998 					save_pl_file(pl_file);
3999 
4000 					refresh_list_entries(win);
4001 					touchwin(win);
4002 
4003 				/* Done. */
4004 				} else if (pl_val == 9) {
4005 					if (pl_files)
4006 						in_playlist = 1;
4007 					in_loop = 0;
4008 
4009 					continue;
4010 				}
4011 			break;
4012 		}
4013 
4014 		if (mod && playing) {
4015 			refresh_info();
4016 			refresh_module_info();
4017 			update_panels();
4018 			doupdate();
4019 			MikMod_Update();
4020 		}
4021 	}
4022 
4023 	return pl_val;
4024 }
4025 
4026 /*** Playlist handler (called with alarm(1)) ***/
update_playlist(int unused)4027 void update_playlist(int unused)
4028 {
4029 	int i;
4030 
4031 	if (in_playlist) {
4032 		if (mod->sngpos >= mod->numpos) {	/* end of module */
4033 			wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
4034 			for (i = 1; i < 40; i++)
4035 				mvwaddch(dspwin, DSP_H-1, i, ACS_HLINE);
4036 
4037 			pl_playtime += mod->sngtime;
4038 			if (!random_mode) {
4039 				if (pl_cnt < pl_files-1) {
4040 					pl_cnt++;
4041 					refresh_pl_info();
4042 
4043 					loading(1);
4044 					play_module(list_files[pl_cnt].fname);
4045 					loading(0);
4046 
4047 					touchwin(dspwin);
4048 
4049 				} else {
4050 					mvwprintw(dspwin, DSP_H-1, 2,
4051 					"[ Playlist finished %3d/%3d (%02d:%02d) ]",
4052 						pl_cnt+1,
4053 						pl_files,
4054 						(pl_playtime/1000)/60,
4055 						(pl_playtime/1000)%60);
4056 
4057 					in_playlist = 0;
4058 					need_to_clear = 1;
4059 				}
4060 
4061 			} else {	/* random_mode */
4062 				if (pl_cnt < pl_files-1) {
4063 					int i = 1 +
4064 						(((float) pl_files-1) * \
4065 					 	rand()) / (RAND_MAX+1.0);
4066 					pl_cnt++;
4067 					pl_playtime += mod->sngtime;
4068 					refresh_pl_info();
4069 
4070 					loading(1);
4071 					play_module(list_files[i].fname);
4072 					loading(0);
4073 
4074 					touchwin(dspwin);
4075 				}
4076 			}
4077 		}
4078 
4079 	} else {
4080 		for (i = 1; i < 40; i++);	/* reset last line */
4081 //			mvwaddch(dspwin, DSP_H-1, i, ACS_HLINE);
4082 	}
4083 
4084 	alarm(1);
4085 }
4086 
4087 /*** Install playlist handler ***/
install_pl_handler(void)4088 void install_pl_handler(void)
4089 {
4090 	pl_cnt = 0;
4091 
4092 	signal(SIGALRM, update_playlist);
4093 
4094 	alarm(1);
4095 }
4096 
4097 /*** Refresh playlist information (bottom of screen) ***/
refresh_pl_info(void)4098 static void refresh_pl_info(void)
4099 {
4100 	int i;
4101 
4102 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
4103 	for (i = 1; i < 48; i++)
4104 		mvwaddch(dspwin, DSP_H-1, i, ACS_HLINE);
4105 	mvwprintw(dspwin, DSP_H-1, 2, "[                                ]");
4106 	wattrset(dspwin, COLOR_PAIR(YELLOW_BLUE)|A_BOLD);
4107 	mvwprintw(dspwin, DSP_H-1, 4, "Playlist:");
4108 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
4109 	mvwprintw(dspwin, DSP_H-1, 16, "%3d/%3d   (%02d:%02d)",
4110 		pl_cnt+1,
4111 		pl_files,
4112 		((mod->sngtime+pl_playtime)/1000)/60,
4113 		((mod->sngtime+pl_playtime)/1000)%60);
4114 }
4115 
4116 /*** Enter playlist. ***/
playlist(void)4117 static void playlist(void)
4118 {
4119 	int i;
4120 	WINDOW *tmpwin;
4121 
4122         plwin = tmpwin = newwin(PL_H, PL_W, PL_Y, PL_X);
4123 	keypad(tmpwin, TRUE);
4124 	wtimeout(tmpwin, DELAY);
4125         box(tmpwin, 0, 0);
4126 	plpan = new_panel(plwin);
4127 
4128 	wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL));
4129 	mvwprintw(tmpwin, 0, 2,
4130 		"[                                                ]");
4131 	wattrset(tmpwin, (COLOR_PAIR(YELLOW)|A_BOLD));
4132 	mvwprintw(tmpwin, 0, 4,
4133 		" Playlist (press 'q' to quit without starting)");
4134 
4135 	wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL));
4136 	for (i = 1; i < PL_H-1; i++)
4137 		mvwaddch(tmpwin, i, PL_W-17, ACS_VLINE);
4138 	mvwaddch(tmpwin, PL_H-1, PL_W-17, ACS_BTEE);
4139 
4140 	refresh_list_entries(tmpwin);
4141 	pl_buttons(tmpwin);
4142 
4143 	del_panel(plpan);
4144 	delwin(plwin);
4145 	refresh_info();
4146 	refresh_module_info();
4147 	touchwin(dspwin);
4148 	update_panels();
4149 	doupdate();
4150 }
4151 
4152 /*****************************************************************************/
4153 
4154 /*** Draw a gauge. ***/
draw_gauge(WINDOW * win,int x,int y,int pc,int vh,int style)4155 static void draw_gauge(WINDOW *win, int x, int y, int pc, int vh, int style)
4156 {
4157 	int i;
4158 	int c = 0;
4159 	int ipc = pc;
4160 
4161 	if (pc > 100)
4162 		pc = 100;
4163 
4164 	if (style == 1 && vh == 1) {
4165 		c = ' ';
4166 		if (pc < 30)
4167 			wattrset(win, COLOR_PAIR(GREEN)|A_REVERSE);
4168 		else
4169 			wattrset(win, COLOR_PAIR(CYAN)|A_REVERSE);
4170 	} else if (style == 1 && vh == 0) {
4171 		wattrset(win, COLOR_PAIR(BLUE)|A_REVERSE);
4172 		c = ' ';
4173 	} else if (style == 2)
4174 		c = ACS_BULLET;
4175 	else if (style == 3) {
4176 		if (vh == 1)
4177 			c = ACS_RARROW;
4178 		else
4179 			c = ACS_UARROW;
4180 	} else if (style == 4)
4181 		c = '*';
4182 	else if (style == 5)
4183 		c = '#';
4184 
4185 	if (vh) {		/* horizontal */
4186 		pc /= 5;
4187 
4188 		for (i = 0; i < pc; i++)
4189 			mvwaddch(win, y, x+i, c);
4190 
4191 		if (style == 1)
4192 			wattrset(win, COLOR_PAIR(GREEN)|A_NORMAL);
4193 
4194 		for (; i < 20; i++)
4195 			mvwaddch(win, y, x+i, ' ');
4196 
4197 		if (pc == 20) {
4198 			if (style == 1) {
4199 				c = ' ';
4200 				wattrset(win, COLOR_PAIR(RED_RED)|A_NORMAL);
4201 			} else
4202 				wattrset(win, COLOR_PAIR(RED)|A_BOLD);
4203 
4204 			mvwaddch(win, y, x+i-1, c);
4205 
4206 			wattrset(win, COLOR_PAIR(RED)|A_BOLD);
4207 			wprintw(win, " %3d%%", ipc);
4208 
4209 		} else {
4210 			wattrset(win, COLOR_PAIR(WHITE)|A_NORMAL);
4211 			wprintw(win, " %3d%%", ipc);
4212 		}
4213 
4214 	} else {		/* vertical */
4215 		pc /= 10;
4216 
4217 		if (style == 1)
4218 			wattrset(win, COLOR_PAIR(BLUE)|A_REVERSE);
4219 		else
4220 			wattrset(win, COLOR_PAIR(BLUE)|A_NORMAL);
4221 
4222 		for (i = 0; i < pc; i++)
4223 			mvwaddch(win, y-i, x, c);
4224 
4225 		if (style == 1)
4226 			wattrset(win, COLOR_PAIR(BLUE)|A_NORMAL);
4227 		wattrset(win, COLOR_PAIR(BLUE)|A_BOLD);
4228 		for (; i < 10; i++)
4229 			mvwaddch(win, y-i, x, ACS_HLINE);
4230 
4231 		if (pc == 10) {
4232 			if (style == 1) {
4233 				c = ' ';
4234 				wattrset(win, COLOR_PAIR(RED_RED)|A_BOLD);
4235 			} else
4236 				wattrset(win, COLOR_PAIR(RED)|A_NORMAL);
4237 
4238 			mvwaddch(win, y-i+1, x, c);
4239 		}
4240 	}
4241 }
4242 
4243 /*** Draw channel pointer. ***/
draw_pointer(void)4244 static void draw_pointer(void)
4245 {
4246 	wattrset(dspwin, (COLOR_PAIR(WHITE|A_NORMAL)));
4247 	mvwaddch(dspwin, (oldcurch%(DSP_H-CHN_START))+CHN_START-1, 0, oldc1);
4248 	mvwaddch(dspwin, (oldcurch%(DSP_H-CHN_START))+CHN_START-1, 3, oldc2);
4249 	oldc1 = mvwinch(dspwin, (curch%(DSP_H-CHN_START))+CHN_START-1, 0);
4250 	oldc2 = mvwinch(dspwin, (curch%(DSP_H-CHN_START))+CHN_START-1, 3);
4251 	oldcurch = curch;
4252 	mvwaddch(dspwin, (curch%(DSP_H-CHN_START))+CHN_START-1, 0, '>');
4253 	mvwaddch(dspwin, (curch%(DSP_H-CHN_START))+CHN_START-1, 3, '<');
4254 }
4255 
4256 /*** Display help. ***/
display_help(void)4257 static void display_help(void)
4258 {
4259 	int c, in_loop = 1;
4260 
4261 	helpwin = newwin(HELP_H, HELP_W, HELP_Y, HELP_X);
4262 	wtimeout(helpwin, DELAY);
4263 	keypad(helpwin, TRUE);
4264         box(helpwin, 0, 0);
4265 
4266 	helppan = new_panel(helpwin);
4267 	top_panel(helppan);
4268 
4269 	wattrset(helpwin, COLOR_PAIR(WHITE)|A_NORMAL);
4270 	mvwprintw(helpwin, 0, 2, "[      ]");
4271 	wattrset(helpwin, COLOR_PAIR(YELLOW)|A_BOLD);
4272 	mvwprintw(helpwin, 0, 4, "Help");
4273 
4274 	/* COL 1 */
4275 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4276 	mvwprintw(helpwin, 1, 2, "Play or pause.............");
4277 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4278 	wprintw(helpwin, "p");
4279 
4280 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4281 	mvwprintw(helpwin, 2, 2, "Stop module...............");
4282 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4283 	wprintw(helpwin, "t");
4284 
4285 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4286 	mvwprintw(helpwin, 3, 2, "Module comment............");
4287 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4288 	wprintw(helpwin, "i");
4289 
4290 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4291 	mvwprintw(helpwin, 4, 2, "Restart pattern...........");
4292 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4293 	wprintw(helpwin, "a");
4294 
4295 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4296 	mvwprintw(helpwin, 5, 2, "Restart module............");
4297 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4298 	wprintw(helpwin, "A");
4299 
4300 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4301 	mvwprintw(helpwin, 7, 2, "Next position.............");
4302 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4303 	wprintw(helpwin, "n");
4304 
4305 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4306 	mvwprintw(helpwin, 8, 2, "Next module...............");
4307 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4308 	wprintw(helpwin, "N");
4309 
4310 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4311 	mvwprintw(helpwin, 9, 2, "Prev position.............");
4312 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4313 	wprintw(helpwin, "v");
4314 
4315 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4316 	mvwprintw(helpwin, 10, 2, "Prev module...............");
4317 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4318 	wprintw(helpwin, "V");
4319 
4320 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4321 	mvwprintw(helpwin, 12, 2, "File selector.............");
4322 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4323 	wprintw(helpwin, "f");
4324 
4325 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4326 	mvwprintw(helpwin, 13, 2, "Quit MP or close panel....");
4327 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4328 	wprintw(helpwin, "q");
4329 
4330 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4331 	mvwprintw(helpwin, 15, 2, "Show all channels.........");
4332 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4333 	wprintw(helpwin, "c");
4334 
4335 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4336 	mvwprintw(helpwin, 16, 2, "Show all voices...........");
4337 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4338 	wprintw(helpwin, "T");
4339 
4340 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4341 	mvwprintw(helpwin, 17, 2, "Voices position...........");
4342 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4343 	wprintw(helpwin, "Y");
4344 
4345 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4346 	mvwprintw(helpwin, 18, 2, "Voices frequency..........");
4347 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4348 	wprintw(helpwin, "y");
4349 
4350 	/* COL 2 */
4351 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4352 	mvwprintw(helpwin, 1, 34, "Bpm up/down...............");
4353 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4354 	wprintw(helpwin, "b/B");
4355 
4356 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4357 	mvwprintw(helpwin, 2, 34, "Reverb up/down............");
4358 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4359 	wprintw(helpwin, "r/R");
4360 
4361 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4362 	mvwprintw(helpwin, 3, 34, "Tempo up/down.............");
4363 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4364 	wprintw(helpwin, "k/K");
4365 
4366 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4367 	mvwprintw(helpwin, 4, 34, "Speed up/down.............");
4368 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4369 	wprintw(helpwin, "s/S");
4370 
4371 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4372 	mvwprintw(helpwin, 5, 34, "Volume up/down............");
4373 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4374 	wprintw(helpwin, "+/-");
4375 
4376 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4377 	mvwprintw(helpwin, 6, 34, "Reverse stereo............");
4378 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4379 	wprintw(helpwin, "!");
4380 
4381 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4382 	mvwprintw(helpwin, 7, 34, "Switch volume display.....");
4383 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4384 	wprintw(helpwin, "u");
4385 
4386 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4387 	mvwprintw(helpwin, 9, 34, "Playlist panel............");
4388 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4389 	wprintw(helpwin, "l");
4390 
4391 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4392 	mvwprintw(helpwin, 10, 34, "Effects panel.............");
4393 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4394 	wprintw(helpwin, "e");
4395 
4396 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4397 	mvwprintw(helpwin, 11, 34, "Options panel.............");
4398 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4399 	wprintw(helpwin, "o");
4400 
4401 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4402 	mvwprintw(helpwin, 12, 34, "Samples panel.............");
4403 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4404 	wprintw(helpwin, "w");
4405 
4406 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4407 	mvwprintw(helpwin, 13, 34, "Instruments panel.........");
4408 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4409 	wprintw(helpwin, "W");
4410 
4411 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4412 	mvwprintw(helpwin, 15, 34, "Select channel............");
4413 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4414 	wprintw(helpwin, "UP/DOWN");
4415 
4416 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4417 	mvwprintw(helpwin, 16, 34, "Mute/unmute channel.......");
4418 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4419 	wprintw(helpwin, "ENTER");
4420 
4421 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4422 	mvwprintw(helpwin, 17, 34, "Mute/unmute all channels..");
4423 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4424 	wprintw(helpwin, "M");
4425 
4426 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4427 	mvwprintw(helpwin, 18, 34, "About.....................");
4428 	wattrset(helpwin, COLOR_PAIR(CYAN)|A_BOLD);
4429 	wprintw(helpwin, "?");
4430 
4431 	wnoutrefresh(helpwin);
4432 	doupdate();
4433 
4434 	/*** Loop ***/
4435 	while (in_loop) {
4436 		switch ((c = wgetch(helpwin))) {
4437 			case 'q': case 'Q': case KEY_ESCAPE:
4438 				  in_loop = 0;
4439 				  continue;
4440 			break;
4441 
4442 			case 'm':
4443 				mp_move_panel(helppan);
4444 			break;
4445 		}
4446 
4447 		if (mod && playing) {
4448 			refresh_info();
4449 			refresh_module_info();
4450 			MikMod_Update();
4451 			update_panels();
4452 			doupdate();
4453 		}
4454 	}
4455 
4456 	del_panel(helppan);
4457 	update_panels();
4458 	doupdate();
4459 }
4460 
4461 
4462 /******************************************************************************/
4463 
4464 /*** Show voices position. ***/
show_voices_pos(void)4465 static void show_voices_pos(void)
4466 {
4467         int i;			/* counter */
4468 	int c;			/* character */
4469 	int x;			/* x position */
4470 	int step;		/* x step */
4471 	int add;		/* add to x */
4472         int pc;			/* percent */
4473 
4474 	unsigned char pan;	/* panning */
4475 	float pos1, pos2;	/* positions */
4476 
4477 	WINDOW *tmpwin;		/* channel window (temporary) */
4478 
4479 	/* Create window. */
4480 	tmpwin = newwin(VPOS_H, VPOS_W, VPOS_Y, VPOS_X);
4481 	vposwin = tmpwin;
4482 	wtimeout(tmpwin, DELAY);
4483 	keypad(tmpwin, TRUE);
4484 	box(tmpwin, 0, 0);
4485 	vpospan = new_panel(tmpwin);
4486 	wattrset(tmpwin, (COLOR_PAIR(CYAN_BLUE)|A_BOLD));
4487 	mvwprintw(tmpwin, 0, 0, "%-68s", " Voices position");
4488 	wattrset(tmpwin, A_NORMAL);
4489 
4490 	wattrset(tmpwin, (COLOR_PAIR(CYAN)|A_NORMAL));
4491 
4492 	/* Calculate x step and add. */
4493 	if (mod->numchn <= 32)
4494 		step = 2;
4495 	else step = 1;
4496 	add = step == 1 ? 1 : 0;
4497 
4498 	/* Display channel counter. */
4499 	for (c = 0; c < mod->numchn; c++) {
4500 		if (c == 0) {
4501 			mvwaddch(tmpwin, VPOS_H-3, 2, '|');
4502 			mvwprintw(tmpwin, VPOS_H-2, 2, "1");
4503 			continue;
4504 		}
4505 
4506 		if ((c % 4) == 0) {
4507 			mvwaddch(tmpwin, VPOS_H-3, (c*step) + add, '|');
4508 			mvwprintw(tmpwin, VPOS_H-2,
4509 				(c*step) + add, "%d", c);
4510 		}
4511 	}
4512 	mvwaddch(tmpwin, VPOS_H-3, (c*step) + add, '|');
4513 	mvwprintw(tmpwin, VPOS_H-2, (c*step) + add, "%d", c);
4514 
4515 	/*** Loop ***/
4516 	while ((c = wgetch(tmpwin)) != 'q') {
4517 		if (c == KEY_ESCAPE)
4518 			break;
4519 		else if (c == 'e')
4520 			effects();
4521 		else if (c == 'o')
4522 			options();
4523 		else if (c == 'p')
4524 			do_pause();
4525 		else if (c == 'm')
4526 			mp_move_panel(vpospan);
4527 
4528 		/* Draw voices. */
4529 		for (x = 0, i = 0; i < mod->numchn; x += step, i++) {
4530 			pos1 = get_voice_pos(i);
4531 			pos2 = maxfreq[i];
4532 			if (pos2 <= 0) pos2=1;
4533 			pc = (int) (100.0 * (pos1 / pos2));
4534 			draw_gauge(tmpwin, x+2, VPOS_H-4, pc, 0, gauge_style);
4535 			if (step == 2)
4536 				draw_gauge(tmpwin, x+3, VPOS_H-4,
4537 					pc, 0, gauge_style);
4538 
4539 			/* Panning. */
4540 			pan = (unsigned char) get_voice_panning(i);
4541 			if (pan == 128)
4542 				wattrset(tmpwin, COLOR_PAIR(BLUE)|A_BOLD);
4543 			else if (pan == 0 || (pan > 0 && pan < 128))
4544 				wattrset(tmpwin, COLOR_PAIR(MAGENTA)|A_BOLD);
4545 			else
4546 				wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD);
4547 
4548 			mvwaddch(tmpwin, 2, x+2,
4549 				(pan == 128 ? 'M' :
4550 				(pan == 0 || (pan > 0 && pan < 128)) ?
4551 				'L' :'R')
4552 			);
4553 		}
4554 
4555 		if (mod && playing) {
4556 			refresh_info();
4557 			refresh_module_info();
4558 			MikMod_Update();
4559 		}
4560 
4561 		update_panels();
4562 		doupdate();
4563 	}
4564 
4565 	del_panel(vpospan);
4566 	touchwin(dspwin);
4567 	wnoutrefresh(dspwin);
4568 	doupdate();
4569 	update_panels();
4570 }
4571 
4572 /*** Show voices frequency. ***/
show_voices_freq(void)4573 static void show_voices_freq(void)
4574 {
4575         int i;			/* counter */
4576 	int c;			/* character */
4577 	int x;			/* x position */
4578 	int step;		/* x step */
4579 	int add;		/* add to x */
4580         int pc;			/* percent */
4581 
4582 	unsigned char pan;	/* panning */
4583 	float freq1, freq2;	/* frequencies */
4584 
4585 	WINDOW *tmpwin;		/* channel window (temporary) */
4586 
4587 
4588 	/* Create window. */
4589 	vfreqwin = tmpwin = newwin(VFREQ_H, VFREQ_W, VFREQ_Y, VFREQ_X);
4590 	wtimeout(tmpwin, DELAY);
4591 	keypad(tmpwin, TRUE);
4592 	box(tmpwin, 0, 0);
4593 	vfreqpan = new_panel(tmpwin);
4594 	wattrset(tmpwin, (COLOR_PAIR(CYAN_BLUE)|A_BOLD));
4595 	mvwprintw(tmpwin, 0, 0, "%-68s", " Voices frequency");
4596 
4597 	/* Calculate x step and add. */
4598 	if (mod->numchn <= 32)
4599 		step = 2;
4600 	else step = 1;
4601 	add = step == 1 ? 1 : 0;
4602 
4603 	/* Display channel counter. */
4604 	wattrset(tmpwin, (COLOR_PAIR(CYAN)|A_NORMAL));
4605 	for (c = 0; c < mod->numchn; c++) {
4606 		if (c == 0) {
4607 			mvwaddch(tmpwin, VFREQ_H-3, 2, '|');
4608 			mvwprintw(tmpwin, VFREQ_H-2, 2, "1");
4609 			continue;
4610 		}
4611 
4612 		if ((c % 4) == 0) {
4613 			mvwaddch(tmpwin, VFREQ_H-3, (c*step) + add, '|');
4614 			mvwprintw(tmpwin, VFREQ_H-2,
4615 				(c*step) + add, "%d", c);
4616 		}
4617 	}
4618 	mvwaddch(tmpwin, VFREQ_H-3, (c*step) + add, '|');
4619 	mvwprintw(tmpwin, VFREQ_H-2, (c*step) + add, "%d", c);
4620 
4621 	/*** Loop ***/
4622 	while ((c = wgetch(tmpwin)) != 'q') {
4623 		if (c == KEY_ESCAPE)
4624 			break;
4625 		else if (c == 'e')
4626 			effects();
4627 		else if (c == 'o')
4628 			options();
4629 		else if (c == 'p')
4630 			do_pause();
4631 		else if (c == 'm')
4632 			mp_move_panel(vfreqpan);
4633 
4634 		/* Draw channels. */
4635 		for (x = 0, i = 0; i < mod->numchn; x += step, i++) {
4636 			pan = (unsigned char) get_voice_panning(i);
4637 			freq1 = get_voice_freq(i);
4638 			freq2 = maxfreq[i];
4639 			if (freq2 <= 0) freq2 = 1;
4640 
4641 			pc = (int) (100.0 * (freq1 / freq2));
4642 			draw_gauge(tmpwin, x+2, VFREQ_H-4, pc, 0, gauge_style);
4643 
4644 			if (step == 2)
4645 				draw_gauge(tmpwin, x+3, VFREQ_H-4,
4646 					pc, 0, gauge_style);
4647 
4648 			if (pan == 128)
4649 				wattrset(tmpwin, COLOR_PAIR(BLUE)|A_BOLD);
4650 			else if (pan == 0 || (pan > 0 && pan < 128))
4651 				wattrset(tmpwin, COLOR_PAIR(MAGENTA)|A_BOLD);
4652 			else
4653 				wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD);
4654 
4655 			mvwaddch(tmpwin, 2, x+2,
4656 				(pan == 128 ? 'M' :
4657 				(pan == 0 || (pan > 0 && pan < 128)) ?
4658 				'L' :'R')
4659 			);
4660 		}
4661 
4662 		if (mod && playing) {
4663 			refresh_info();
4664 			refresh_module_info();
4665 			MikMod_Update();
4666 		}
4667 
4668 		update_panels();
4669 		doupdate();
4670 	}
4671 
4672 	del_panel(vfreqpan);
4673 	touchwin(dspwin);
4674 	wnoutrefresh(dspwin);
4675 	update_panels();
4676 	doupdate();
4677 }
4678 
4679 /*** Show all channels. ***/
show_all_channels(void)4680 static void show_all_channels(void)
4681 {
4682         int i;			/* counter */
4683 	int c;			/* character */
4684 	int x;			/* x position */
4685 	int step;		/* x step */
4686 	int add;		/* add to x */
4687         int pc;			/* percent */
4688 	int lastmod = 0;	/* for playlist checking */
4689 
4690 	unsigned char pan;	/* panning */
4691 	float vol1, vol2;	/* volume */
4692 
4693 	WINDOW *tmpwin;		/* channel window (temporary) */
4694 
4695 	/* Create window. */
4696 	acwin = tmpwin = newwin(AC_H, AC_W, AC_Y, AC_X);
4697 	wtimeout(tmpwin, DELAY);
4698 	keypad(tmpwin, TRUE);
4699 	box(tmpwin, 0, 0);
4700 	acpan = new_panel(tmpwin);
4701 	wattrset(tmpwin, (COLOR_PAIR(CYAN_BLUE)|A_BOLD));
4702 	mvwprintw(tmpwin, 0, 0, "%-68s", " All channels");
4703 
4704 	/* Calculate x step and add. */
4705 CHN_CNT:
4706 	step = mod->numchn <= 32 ? 2 : 1;
4707 	add = step == 1 ? 1 : 0;
4708 
4709 	/* Print channel counter. */
4710 	wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL);
4711 	for (i = 1; i < AC_H-1; i++)
4712 		mvwprintw(tmpwin, i, 1, "%66s", "");
4713 	wattrset(tmpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4714 	for (c = 0; c < mod->numchn; c++) {
4715 		if (c == 0) {
4716 			mvwaddch(tmpwin, AC_H-3, 2, '|');
4717 			mvwprintw(tmpwin, AC_H-2, 2, "1");
4718 			continue;
4719 		}
4720 
4721 		if (!(c % 4)) {
4722 			mvwaddch(tmpwin, AC_H-3, (c * step) + add, '|');
4723 			mvwprintw(tmpwin, AC_H-2,
4724 				(c*step) + add, "%d", c);
4725 		}
4726 	}
4727 	mvwaddch(tmpwin, AC_H-3, (c * step) + add, '|');
4728 	mvwprintw(tmpwin, AC_H-2, (c * step) + add, "%d", c);
4729 
4730 	/*** Loop ***/
4731 	if (in_playlist)
4732 		lastmod = pl_cnt;
4733 	while ((c = wgetch(tmpwin)) != 'q') {
4734 		if (c == KEY_ESCAPE)
4735 			break;
4736 		else if (c == 'e')
4737 			effects();
4738 		else if (c == 'o')
4739 			options();
4740 		else if (c == 'u') {
4741 			real_volume = 1-real_volume;
4742 			refresh_legend();
4743 		} else if (c == 'm')
4744 			mp_move_panel(acpan);
4745 		else
4746 			module_control(c);
4747 
4748 		if (c == '*') {
4749 			if (gauge_style < 5)
4750 				gauge_style++;
4751 			else
4752 				gauge_style = 1;
4753 		}
4754 
4755 		/* Draw channels. */
4756 		for (x = 0, i = 0; i < mod->numchn; x += step, i++) {
4757 			if (real_volume) {
4758 				vol1 = get_voice_realvol(i);
4759 				vol2 = maxrvol[i];
4760 				if (vol2 <= 0) vol2=1;
4761 				pc = (int) (100.0 * (vol1 / vol2));
4762 				draw_gauge(tmpwin, x+2, AC_H-4,
4763 					pc, 0, gauge_style);
4764 
4765 			} else {
4766 				vol1 = get_voice_volume(i);
4767 				vol2 = maxvol[i];
4768 				if (vol2 <= 0) vol2 = 1;
4769 				pc = (int) (100.0 * (vol1 / vol2));
4770 				draw_gauge(tmpwin, x+2, AC_H-4,
4771 					pc, 0, gauge_style);
4772 			}
4773 			if (step == 2)
4774 				draw_gauge(tmpwin, x+3, AC_H-4,
4775 					pc, 0, gauge_style);
4776 
4777 			/* Volume.
4778 			vol1 = get_voice_volume(i);
4779 			if (vol1 > 0)
4780 				wattrset(tmpwin, COLOR_PAIR(GREEN)|A_BOLD);
4781 			else
4782 				wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL);
4783 			if (vol1 >= 128 && vol1 < MODVOL_LIMIT)
4784 				wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD);
4785 			else if (vol1 >= MODVOL_LIMIT)
4786 				wattrset(tmpwin, COLOR_PAIR(RED)|A_BOLD);
4787 			mvwaddch(tmpwin, 1, x+2, ACS_BLOCK);*/
4788 
4789 			/* Panning. */
4790 			pan = (unsigned char) get_voice_panning(i);
4791 			if (pan == 128)
4792 				wattrset(tmpwin, COLOR_PAIR(BLUE)|A_BOLD);
4793 			else if (pan == 0 || (pan > 0 && pan < 128))
4794 				wattrset(tmpwin, COLOR_PAIR(MAGENTA)|A_BOLD);
4795 			else
4796 				wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD);
4797 				mvwaddch(tmpwin, 2, x+2,
4798 					(pan == 128 ? 'M' :
4799 					(pan == 0 || (pan > 0 && pan < 128)) ?
4800 					'L' :'R')
4801 			);
4802 		}
4803 
4804 		wattrset(tmpwin, A_NORMAL);
4805 		mvwprintw(tmpwin, AC_H-1, AC_W-18, "%s",
4806 			(real_volume ?  "[ Real volume  ]":"[ Voice volume ]")
4807 		);
4808 
4809 		if (mod && playing) {
4810 			refresh_info();
4811 			refresh_module_info();
4812 			MikMod_Update();
4813 
4814 			if (in_playlist) {
4815 				if (pl_cnt != lastmod) {
4816 					lastmod = pl_cnt;
4817 					goto CHN_CNT;
4818 				}
4819 			}
4820 		}
4821 
4822 		update_panels();
4823 		doupdate();
4824 	}
4825 
4826 	del_panel(acpan);
4827 	update_panels();
4828 	doupdate();
4829 }
4830 
4831 /*** Show all voices. ***/
show_all_voices(void)4832 static void show_all_voices(void)
4833 {
4834         int i;			/* counter */
4835 	int c;			/* character */
4836 	int x;			/* x position */
4837 	int step;		/* x step */
4838 	int add;		/* add to x */
4839         int pc;			/* percent */
4840 	int lastmod = 0;	/* for playlist checking */
4841 
4842 	unsigned char pan;	/* panning */
4843 	float vol1, vol2;	/* volume */
4844 
4845 	WINDOW *tmpwin;		/* channel window (temporary) */
4846 
4847 	/* Create window. */
4848 	acwin = tmpwin = newwin(AC_H+2, AC_W, AC_Y, AC_X);
4849 	wtimeout(tmpwin, DELAY);
4850 	keypad(tmpwin, TRUE);
4851 	box(tmpwin, 0, 0);
4852 	acpan = new_panel(tmpwin);
4853 	wattrset(tmpwin, (COLOR_PAIR(CYAN_BLUE)|A_BOLD));
4854 	mvwprintw(tmpwin, 0, 0, "%-68s", " All voices");
4855 
4856 	/* Calculate x step and add. */
4857 CHN_CNT:
4858 	step = 1;
4859 	add = 1;
4860 
4861 	/* Print voices counter. */
4862 	wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL);
4863 	for (i = 1; i < AC_H-1; i++)
4864 		mvwprintw(tmpwin, i, 1, "%66s", "");
4865 	wattrset(tmpwin, COLOR_PAIR(CYAN)|A_NORMAL);
4866 	for (c = 0; c < 64; c++) {
4867 		if (c == 0) {
4868 			mvwaddch(tmpwin, AC_H-2, 2, '|');
4869 			mvwprintw(tmpwin, AC_H-1, 2, "1");
4870 			continue;
4871 		}
4872 
4873 		if (!(c % 4)) {
4874 			mvwaddch(tmpwin, AC_H-2, (c * step) + add, '|');
4875 			mvwprintw(tmpwin, AC_H-1,
4876 				(c*step) + add, "%d", c);
4877 		}
4878 	}
4879 	mvwaddch(tmpwin, AC_H-2, (c * step) + add, '|');
4880 	mvwprintw(tmpwin, AC_H-1, (c * step) + add, "%d", c);
4881 
4882 	/*** Loop ***/
4883 	if (in_playlist)
4884 		lastmod = pl_cnt;
4885 	while ((c = wgetch(tmpwin)) != 'q') {
4886 		if (c == KEY_ESCAPE)
4887 			break;
4888 		else if (c == 'e')
4889 			effects();
4890 		else if (c == 'o')
4891 			options();
4892 		else if (c == 'u') {
4893 			real_volume = 1-real_volume;
4894 			refresh_legend();
4895 		} else if (c == 'm')
4896 			mp_move_panel(acpan);
4897 		else
4898 			module_control(c);
4899 
4900 		if (c == '*') {
4901 			if (gauge_style < 5)
4902 				gauge_style++;
4903 			else
4904 				gauge_style = 1;
4905 		}
4906 
4907 		/* Draw voices. */
4908 		for (x = 0, i = 0; i < 64; x += step, i++) {
4909 			if (real_volume) {
4910 				vol1 = get_voice_realvol(i);
4911 				vol2 = maxrvol[i];
4912 				if (vol2 <= 0) vol2=1;
4913 				pc = (int) (100.0 * (vol1 / vol2));
4914 				draw_gauge(tmpwin, x+2, AC_H-4,
4915 					pc, 0, gauge_style);
4916 
4917 			} else {
4918 				vol1 = get_voice_volume(i);
4919 				vol2 = maxvol[i];
4920 				if (vol2 <= 0) vol2 = 1;
4921 				pc = (int) (100.0 * (vol1 / vol2));
4922 				draw_gauge(tmpwin, x+2, AC_H-4,
4923 					pc, 0, gauge_style);
4924 			}
4925 
4926 			/* Volume. */
4927 			vol1 = get_voice_volume(i);
4928 			if (vol1 > 0)
4929 				wattrset(tmpwin, COLOR_PAIR(GREEN)|A_BOLD);
4930 			else
4931 				wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL);
4932 			if (vol1 >= 128 && vol1 < MODVOL_LIMIT)
4933 				wattrset(tmpwin, COLOR_PAIR(YELLOW)|A_BOLD);
4934 			else if (vol1 >= MODVOL_LIMIT)
4935 				wattrset(tmpwin, COLOR_PAIR(RED)|A_BOLD);
4936 			mvwaddch(tmpwin, AC_H-3, x+2, ACS_BLOCK);
4937 
4938 			/* Panning. */
4939 			pan = (unsigned char) get_voice_panning(i);
4940 			if (pan == 128)
4941 				wattrset(tmpwin, COLOR_PAIR(BLUE)|A_BOLD);
4942 			else if (pan == 0 || (pan > 0 && pan < 128))
4943 				wattrset(tmpwin, COLOR_PAIR(MAGENTA)|A_BOLD);
4944 			else
4945 				wattrset(tmpwin, COLOR_PAIR(CYAN)|A_BOLD);
4946 				mvwaddch(tmpwin, 2, x+2,
4947 					(pan == 128 ? 'M' :
4948 					(pan == 0 || (pan > 0 && pan < 128)) ?
4949 					'L' :'R')
4950 			);
4951 		}
4952 
4953 		wattrset(tmpwin, COLOR_PAIR(YELLOW_BLUE)|A_BOLD);
4954 		mvwprintw(tmpwin, 0, AC_W-14, "%s",
4955 			(real_volume ?  " Real volume ":" Voice volume ")
4956 		);
4957 
4958 		if (mod && playing) {
4959 			refresh_info();
4960 			refresh_module_info();
4961 			MikMod_Update();
4962 
4963 			if (in_playlist) {
4964 				if (pl_cnt != lastmod) {
4965 					lastmod = pl_cnt;
4966 					goto CHN_CNT;
4967 				}
4968 			}
4969 		}
4970 
4971 		update_panels();
4972 		doupdate();
4973 	}
4974 
4975 	del_panel(acpan);
4976 	update_panels();
4977 	doupdate();
4978 }
4979 /*** Enter tracks view. ***/
track_view(void)4980 void track_view(void)
4981 {
4982 	int c;
4983 	int i, j;
4984 	int opcode;
4985 	UBYTE *curtrk;
4986 	WINDOW *tmpwin;
4987 	PANEL *tmppan;
4988 
4989 	/* Create window. */
4990 	tmpwin = newwin(22, 70, 1, 4);
4991 	wtimeout(tmpwin, DELAY);
4992 	keypad(tmpwin, TRUE);
4993 	box(tmpwin, 0, 0);
4994 	tmppan = new_panel(tmpwin);
4995 
4996 	wattrset(tmpwin, (COLOR_PAIR(WHITE)|A_NORMAL));
4997 	mvwprintw(tmpwin, 0, 2, "[              ]");
4998 	wattrset(tmpwin, (COLOR_PAIR(YELLOW)|A_BOLD));
4999 	mvwprintw(tmpwin, 0, 4, "Pattern view");
5000 	wattrset(tmpwin, A_NORMAL);
5001 
5002 	/*** Loop ***/
5003 	while ((c = wgetch(tmpwin)) != 'q') {
5004 		if (c == 'p')
5005 			do_pause();
5006 
5007 		if (c == 'm')
5008 			mp_move_panel(tmppan);
5009 
5010 		for (j = 0; j < 4 /* mod->numtrk */; j++) {
5011 			curtrk = mod->tracks[j]; /* ptr to array of UBYTES */
5012 			for (i = 1; i < 21; i++) {
5013 				wattrset(tmpwin, COLOR_PAIR(CYAN)|A_NORMAL);
5014 				mvwprintw(tmpwin, i, 1, "%3d", mod->patpos+i);
5015 				if ((mod->patpos+i) > mod->numrow) {
5016 					mvwprintw(tmpwin, i, (j*8)+6, "----");
5017 					continue;
5018 				}
5019 				opcode = curtrk[(i+mod->patpos)+
5020 					(mod->sngpos*mod->numpos)];
5021 				wattrset(tmpwin, COLOR_PAIR(WHITE)|A_NORMAL);
5022 				if (opcode)
5023 					mvwprintw(tmpwin, i, (j*8)+6,
5024 						"%04x", opcode);
5025 				else
5026 					mvwprintw(tmpwin, i, (j*8)+6, "----");
5027 
5028 			}
5029 		}
5030 
5031 		if (mod && playing) {
5032 			refresh_info();
5033 			refresh_module_info();
5034 			update_panels();
5035 			doupdate();
5036 			MikMod_Update();
5037 		}
5038 	}
5039 
5040 	del_panel(tmppan);
5041 	delwin(tmpwin);
5042 }
5043 
5044 /*** Display module info. ***/
5045 int hidden = 1, hcnt = 0, hc[4] = { '-', '\\', '|', '/' }, pp = 0;
refresh_module_info(void)5046 static void refresh_module_info(void)
5047 {
5048 	int i;
5049 
5050 	if (mod->sngpos >= mod->numpos)
5051 		return;
5052 
5053 	wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD);
5054 	mvwprintw(dspwin, MODINFO_Y, 1, "Ch:");
5055 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5056 	wprintw(dspwin,  "%2d/%2d",
5057 			mod->realchn,
5058 			mod->numchn);
5059 
5060 	wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD);
5061 	mvwprintw(dspwin, MODINFO_Y, 11, "Pat:");
5062 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5063 	wprintw(dspwin,  "%3d %3d/%3d",
5064 		(mod->patterns[mod->sngpos]+1 > mod->numpos ?
5065 			mod->numpos : mod->patterns[mod->sngpos]+1),
5066 		(mod->sngpos+1 > mod->numpos ?
5067 			mod->numpos : mod->sngpos+1), mod->numpos);
5068 
5069 	wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD);
5070 	mvwprintw(dspwin, MODINFO_Y, 28, "Pos:");
5071 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5072 	wprintw(dspwin,  "%3d", mod->patpos);
5073 
5074 	wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD);
5075 	mvwprintw(dspwin, MODINFO_Y, 37, "Bpm:");
5076 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5077 	wprintw(dspwin,  "%3d", mod->bpm);
5078 
5079 	wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD);
5080 	mvwprintw(dspwin, MODINFO_Y, 46, "Spd:");
5081 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5082 	wprintw(dspwin,  "%3d", mod->sngspd);
5083 
5084 	wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD);
5085 	mvwprintw(dspwin, MODINFO_Y, 55, "Tmp:");
5086 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5087 	wprintw(dspwin,  "%3d", mod->inittempo);
5088 
5089 	wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD);
5090 	mvwprintw(dspwin, MODINFO_Y, 64, "Rvb:");
5091 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5092 	wprintw(dspwin,  "%2d", md_reverb);
5093 
5094 	wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD);
5095 	mvwprintw(dspwin, MODINFO_Y, 72, "Vol:");
5096 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5097 	wprintw(dspwin,  "%3d", mod->volume);
5098 
5099 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5100 	mvwprintw(dspwin, DSP_H-1, COLS-17, "[             ]");
5101 	wattrset(dspwin, COLOR_PAIR(CYAN)|A_BOLD);
5102 	mvwprintw(dspwin, DSP_H-1, COLS-15, "Time:");
5103 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5104 	mvwprintw(dspwin, DSP_H-1, COLS-9, "%02d:%02d",
5105 			((mod->sngtime/1000)/60),
5106 			((mod->sngtime/1000)%60));
5107 
5108 	if (in_playlist)
5109 		refresh_pl_info();
5110 	else if (need_to_clear) {
5111 		for (i = 1; i < 60; i++)
5112 			mvwaddch(dspwin, DSP_H-1, i, ACS_HLINE);
5113 		need_to_clear = 0;
5114 	}
5115 
5116 	if (!hidden && pp != mod->patpos) {
5117 		wattrset(dspwin, COLOR_PAIR(GREEN_BLUE)|A_BOLD);
5118 		mvwaddch(dspwin, 0,  1,  hc[(hcnt) & 3]);
5119 		mvwaddch(dspwin, 0,  2,  hc[(hcnt+1) & 3]);
5120 		mvwaddch(dspwin, 0,  9+strlen(VERSION), hc[(hcnt+2) & 3]);
5121 		mvwaddch(dspwin, 0, 10+strlen(VERSION), hc[(hcnt+3) & 3]);
5122 		hcnt++, pp = mod->patpos;
5123 		wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5124 	}
5125 }
5126 
5127 /*** Display channels info. ***/
refresh_info(void)5128 static void refresh_info(void)
5129 {
5130 	int i;
5131 	int vol = 0, pc;
5132 	int panc, panx;
5133 	int period;
5134 	float vol1, vol2;
5135 	float f1, f2;
5136 	unsigned char pan, vpan;
5137 	chtype attr;
5138 
5139 	if (mod == NULL) {
5140 		for (i = (page*(DSP_H-CHN_START));
5141 				i < ((page+1)*(DSP_H-CHN_START)); i++) {
5142 			int y = i%(DSP_H-CHN_START);
5143 
5144 			wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5145 			mvwprintw(dspwin, y+4, 1,
5146 				" %02d   %6d  %6d    %6d   %6d     %3d ",
5147 				y, 0, 0, 0, 0, 0);
5148 
5149 			draw_gauge(dspwin, 52, y+CHN_START-1,
5150 				0, 1, gauge_style);
5151 		}
5152 
5153 		return;
5154 	}
5155 
5156 	for (i = (page*(DSP_H-CHN_START));
5157 			i < ((page+1)*(DSP_H-CHN_START)); i++) {
5158 		int y = i%(DSP_H-CHN_START);
5159 
5160 		if (i > mod->numchn-1) {
5161 			if ((mod->sngpos == 0 && mod->patpos < 1)
5162 					|| lastpage < page)
5163 				mvwprintw(dspwin, y+CHN_START-1, 1, "%78s", "");
5164 			continue;
5165 		}
5166 
5167 		/* Print line. */
5168 		if (muted[i] == 0) {
5169 			period = get_channel_period(i);
5170 
5171 			/* Channel # */
5172 			if (period == 0)
5173 				vol = 0;
5174 			else
5175 				vol = get_voice_volume(get_channel_voice(i));
5176 			if (vol > 0) {
5177 				wattrset(dspwin,
5178 					(attr = COLOR_PAIR(CYAN_BLUE)|A_BOLD));
5179 			} else {
5180 				wattrset(dspwin,
5181 					(attr = COLOR_PAIR(WHITE)|A_NORMAL));
5182 			}
5183 			mvwprintw(dspwin, y+CHN_START-1, 1, "%02d", i+1);
5184 
5185 			/* Channel period. */
5186 			wattrset(dspwin,
5187 				(attr = COLOR_PAIR(WHITE)|A_NORMAL));
5188 			mvwprintw(dspwin, y+CHN_START-1, 5, "%6d", period);
5189 
5190 			/* Set line color from voice volume. */
5191 			if (period == 0) {
5192 				vol = 0;
5193 				wattrset(dspwin,
5194 					(attr = COLOR_PAIR(WHITE)|A_NORMAL));
5195 				goto NO_VOLCLR;
5196 			}
5197 			vol = get_voice_volume(get_channel_voice(i));
5198 			if (vol > 0 && vol < 64)
5199 				wattrset(dspwin,
5200 					(attr = COLOR_PAIR(GREEN)|A_NORMAL));
5201 			else if (vol > 64 && vol < 128)
5202 				wattrset(dspwin,
5203 					(attr = COLOR_PAIR(GREEN)|A_BOLD));
5204 			else if (vol >= 128 && vol < 192)
5205 				wattrset(dspwin,
5206 					(attr = COLOR_PAIR(YELLOW)|A_BOLD));
5207 			else if (vol >= 192 && vol < 256)
5208 				wattrset(dspwin,
5209 					(attr = COLOR_PAIR(RED)|A_BOLD));
5210 
5211 			else if (vol == 256)
5212 				wattrset(dspwin,
5213 					(attr = COLOR_PAIR(WHITE_RED)|A_BOLD));
5214 
5215 
5216 		NO_VOLCLR:
5217 			if (period != 0) {
5218 				mvwprintw(dspwin, y+CHN_START-1, 13,
5219 					"%2d  %6d  %6d",
5220 					(get_channel_voice(i)+1),
5221 					(get_voice_freq(get_channel_voice(i))),
5222 					(get_voice_pos(get_channel_voice(i))));
5223 
5224 			} else {
5225 				mvwprintw(dspwin, y+CHN_START-1, 13,
5226 					"%2d  %6d  %6d", 0, 0, 0);
5227 			}
5228 
5229 			/* Panning. */
5230 			pan = (unsigned char) get_voice_panning(
5231 					get_channel_voice(i));
5232 			if (period == 0)
5233 				pan = 128;
5234 			if (pan == 128) {
5235 				wattrset(dspwin,
5236 					COLOR_PAIR(BLUE)|A_BOLD);
5237 			} else if (pan == 0 || (pan > 0 && pan < 128))  {
5238 				wattrset(dspwin,
5239 					COLOR_PAIR(MAGENTA)|A_BOLD);
5240 			} else {
5241 				wattrset(dspwin,
5242 					COLOR_PAIR(CYAN)|A_BOLD);
5243 			}
5244 			mvwprintw(dspwin, y+CHN_START-1, 33, ".......");
5245 			if (pan == 0)  {
5246 				wattrset(dspwin,
5247 					COLOR_PAIR(MAGENTA_MAGENTA)|A_BOLD);
5248 			} else if (pan == 255) {
5249 				wattrset(dspwin,
5250 					COLOR_PAIR(CYAN_CYAN)|A_BOLD);
5251 			}
5252 
5253 			vpan = 0;
5254 			panx = 0;
5255 			panc =  (pan == 128 ? 'M' :
5256 			 	(pan == 0 ||
5257 				(pan > 0 && pan < 128) ? 'L' : 'R'));
5258 
5259 			if (panc == 'M') {
5260 				panx = 3;
5261 				vpan = 128;
5262 
5263 			} else if (panc == 'L') {
5264 				if (pan == 0) {
5265 					panx = 0;
5266 					vpan = 127;
5267 				} else if (pan == 127) {
5268 					panx = 2;
5269 					vpan = 0;
5270 				} else {
5271 					f1 = pan;
5272 					f2 = 100.0 * (f1 / 127.0);
5273 					f2 /= 33.0;
5274 					panx = f2;
5275 					vpan = 127 - pan;
5276 				}
5277 
5278 			} else if (panc == 'R') {
5279 				pan -= 128;
5280 				f1 = pan;
5281 				f2 = 100.0 * (f1 / 127.0);
5282 				f2 /= 33.0;
5283 
5284 				panx = f2;
5285 				if (panx > 2)
5286 					panx = 2;
5287 				panx += 4;
5288 
5289 				vpan = pan;
5290 			}
5291 			mvwaddch(dspwin, y+CHN_START-1, 33+panx, panc);
5292 
5293 			wattrset(dspwin, COLOR_PAIR(CYAN)|A_NORMAL);
5294 			mvwprintw(dspwin, y+CHN_START-1, 41, "%3d", vpan);
5295 
5296 			/* Volume. */
5297 			wattrset(dspwin, attr);
5298 			mvwprintw(dspwin, y+CHN_START-1, 46,
5299 				"%3d  %c", vol,
5300 				(lastvol[i] == vol ? '=' :
5301 				(lastvol[i] < vol ? '+' : '-')));
5302 				lastvol[i] = vol;
5303 
5304 			if (real_volume) {
5305 				if (period == 0) {
5306 					pc = 0;
5307 					goto NO_CALC;
5308 				}
5309 				vol1 = get_voice_realvol(
5310 						get_channel_voice(i));
5311 				vol2 = maxrvol[i];
5312 				if (vol2 <= 0) vol2 = 1;
5313 				pc = (int) (100.0 * (vol1 / vol2));
5314 				if (pc > 100) pc = 100;
5315 			NO_CALC:
5316 				draw_gauge(dspwin, 54, y+CHN_START-1,
5317 					pc, 1, gauge_style);
5318 
5319 			} else {
5320 				vol1 = vol;
5321 				vol2 = maxvol[i];
5322 				if (vol2 <= 0) vol2 = 1;
5323 				pc = (int) (100.0 * (vol1 / vol2));
5324 				draw_gauge(dspwin, 54, y+CHN_START-1,
5325 					pc, 1, gauge_style);
5326 			}
5327 
5328 		} else {
5329 			wattrset(dspwin, A_NORMAL);
5330 			mvwprintw(dspwin, y+CHN_START-1, 1,
5331 			"%02d  ------  --  ------ -------  ------- ---   MUTED",
5332 				i+1);
5333 			draw_gauge(dspwin, 54, y+CHN_START-1,
5334 				0, 1, gauge_style);
5335 		}
5336 	}
5337 
5338 	draw_pointer();
5339 }
5340 
5341 /*** Refresh driver info. ***/
refresh_driver_info(void)5342 static void refresh_driver_info(void)
5343 {
5344 	int i;
5345 
5346 	for (i = 1; i < COLS-1; i++)
5347 		mvwaddch(dspwin, 3, i, ' ');
5348 
5349 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_BOLD);
5350 	mvwprintw(dspwin, 3, 1, "Driver : ");
5351 	wattrset(dspwin, COLOR_PAIR(MAGENTA)|A_BOLD);
5352 	wprintw(dspwin, md_driver->Name);
5353 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5354 	wprintw(dspwin, " - ");
5355 
5356 	wattrset(dspwin, COLOR_PAIR(MAGENTA)|A_BOLD);
5357 	wprintw(dspwin, "%s %s %s %s %s",
5358 		(md_mode & DMODE_16BITS ? "16bit" : "8bit"),
5359 		(md_mode & DMODE_REVERSE ? "!STEREO" : \
5360 			(md_mode & DMODE_STEREO ? "STEREO" : "MONO" )),
5361 		(md_mode & DMODE_SURROUND ? "SURROUND" : "NORMAL" ),
5362 		(md_mode & DMODE_HQMIXER ? "HQMIXER" : "LQMIXER" ),
5363 		(md_mode & DMODE_SOFT_MUSIC ? "(soft)" : "(hard)"));
5364 
5365 	wattrset(dspwin, COLOR_PAIR(YELLOW)|A_BOLD);
5366 	wprintw(dspwin,  " %d Hz", md_mixfreq);
5367 
5368 	wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5369 }
5370 
5371 /*** Refresh legend bar. ***/
refresh_legend(void)5372 static void refresh_legend(void)
5373 {
5374 	if (real_volume) {
5375 		wattrset(dspwin, A_REVERSE);
5376 		mvwprintw(dspwin, CHN_START-2, 0, "%-80s",
5377 " Ch  Period  Vc    Freq     Pos    Panning    Volume       Real volume");
5378 	} else {
5379 		wattrset(dspwin, A_REVERSE);
5380 		mvwprintw(dspwin, CHN_START-2, 0, "%-80s",
5381 " Ch  Period  Vc    Freq     Pos    Panning    Volume      Voice volume");
5382 	}
5383 }
5384 
5385 /******************************************************************************/
5386 
5387 /*** Print the usual usage string. ***/
usage(void)5388 static void usage(void)
5389 {
5390 	fprintf(stderr, ":: MP v%s ::\n", VERSION);
5391 	fprintf(stderr, "Usage: mp [ -h | -v ]... [ module | playlist ]...\n");
5392 	fprintf(stderr, "  -h           help\n");
5393 	fprintf(stderr, "  -v           version\n");
5394 	fprintf(stderr, "  module       .xm, .it, .mod...\n");
5395 	fprintf(stderr, "  playlist     .pli\n");
5396 }
5397 
5398 /*** Main control keys. ***/
module_control(int c)5399 void module_control(int c)
5400 {
5401 	int i;
5402 
5403 	switch (c) {
5404 		/*
5405 		 * Next position.
5406 		 */
5407 		case 'n':
5408 			if (pos < mod->numpos-1) {
5409 				Player_NextPosition();
5410 				MikMod_Update();
5411 				pos = mod->sngpos;
5412 			}
5413 		break;
5414 
5415 		/*
5416 		 * Next module.
5417 		 */
5418 		case 'N':
5419 			if (in_playlist && pl_cnt < pl_files-1) {
5420 				if (random_mode) {
5421 					pl_cnt = (int)
5422 					(((float)pl_files-1)*(rand()/
5423 					(RAND_MAX+1.0)));
5424 				} else {
5425 					pl_cnt++;
5426 
5427 				}
5428 
5429 				pl_playtime += mod->sngtime;
5430 				Player_Stop();
5431 				loading(1);
5432 				play_module(
5433 					list_files[pl_cnt].fname);
5434 				loading(0);
5435 
5436 				refresh_pl_info();
5437 			}
5438 		break;
5439 
5440 		/*
5441 		 * Prev position.
5442 		 */
5443 		case 'v':
5444 			if (mod->sngpos > 0) {
5445 				mod->sngpos--;
5446 				MikMod_Update();
5447 				pos = mod->sngpos;
5448 			}
5449 		break;
5450 
5451 		/*
5452 		 * Prev module.
5453 		 */
5454 		case 'V':
5455 			if (in_playlist && pl_cnt > 0) {
5456 				pl_cnt--;
5457 
5458 				Player_Stop();
5459 
5460 				loading(1);
5461 				play_module(
5462 				    list_files[pl_cnt].fname);
5463 					loading(0);
5464 
5465 				refresh_pl_info();
5466 			}
5467 		break;
5468 
5469 		/*
5470 		 * Restart module.
5471 		 */
5472 		case 'A':
5473 			if (playing == 0)
5474 				playing = 1;
5475 
5476 			Player_SetPosition(0);
5477 			pos = 0;
5478 
5479 			if (stopped) {
5480 				stopped = 0;
5481 				Player_Start(mod);
5482 			}
5483 		break;
5484 
5485 		/*
5486 		 * Restart pattern.
5487 		 */
5488 		case 'a':
5489 			mod->patpos = 0;
5490 			MikMod_Update();
5491 		break;
5492 
5493 		/*
5494 		 * Playlist.
5495 		 */
5496 		case 'l':
5497 			playlist();
5498 
5499 			if (in_playlist && pl_files != 0
5500 					&& pl_val != 255) {
5501 				install_pl_handler();
5502 				pl_playtime = 0;
5503 
5504 				Player_Stop();
5505 				loading(1);
5506 				play_module(list_files[pl_cnt].fname);
5507 				loading(0);
5508 
5509 				refresh_pl_info();
5510 			}
5511 		break;
5512 
5513 		/* ;-) */
5514 		case KEY_F(12):
5515 			hidden = 1-hidden;
5516 			if (hidden) {
5517 				wattrset(dspwin, COLOR_PAIR(CYAN_BLUE)|A_BOLD);
5518 				mvwprintw(dspwin, 0, 0,
5519 					" :: MP v%s ::", VERSION);
5520 			}
5521 		break;
5522 
5523 		/*
5524 		 * Play or pause.
5525 		 */
5526 		case 'p':
5527 			if (stopped) {
5528 				if (mod) {
5529 					Player_Start(mod);
5530 					stopped = 0;
5531 					playing = 1;
5532 				}
5533 			} else {
5534 				do_pause();
5535 			}
5536 		break;
5537 
5538 		/*
5539 		 * Stop.
5540 		 */
5541 		case 't':
5542 			do_stop();
5543 		break;
5544 
5545 
5546 		/*
5547 		 * Reverb +/-
5548 		 */
5549 		case 'r':
5550 			if (md_reverb > 0)
5551 				md_reverb--;
5552 		break;
5553 		case 'R':
5554 			if (md_reverb < REVERB_LIMIT)
5555 				md_reverb++;
5556 		break;
5557 
5558 		/*
5559 		 * Speed +/-
5560 		 */
5561 		case 's':
5562 			if (mod->sngspd > 0)
5563 				mod->sngspd--;
5564 		break;
5565 		case 'S':
5566 			if (mod->sngspd < SPEED_LIMIT)
5567 				mod->sngspd++;
5568 		break;
5569 
5570 		/*
5571 		 * BPM +/-
5572 		 */
5573 		case 'b':
5574 			if (mod->bpm > 1)
5575 				mod->bpm--;
5576 		break;
5577 		case 'B':
5578 			if (mod->bpm < BPM_LIMIT)
5579 				mod->bpm++;
5580 		break;
5581 
5582 		/*
5583 		 * Tempo +/-
5584 		 */
5585 		case 'k':
5586 			if (mod->inittempo > 0)
5587 				mod->inittempo--;
5588 		break;
5589 		case 'K':
5590 			if (mod->inittempo < TEMPO_LIMIT)
5591 				mod->inittempo++;
5592 		break;
5593 
5594 		/*
5595 		 * Volume +/-
5596 		 */
5597 		case '+':
5598 			if (mod->volume < MODVOL_LIMIT)
5599 				mod->volume++;
5600 		break;
5601 		case '-':
5602 			if (mod->volume > 0)
5603 				mod->volume--;
5604 		break;
5605 
5606 		/*
5607 		 * Reverse stereo
5608 		 */
5609 		case '!':
5610 			if ((md_mode & DMODE_STEREO))
5611 				reverse_stereo = 1-reverse_stereo;
5612 			else
5613 				break;
5614 
5615 			if (!reverse_stereo) {
5616 				md_mode &= ~DMODE_REVERSE;
5617 			} else
5618 				md_mode |= DMODE_REVERSE;
5619 
5620 			refresh_driver_info();
5621 		break;
5622 
5623 		/*
5624 		 * Switch volume display.
5625 		 */
5626 		case 'u':
5627 			real_volume = 1-real_volume;
5628 			refresh_legend();
5629 		break;
5630 
5631 
5632 		/*
5633 		 * Mute all channels.
5634 		 */
5635 		case 'M':
5636 			for (i = 0; i < mod->numchn; i++) {
5637 				if (output == 1) {
5638 					muted[i] = 1;
5639 					Player_Mute(i);
5640 				} else {
5641 					muted[i] = 0;
5642 					Player_Unmute(i);
5643 				}
5644 			}
5645 			output = 1-output;
5646 			draw_pointer();
5647 		break;
5648 
5649 		/*
5650 		 * Module info.
5651 		 */
5652 		case 'i':
5653 			if (mod)
5654 				module_info(mod);
5655 		break;
5656 
5657 		/*
5658 		 * Help.
5659 		 */
5660 		case 'h': case 'H':
5661 			display_help();
5662 		break;
5663 
5664 		/*
5665 		 * About.
5666 		 */
5667 		case '?':
5668 			about();
5669 		break;
5670 
5671 	}
5672 }
5673 
5674 /******************************************************************************
5675  ***
5676  ***				Start here.
5677  ***
5678  ******************************************************************************/
5679 
main(int argc,char * argv[])5680 int main(int argc, char *argv[])
5681 {
5682 	/* Variables. */
5683 	int key;
5684 	struct stat sbuf;
5685 	char str[NAME_MAX+1];
5686 	char *modname;
5687 
5688 	/* If called without arguments. */
5689 	if (argv[1] == NULL) {
5690 		usage();
5691 		exit(-1);
5692 
5693 	/* Help? */
5694 	} else if (strncmp(argv[1], "-h", 2) == 0) {
5695 		usage();
5696 		exit(0);
5697 
5698 	/* Version? */
5699 	} else if (strncmp(argv[1], "-v", 2) == 0) {
5700 		fprintf(stderr, ":: MP v%s ::\n", VERSION);
5701 		exit(0);
5702 
5703 	/* Check file. */
5704 	} else if (access(argv[1], R_OK) != 0) {
5705 		fprintf(stderr, "MP: Can't open '%s'\n", argv[1]);
5706 		exit(-1);
5707 
5708 		stat(argv[1], &sbuf);
5709 		if (S_ISREG(sbuf.st_mode) == 0) {
5710 			fprintf(stderr, "MP: Can't open '%s'\n", argv[1]);
5711 			exit(-1);
5712 		}
5713 	}
5714 
5715 	/*
5716 	 * Check for presence of the '.mp' directory
5717 	 * in the user homedir.
5718 	 */
5719 	sprintf(str, "%s/.mp", (getenv("HOME")));
5720 	if (access(str, R_OK) != 0) {
5721 		fprintf(stderr, "MP: Can't access '%s', creating it.\n", str);
5722 		mkdir(str, 0644);
5723 	} else {
5724 		read_options_file();
5725 	}
5726 
5727 	/* Init sound. */
5728 	init_sound();
5729 
5730 	/* Init curses. */
5731 	init_nc();
5732 	read_options_file();
5733 	init_windows();
5734 	oldc1 = mvwinch(dspwin, curch+3, 0);
5735 	oldc2 = mvwinch(dspwin, curch+3, 3);
5736 	/*
5737 	 * Load module.
5738 	 */
5739 	if (argv[1] != NULL) {
5740 		loading(1);
5741 		if (play_module(argv[1])) {
5742 			leave(0);
5743 			usage();
5744 			exit(-1);
5745 		} else
5746 			playing = 1;
5747 		loading(0);
5748 
5749 	} else {
5750 		wattrset(dspwin, COLOR_PAIR(WHITE)|A_NORMAL);
5751 		mvwprintw(dspwin, 0, 1,
5752 			" No module loaded. Press 'f' for file selector. ");
5753 		playing = 0;
5754 	}
5755 
5756 	/* Create screen. */
5757 	refresh_driver_info();
5758 	refresh_info();
5759 	refresh_module_info();
5760 	doupdate();
5761 
5762 	/* Ensure we do a clean exit if those signals are received... */
5763 	signal(SIGTERM, leave);
5764         signal(SIGINT,  leave);
5765         signal(SIGUSR1, leave);
5766         signal(SIGUSR2, leave);
5767 
5768 	/*** Main loop ***/
5769 	while ((key = wgetch(dspwin)) != 'q') {
5770 		module_control(key);
5771 		switch (key) {
5772 			/*
5773 			 * Show all channels.
5774 			 */
5775 			case 'c': case 'C':
5776 				if (mod != NULL)
5777 					show_all_channels();
5778 				else
5779 					beep();
5780 			break;
5781 
5782 			/*
5783 			 * Show voices frequency.
5784 			 */
5785 			case 'y':
5786 				if (mod != NULL)
5787 					show_voices_freq();
5788 				else
5789 					beep();
5790 			break;
5791 
5792 			/*
5793 			 * Show voices position.
5794 			 */
5795 			case 'Y':
5796 				if (mod != NULL)
5797 					show_voices_pos();
5798 				else
5799 					beep();
5800 			break;
5801 
5802 			/*
5803 			 * Select file.
5804 			 */
5805 			case 'f':
5806 				modname = file_select();
5807 
5808 				touchwin(dspwin);
5809 				wnoutrefresh(dspwin);
5810 				doupdate();
5811 
5812 				if (modname != NULL && (strlen(modname)) > 0) {
5813 					loading(1);
5814 					if (!(play_module(full_modname))) {
5815 						in_playlist = 0;
5816 						need_to_clear = 1;
5817 					}
5818 					loading(0);
5819 
5820 					touchwin(dspwin);
5821 
5822 				}
5823 			break;
5824 
5825 			/*
5826 			 * Effects.
5827 			 */
5828 			case 'e':
5829 				effects();
5830 			break;
5831 
5832 			/*
5833 			 * Options.
5834 			 */
5835 			case 'o':
5836 				options();
5837 			break;
5838 
5839 			/*
5840 			 * Show samples.
5841 			 */
5842 			case 'w':
5843 				show_samples();
5844 			break;
5845 
5846 			/*
5847 			 * Show instruments.
5848 			 */
5849 			case 'W':
5850 				show_instruments();
5851 			break;
5852 
5853 			/*
5854 			 * Move up.
5855 			 */
5856 			case KEY_UP:
5857 				if (mod == NULL) break;
5858 				if (curch > 0) curch--;
5859 				page = (curch/(DSP_H-CHN_START));
5860 				draw_pointer();
5861 			break;
5862 			case KEY_PPAGE:
5863 				if (mod == NULL) break;
5864 				if (curch == 0) break;
5865 				if (curch == (page*(DSP_H-CHN_START))) {
5866 					curch = (--page*(DSP_H-CHN_START));
5867 					break;
5868 				}
5869 				curch = (page*(DSP_H-CHN_START));
5870 				draw_pointer();
5871 			break;
5872 
5873 			/*
5874 			 * Move down.
5875 			 */
5876 			case KEY_DOWN:
5877 				if (mod == NULL) break;
5878 				if (curch < mod->numchn-1) curch++;
5879 				page = (curch/(DSP_H-CHN_START));
5880 				draw_pointer();
5881 			break;
5882 			case KEY_NPAGE:
5883 				if (mod == NULL) break;
5884 				if (((page+1)*(DSP_H-CHN_START))
5885 						>= mod->numchn) {
5886 					curch = mod->numchn-1;
5887 					draw_pointer();
5888 					break;
5889 				}
5890 				curch = ((page+1)*(DSP_H-CHN_START));
5891 				page = (curch/(DSP_H-CHN_START));
5892 				draw_pointer();
5893 			break;
5894 
5895 			/*
5896 			 * Change gauge style.
5897 			 */
5898 			case '*':
5899 				if (gauge_style < 5)
5900 					gauge_style++;
5901 				else
5902 					gauge_style = 1;
5903 			break;
5904 
5905 
5906 			/*
5907 			 * Tracks view.
5908 			 */
5909 			case 'T':
5910 				//track_view();
5911 				show_all_voices();
5912 			break;
5913 
5914 			/*
5915 			 * Bass.
5916 			 */
5917 			case '<':
5918 				if (bass) {
5919 					bass--;
5920 					ioctl(mixerfd,
5921 						MIXER_WRITE(SOUND_MIXER_BASS),
5922 						&bass);
5923 				}
5924 			break;
5925 			case '>':
5926 				if (bass < BASS_LIMIT) {
5927 					bass++;
5928 					ioctl(mixerfd,
5929 						MIXER_WRITE(SOUND_MIXER_BASS),
5930 						&bass);
5931 				}
5932 			break;
5933 
5934 			/*
5935 			 * Treble.
5936 			 */
5937 			case 'x':
5938 				if (treble) {
5939 					treble--;
5940 					ioctl(mixerfd,
5941 						MIXER_WRITE(SOUND_MIXER_BASS),
5942 						&treble);
5943 				}
5944 			break;
5945 			case 'X':
5946 				if (treble < TREBLE_LIMIT) {
5947 					treble++;
5948 					ioctl(mixerfd,
5949 						MIXER_WRITE(SOUND_MIXER_BASS),
5950 						&treble);
5951 				}
5952 			break;
5953 
5954 			/*
5955 			 * Mute channel.
5956 			 */
5957 			case KEY_ENTER:
5958 				if (muted[curch]) {
5959 					muted[curch] = 0;
5960 					Player_Unmute(curch);
5961 					refresh_info();
5962 				} else {
5963 					muted[curch] = 1;
5964 					Player_Mute(curch);
5965 					refresh_info();
5966 				}
5967 				draw_pointer();
5968 			break;
5969 		}
5970 
5971 		if (mod && playing) {
5972 			refresh_info();
5973 			refresh_module_info();
5974 			update_panels();
5975 			doupdate();
5976 			MikMod_Update();
5977 		}
5978 	}
5979 
5980 	/* Leaving... */
5981 	in_playlist = 0;
5982 
5983 	/* End here. */
5984 	clear();
5985 	refresh();
5986 	leave(0);
5987 }
5988 
5989 /* EOF */
5990