1 /* vi:set ts=8 sts=8 sw=8 noexpandtab: */
3 /* welcome to gui.c, enjoy your stay 8-) */
22 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
24 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
27 static char *notenames
[] = {"C-", "C#", "D-", "D#", "E-", "F-", "F#",
28 "G-", "G#", "A-", "A#", "H-"};
30 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
31 \\\ local functions
.\
32 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
33 int _char2int(char ch
);
36 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
37 \\\ end local declarations
.\
38 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
40 char cmdstr
[500] = "";
43 int currmode
= PM_NORMAL
;
46 int tracklen
= TRACKLEN
;
58 // 0 is like a blank command
59 char *validcmds
= "0dfi@smtvw~+=*";
71 /* hexinc and hexdec wrap around */
73 return (x
>= 0 && x
<= 14)? x
+1 : 0;
76 return (x
>= 1 && x
<= 15)? x
-1 : 15;
79 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
80 \\\
< int _char2int(char) > .|
81 /// Draws the instrument editor. .\
82 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
83 int _char2int(char ch
){
90 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
91 \\\
< int freqkey(int) > .|
92 /// Calculates the frequency of key c. .\
93 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
98 if(c
== '-' || c
== KEY_DC
) return 0;
100 s
= strchr(keymap
[0], c
);
102 f
= (s
- (keymap
[0])) + octave
* 12 + 1;
104 s
= strchr(keymap
[1], c
);
106 f
= (s
- (keymap
[1])) + octave
* 12 + 12 + 1;
110 if(f
> 12 * 9 + 1) return -1;
114 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
115 \\\
< void initsonglines() > .|
117 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
118 void initsonglines(void){
119 for(int i
=0; i
< songlen
; i
++){
120 memmove(&song
[i
+ 0], &song
[i
+ 1], sizeof(struct songline
) * (songlen
- i
- 1));
122 song
[0].track
[i
] = 0x00;
123 song
[0].transp
[i
] = 0x00;
129 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
130 \\\
< void inittracks() > .\
131 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
132 void inittracks(void){
133 for(int i
=0; i
< 256; i
++){
134 for(int j
=0; j
< TRACKLEN
; j
++){
135 track
[i
].line
[j
].note
= 0x00;
136 track
[i
].line
[j
].instr
= 0x00;
137 for(int k
=0; k
< 2; k
++){
138 track
[i
].line
[j
].cmd
[k
] = 0x0000;
139 track
[i
].line
[j
].param
[k
] = 0x0000;
145 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
146 \\\
< void initinstrs() > .\
147 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
148 void initinstrs(void){
149 for(int i
=1; i
< 256; i
++){
150 instrument
[i
].length
= 1;
151 instrument
[i
].line
[0].cmd
= '0';
152 instrument
[i
].line
[0].param
= 0;
156 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
157 \\\
< void readsong(int,int,u8
) > .\
158 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
159 void readsong(int pos
, int ch
, u8
*dest
){
160 dest
[0] = song
[pos
].track
[ch
];
161 dest
[1] = song
[pos
].transp
[ch
];
164 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
165 \\\
< void readtrack(int,int,trackline
) > .\
166 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
167 void readtrack(int num
, int pos
, struct trackline
*tl
){
168 tl
->note
= track
[num
].line
[pos
].note
;
169 tl
->instr
= track
[num
].line
[pos
].instr
;
170 tl
->cmd
[0] = track
[num
].line
[pos
].cmd
[0];
171 tl
->cmd
[1] = track
[num
].line
[pos
].cmd
[1];
172 tl
->param
[0] = track
[num
].line
[pos
].param
[0];
173 tl
->param
[1] = track
[num
].line
[pos
].param
[1];
176 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
177 \\\
< void readinstr(int,int,u8
) > .\
178 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
179 void readinstr(int num
, int pos
, u8
*il
){
180 if(pos
>= instrument
[num
].length
){
184 il
[0] = instrument
[num
].line
[pos
].cmd
;
185 il
[1] = instrument
[num
].line
[pos
].param
;
189 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
190 \\\
< void exitgui() > .|
191 /// Exits the gui. .\
192 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
197 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
198 \\\
< void initgui() > .|
199 /// Initializes the gui. .\
200 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
204 //if(setlocale(LC_CTYPE,"en_US.utf8") != NULL){
205 // setdisplay("UTF-8 enabled!");
208 // don't send newline on Enter key, and don't echo chars to the screen.
212 // make sure behaviour for special keys like ^H isn't overridden
213 keypad(stdscr
, FALSE
);
215 nodelay(stdscr
, TRUE
);
222 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
223 \\\
< void handleinput() > .|
224 /// Main input loop. .\
225 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
226 void handleinput(void){
229 //if(currmode == PM_NORMAL){
230 if((c
= getch()) != ERR
){
236 cmdrepeatnum
= _char2int(c
);
238 cmdrepeatnum
= (cmdrepeatnum
*10) + _char2int(c
);
246 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
247 \\\
< char nextchar() > .|
248 /// Wait for the next keyboard char and return it. .\
249 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
261 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
262 \\\
< void setdisplay(char*) > .|
263 /// Sets a message to be popped up for a while. .\
264 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
265 void setdisplay(char *str
){
270 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
271 \\\
< void drawgui() > .|
272 /// Draw all text and graphix to the screen. .\
273 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
277 int songcols
[] = {0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22};
278 int trackcols
[] = {0, 2, 4, 5, 7, 8, 9, 11, 12, 13};
279 int instrcols
[] = {0, 2, 3};
283 attrset(A_UNDERLINE
);
284 mvaddstr(0, 0, "PINEAPPLEtRACKER");
288 mvaddch(0, 31, ACS_ULCORNER
);
289 snprintf(buf
, sizeof(buf
), "%02x{}", currtrack
);
290 mvaddstr(0, 32, buf
);
291 drawtracked(29, 1, lines
- 2);
293 // display instrument num
294 mvaddch(0, 51, ACS_ULCORNER
);
295 snprintf(buf
, sizeof(buf
), "%02x[]", currinstr
);
296 mvaddstr(0, 52, buf
);
297 drawinstred(49, 1, lines
- 2);
299 mvaddstr(1, 0, "Song");
300 drawsonged(0, 1, lines
- 2);
302 // just a wild guess here..
303 tempo
= callbacktime
* (-1) + 300;
305 mvaddch(0, 17, ACS_DEGREE
);
306 snprintf(buf
, sizeof(buf
), "%d()", tempo
);
307 mvaddstr(0, 18, buf
);
310 mvaddch(0, 24, ACS_PI
);
311 snprintf(buf
, sizeof(buf
), "%d<>", octave
);
312 mvaddstr(0, 25, buf
);
314 // display step amount
315 mvaddstr(0, 60, "step -=");
316 snprintf(buf
, sizeof(buf
), "%0x", step
);
317 mvaddstr(0, 68, buf
);
320 mvaddstr(2, 60, "comment:");
321 snprintf(buf
, sizeof(buf
), "%s", comment
);
322 mvaddstr(3, 60, buf
);
324 if(currmode
== PM_NORMAL
){
325 mvaddstr(getmaxy(stdscr
)-1, 0, filename
);
326 if(!saved
&& currmode
!= PM_INSERT
){
337 if(currmode
== PM_INSERT
){
340 move(getmaxy(stdscr
)-1,0);
342 mvaddstr(getmaxy(stdscr
)-1, 0, "-- INSERT --");
343 }else if(currmode
== PM_VISUAL
){
346 move(getmaxy(stdscr
)-1,0);
348 mvaddstr(getmaxy(stdscr
)-1, 0, "-- VISUAL --");
349 }else if(currmode
== PM_VISUALLINE
){
352 move(getmaxy(stdscr
)-1,0);
354 mvaddstr(getmaxy(stdscr
)-1, 0, "-- VISUAL LINE --");
355 }else if(currmode
== PM_JAMMER
){
358 move(getmaxy(stdscr
)-1,0);
360 mvaddstr(getmaxy(stdscr
)-1, 0, "-- JAMMER --");
361 }else if(currmode
== PM_CMDLINE
){
364 move(getmaxy(stdscr
)-1,0);
366 mvaddstr(getmaxy(stdscr
) - 1, 0, cmdstr
);
367 }else if(infinitemsg
!= NULL
){
368 move(getmaxy(stdscr
)-1,0);
370 mvaddstr(getmaxy(stdscr
) - 1, 0, infinitemsg
);
375 move(1 + songy
- songoffs
, 0 + 4 + songcols
[songx
]);
378 move(1 + tracky
- trackoffs
, 29 + 4 + trackcols
[trackx
]);
381 move(1 + instry
- instroffs
, 49 + 4 + instrcols
[instrx
]);
392 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
393 \\\
< void *spin_input(void *) > .|
394 /// Pass this function to a thread to get the next key without blocking the .\
396 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
397 /*void *spin_input(void *tid){
404 void *spin_gui(void *tid){
411 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
412 \\\
< void eventloop() > .|
413 /// Main event loop .\
414 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
415 void eventloop(void){
425 //--------------------------------------------------------------------------\\
426 // this is when i tried to make separate threads for the screen and the
428 //--------------------------------------------------------------------------//
429 //TODO: figure out a method where we don't have to use usleep()... the
430 // screen also jitters sometimes
431 /*void eventloop(void){
433 pthread_t inputthread;
437 // make it detached ... we won't need to join it
438 pthread_attr_init(&attr);
439 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
441 rc = pthread_create(&inputthread,&attr,spin_input,(void *)0);
443 setdisplay("Uh oh!!! thread please");
445 rc = pthread_create(&guithread,&attr,spin_gui,(void *)0);
448 // don't treat the escape key like a meta key
457 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
458 \\\ Internal functions
.\
459 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
461 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
462 \\\
< void _display() > .|
463 /// Display dispmesg in the center of the screen. .\
464 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
466 int cx
= (getmaxx(stdscr
)/2)-(strlen(dispmesg
)/2)-1;
467 int cy
= getmaxy(stdscr
)/2;
469 mvaddch(cy
-1, cx
, ACS_ULCORNER
);
470 for(int i
=cx
+1; i
<cx
+strlen(dispmesg
)+1; i
++)
471 mvaddch(cy
-1, i
, ACS_HLINE
);
472 mvaddch(cy
-1, cx
+strlen(dispmesg
)+1, ACS_URCORNER
);
474 mvaddch(cy
, cx
, ACS_VLINE
);
475 mvaddstr(cy
, cx
+1, dispmesg
);
476 mvaddch(cy
, cx
+strlen(dispmesg
)+1, ACS_VLINE
);
478 mvaddch(cy
+1, cx
, ACS_LLCORNER
);
479 for(int i
=cx
+1; i
<cx
+strlen(dispmesg
)+1; i
++)
480 mvaddch(cy
+1, i
, ACS_HLINE
);
481 mvaddch(cy
+1, cx
+strlen(dispmesg
)+1, ACS_LRCORNER
);
484 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
485 \\\
< void drawsonged(int,int,int) > .|
486 /// Draws the song editor. .\
487 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
488 void drawsonged(int x
, int y
, int height
){
493 if(songy
< songoffs
) songoffs
= songy
;
494 if(songy
>= songoffs
+ height
) songoffs
= songy
- height
+ 1;
496 for(i
= 0; i
< tune
->songlen
; i
++){
497 if(i
>= songoffs
&& i
- songoffs
< height
){
498 move(y
+ i
- songoffs
, x
+ 0);
499 if(i
== songy
) attrset(A_BOLD
);
501 snprintf(buf
, sizeof(buf
), "%02x", i
);
503 if(i
== 0){ addch(ACS_ULCORNER
); }
504 else if(i
== tune
->songlen
-1){ addch(ACS_LLCORNER
); }
505 else if(i
%4 == 0){ addch(ACS_LTEE
); }
506 else if(i
< tune
->songlen
-1){ addch(ACS_VLINE
); }
509 // should this line be highlighted?
510 //if( (match = list_contains(highlightlines, findu8, &i)) ){
511 if( currtab
== 0 && currmode
== PM_VISUALLINE
&&
512 ((i
<= highlight_firstline
&& i
>= highlight_lastline
)
513 || (i
>= highlight_firstline
&& i
<= highlight_lastline
)) ){
518 for(j
= 0; j
< 4; j
++){
519 snprintf(buf
, sizeof(buf
), "%02x:%02x", tune
->sng
[i
].track
[j
], tune
->sng
[i
].transp
[j
]);
521 if(j
!= 3) addch(' ');
523 if(playsong
&& tune
->songpos
== (i
+ 1)){
532 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
533 \\\
< void drawtracked(int,int,int) > .|
534 /// Draws the track editor. .\
535 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
536 void drawtracked(int x
, int y
, int height
){
540 if(tracky
< trackoffs
) trackoffs
= tracky
;
541 if(tracky
>= trackoffs
+ height
) trackoffs
= tracky
- height
+ 1;
543 for(i
= 0; i
< tune
->tracklen
; i
++){
544 if(i
>= trackoffs
&& i
- trackoffs
< height
){
545 move(y
+ i
- trackoffs
, x
+ 0);
546 if(i
== tracky
) attrset(A_BOLD
);
548 snprintf(buf
, sizeof(buf
), "%02x", i
);
551 if(i
== 0){ addch(ACS_LLCORNER
); }
552 else if(i
== 1){ addch(ACS_ULCORNER
); }
553 else if(i
== tune
->tracklen
-1){ addch(ACS_LLCORNER
); }
554 else if(i
%4 == 0){ addch(ACS_LTEE
); }
555 else if(i
< tune
->tracklen
-1){ addch(ACS_VLINE
); }
558 // should this line be highlighted?
559 //if( (match = list_contains(highlightlines, findu8, &i)) ){
560 if(currtab
== 1 && currmode
== PM_VISUALLINE
561 && ((i
<= highlight_firstline
&& i
>= highlight_lastline
)
562 || (i
>= highlight_firstline
&& i
<= highlight_lastline
)) ){
566 if (currtab
== 1 && currmode
== PM_VISUAL
)
569 if(tune
->trk
[currtrack
].line
[i
].note
){
570 snprintf(buf
, sizeof(buf
), "%s%d",
571 notenames
[(tune
->trk
[currtrack
].line
[i
].note
- 1) % 12],
572 (tune
->trk
[currtrack
].line
[i
].note
- 1) / 12);
574 snprintf(buf
, sizeof(buf
), "---");
577 snprintf(buf
, sizeof(buf
), " %02x", tune
->trk
[currtrack
].line
[i
].instr
);
579 for(j
= 0; j
< 2; j
++){
580 if(tune
->trk
[currtrack
].line
[i
].cmd
[j
]){
581 snprintf(buf
, sizeof(buf
), " %c%02x",
582 tune
->trk
[currtrack
].line
[i
].cmd
[j
],
583 tune
->trk
[currtrack
].line
[i
].param
[j
]);
585 snprintf(buf
, sizeof(buf
), " ...");
589 if(playtrack
&& ((i
+ 1) % tune
->tracklen
) == tune
->trackpos
){
598 //\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\/\\
599 \\\
< void drawinstred(int,int,int) > .|
600 /// Draws the instrument editor. .\
601 \\/\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\//
602 void drawinstred(int x
, int y
, int height
){
606 if(instry
>= instrument
[currinstr
].length
) instry
= instrument
[currinstr
].length
- 1;
608 if(instry
< instroffs
) instroffs
= instry
;
609 if(instry
>= instroffs
+ height
) instroffs
= instry
- height
+ 1;
611 for(i
= 0; i
< instrument
[currinstr
].length
; i
++){
612 if(i
>= instroffs
&& i
- instroffs
< height
){
613 move(y
+ i
- instroffs
, x
+ 0);
614 if(i
== instry
) attrset(A_BOLD
);
616 snprintf(buf
, sizeof(buf
), "%02x", i
);
619 if(i
== 0){ addch(ACS_LLCORNER
); }
620 else if(i
== 1){ addch(ACS_ULCORNER
); }
621 else if(i
== instrument
[currinstr
].length
-1){ addch(ACS_LLCORNER
); }
622 else if(i
< instrument
[currinstr
].length
-1){ addch(ACS_VLINE
); }
625 // should this line be highlighted?
626 //if( (match = list_contains(highlightlines, findu8, &i)) ){
627 if( currtab
== 2 && currmode
== PM_VISUALLINE
&&
628 ((i
<= highlight_firstline
&& i
>= highlight_lastline
)
629 || (i
>= highlight_firstline
&& i
<= highlight_lastline
)) ){
633 snprintf(buf
, sizeof(buf
), "%c ", instrument
[currinstr
].line
[i
].cmd
);
635 if(instrument
[currinstr
].line
[i
].cmd
== '+' || instrument
[currinstr
].line
[i
].cmd
== '='){
636 if(instrument
[currinstr
].line
[i
].param
){
637 snprintf(buf
, sizeof(buf
), "%s%d",
638 notenames
[(instrument
[currinstr
].line
[i
].param
- 1) % 12],
639 (instrument
[currinstr
].line
[i
].param
- 1) / 12);
641 snprintf(buf
, sizeof(buf
), "---");
644 snprintf(buf
, sizeof(buf
), "%02x", instrument
[currinstr
].line
[i
].param
);