1 /*
2     TiMidity++ -- MIDI to WAVE converter and player
3     Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4     Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 
20     motif_interface.c: written by Vincent Pagel (pagel@loria.fr) 10/4/95
21 
22     Policy : I choose to make a separate process for a TIMIDITY motif
23     interface for TIMIDITY (if the interface was in the same process
24     X redrawings would interfere with the audio computation. Besides
25     XtAppAddWorkProc mechanism is not easily controlable)
26 
27     The solution : I create a pipe between Timidity and the forked interface
28     and use XtAppAddInput to watch the data arriving on the pipe.
29 
30     10/4/95
31       - Initial working version with prev, next, and quit button and a
32         text display
33 
34     17/5/95
35       - Add timidity icon with filename displaying to play midi while
36         I work without having that big blue window in the corner of
37         my screen :)
38       - Solve the problem of concurent scale value modification
39 
40     21/5/95
41       - Add menus, file selection box
42 
43     14/6/95
44       - Make the visible part of file list follow the selection
45 
46    */
47 
48 #ifdef HAVE_CONFIG_H
49 #include "config.h"
50 #endif /* HAVE_CONFIG_H */
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <unistd.h>
54 #include <stdarg.h>
55 
56 #include <Xm/Xm.h>
57 #include <Xm/Form.h>
58 #include <Xm/Text.h>
59 #include <Xm/PushB.h>
60 #include <Xm/Label.h>
61 #include <Xm/Scale.h>
62 #include <Xm/List.h>
63 #include <Xm/Frame.h>
64 #include <Xm/RowColumn.h>
65 #include <Xm/CascadeB.h>
66 #include <Xm/FileSB.h>
67 #include <Xm/FileSB.h>
68 #include <Xm/ToggleB.h>
69 
70 #include "timidity.h"
71 #include "common.h"
72 #include "instrum.h"
73 #include "playmidi.h"
74 #include "output.h"
75 #include "controls.h"
76 #include "motif.h"
77 
78 static XtAppContext context;
79 static XmStringCharSet char_set=XmSTRING_DEFAULT_CHARSET;
80 
81 static Widget toplevel;
82 
83 static Widget text;
84 static XmTextPosition wpr_position=0;
85 
86 static Widget mainForm;
87 
88 static Widget menu_bar, open_option, quit_option, auto_next_option;
89 static Widget open_dialog , add_all_button;
90 
91 static Widget btnForm, backBtn,fwdBtn, restartBtn, pauseBtn, quitBtn,
92 	      nextBtn, prevBtn;
93 
94 static Pixmap backPixmap, fwdPixmap, pausePixmap , restartPixmap,
95 	      prevPixmap, nextPixmap, quitPixmap,
96 	      timidityPixmap;
97 
98 static Widget countFrame, countForm, counterlbl, totlbl , count_headlbl;
99 static int last_sec=0;
100 static int max_sec=0;
101 
102 static Widget file_namelbl, file_headlbl;
103 
104 static Widget volume_scale , locator_scale ;
105 static Boolean locator_scale_button= ButtonRelease;
106 
107 static Widget file_list;
108 static int file_number_to_play; /* Number of the file we're playing in the list */
109 
110 /*
111  * CREATE PIXMAPS FOR THE BUTONS
112  */
CreatePixmaps(Widget parent)113 static void CreatePixmaps(Widget parent)
114 {
115   /*
116    *
117    * BITMAPS
118    */
119 #include "motif_bitmaps/back.xbm"
120 #include "motif_bitmaps/next.xbm"
121 #include "motif_bitmaps/prev.xbm"
122 #include "motif_bitmaps/restart.xbm"
123 #include "motif_bitmaps/fwd.xbm"
124 #include "motif_bitmaps/pause.xbm"
125 #include "motif_bitmaps/quit.xbm"
126 #include "motif_bitmaps/timidity.xbm"
127 
128     Display *disp;
129     Drawable d;
130     Pixel fg,bg;
131     int ac;
132     Arg al[20];
133     unsigned int depth=DefaultDepthOfScreen(XtScreen(toplevel));
134 
135     ac = 0;
136     XtSetArg(al[ac], XmNbackground, &bg); ac++;
137     XtSetArg(al[ac], XmNforeground, &fg); ac++;
138     XtGetValues(parent, al, ac);
139 
140     disp=XtDisplay(toplevel);
141     d=RootWindowOfScreen(XtScreen(toplevel));
142 
143     backPixmap = XCreatePixmapFromBitmapData(disp, d,
144 					     back_bits, back_width, back_height,
145 					     fg, bg,depth);
146     fwdPixmap = XCreatePixmapFromBitmapData( disp, d,
147 					     fwd_bits, fwd_width, fwd_height,
148 					     fg, bg,depth);
149     pausePixmap = XCreatePixmapFromBitmapData(disp, d,
150 					pause_bits, pause_width, pause_height,
151 					fg, bg,depth);
152 
153     restartPixmap = XCreatePixmapFromBitmapData(disp, d,
154 					  restart_bits, restart_width, restart_height,
155 					  fg, bg,depth);
156 
157     nextPixmap  = XCreatePixmapFromBitmapData(disp, d,
158 					next_bits, next_width, next_height,
159 					fg, bg,depth);
160 
161     prevPixmap  = XCreatePixmapFromBitmapData(disp, d,
162 					prev_bits, prev_width, prev_height,
163 					fg, bg,depth);
164 
165     quitPixmap  = XCreatePixmapFromBitmapData(disp, d,
166 					quit_bits, quit_width, quit_height,
167 					fg, bg,depth);
168 
169     timidityPixmap  = XCreatePixmapFromBitmapData(disp, d,
170 						  timidity_bits, timidity_width, timidity_height,
171 						  WhitePixelOfScreen(XtScreen(toplevel)),
172 						  BlackPixelOfScreen(XtScreen(toplevel)),depth);
173 }
174 
175 
176 /************************************
177  *                                  *
178  * ALL THE INTERFACE'S CALLBACKS    *
179  *                                  *
180  ************************************/
181 
182 /*
183  * Generic buttons callbacks ( Transport Buttons )
184  */
185 /*ARGSUSED*/
GenericCB(Widget widget,int data,XtPointer call_data)186 static void  GenericCB(Widget widget, int data, XtPointer call_data)
187 {
188 
189 	if(data != MOTIF_QUIT && data != MOTIF_NEXT && data != MOTIF_PREV)
190 	{
191 		Arg al[10];
192 		int ac, nbfile;
193 
194 		ac=0;
195 		XtSetArg(al[ac], XmNitemCount, &nbfile); ac++;
196 		XtGetValues(file_list, al, ac);
197 		if(file_number_to_play==0||file_number_to_play>nbfile)
198 			return;
199 	}
200     m_pipe_int_write( data );
201 }
202 
203 /*
204  *  Generic scales callbacks : VOLUME and LOCATOR
205  */
206 /*ARGSUSED*/
Generic_scaleCB(Widget widget,int data,XtPointer call_data)207 static void Generic_scaleCB(Widget widget, int data, XtPointer call_data)
208 {
209     XmScaleCallbackStruct *cbs = (XmScaleCallbackStruct *) call_data;
210 
211 	if(data == MOTIF_CHANGE_LOCATOR)
212 	{
213 		Arg al[10];
214 		int ac, nbfile;
215 
216 		ac=0;
217 		XtSetArg(al[ac], XmNitemCount, &nbfile); ac++;
218 		XtGetValues(file_list, al, ac);
219 		if(file_number_to_play<=0||file_number_to_play>nbfile)
220 		{
221 			XmScaleSetValue(locator_scale,0);
222 			return;
223 		}
224 	}
225     m_pipe_int_write(  data );
226     m_pipe_int_write(cbs->value);
227 }
228 
229 /*
230  * Detect when a mouse button is pushed or released in a scale area to
231  * avoid concurent scale value modification while holding it with the mouse
232  */
233 /*ARGSUSED*/
Locator_btn(Widget w,XtPointer client_data,XEvent * event,Boolean * cont)234 static void Locator_btn(Widget w,XtPointer client_data,XEvent *event,Boolean *cont)
235 {
236     /* Type = ButtonPress or ButtonRelease */
237     locator_scale_button= event->xbutton.type;
238 }
239 
240 /*
241  * File List selection CALLBACK
242  */
243 /*ARGSUSED*/
File_ListCB(Widget widget,int data,XtPointer call_data)244 static void File_ListCB(Widget widget, int data, XtPointer call_data)
245 {
246     XmListCallbackStruct *cbs= (XmListCallbackStruct *) call_data;
247     char *text;
248     int nbvisible, first_visible ;
249     Arg al[10];
250     int ac;
251 
252     /* First, check that the selected file is really visible in the list */
253     ac=0;
254     XtSetArg(al[ac],XmNtopItemPosition,&first_visible); ac++;
255     XtSetArg(al[ac],XmNvisibleItemCount,&nbvisible); ac++;
256     XtGetValues(widget, al, ac);
257 
258     if ( ( first_visible > cbs->item_position) ||
259          ((first_visible+nbvisible) <= cbs->item_position))
260 	XmListSetPos(widget, cbs->item_position);
261 
262     /* Tell the application to play the requested file */
263     XmStringGetLtoR(cbs->item,char_set,&text);
264     m_pipe_int_write(MOTIF_PLAY_FILE);
265     m_pipe_string_write(text);
266     file_number_to_play=cbs->item_position;
267     XtFree(text);
268 }
269 
270 /*
271  * Generic menu callback
272  */
273 /*ARGSUSED*/
menuCB(Widget w,int client_data,XmAnyCallbackStruct * call_data)274 static void menuCB(Widget w,int client_data,XmAnyCallbackStruct *call_data)
275 {
276     switch (client_data)
277 	{
278 	case MENU_OPEN:
279 	{
280 	    XtManageChild(open_dialog);
281 	}
282 	break;
283 
284 	case MENU_QUIT : {
285 	    m_pipe_int_write(MOTIF_QUIT);
286 	}
287 	    break;
288 	case MENU_TOGGLE : {
289 	    /* Toggle modified : for the moment , nothing to do ! */
290 	    /* if (XmToggleButtonGetState(w)) TRUE else FALSE */
291 	    }
292 	    break;
293 	}
294 }
295 
296 /*
297  * File selection box callback
298  */
299 /*ARGSUSED*/
openCB(Widget w,int client_data,XmFileSelectionBoxCallbackStruct * call_data)300 static void openCB(Widget w,int client_data,XmFileSelectionBoxCallbackStruct *call_data)
301 {
302     if (client_data==DIALOG_CANCEL)
303 	{ /* do nothing if cancel is selected. */
304 	    XtUnmanageChild(open_dialog);
305 	    return;
306 	}
307     else if (client_data==DIALOG_ALL)
308 	{ /* Add all the listed files  */
309 	    Arg al[10];
310 	    int ac;
311 	    Widget the_list;
312 	    int nbfile;
313 	    XmStringTable files;
314 		char *text;
315 	    int i;
316 
317 	    the_list=XmFileSelectionBoxGetChild(open_dialog,XmDIALOG_LIST);
318 	    if (!XmIsList(the_list))
319 		{
320 		    fprintf(stderr, "PANIC: List are not what they used to be"
321 			    NLS);
322 		    exit(1);
323 		}
324 
325 	    ac=0;
326 	    XtSetArg(al[ac], XmNitemCount, &nbfile); ac++;
327 	    XtSetArg(al[ac], XmNitems, &files); ac++;
328 	    XtGetValues(the_list, al, ac);
329 
330 	    m_pipe_int_write(MOTIF_EXPAND);
331 	    m_pipe_int_write(nbfile);
332 	    for (i=0;i<nbfile;i++)
333 		{
334 			XmStringGetLtoR(files[i],char_set,&text);
335 			m_pipe_string_write(text);
336 			XtFree(text);
337 		}
338 	    XtUnmanageChild(open_dialog);
339 	}
340     else
341 	{   /* get filename from file selection box and add it to the list*/
342 		char *text;
343 
344 	    m_pipe_int_write(MOTIF_EXPAND);
345 	    m_pipe_int_write(1);
346 		XmStringGetLtoR(call_data->value,char_set,&text);
347 	    m_pipe_string_write(text);
348 		XtFree(text);
349 	    XtUnmanageChild(open_dialog);
350 	}
351 }
352 
353 
354 /********************************************************
355  *                                                      *
356  * Receive DATA sent by the application on the pipe     *
357  *                                                      *
358  ********************************************************/
359 /*ARGSUSED*/
handle_input(client_data,source,id)360 static void handle_input(client_data, source, id)
361     XtPointer client_data;
362     int *source;
363     XtInputId *id;
364 {
365     int message;
366 
367     m_pipe_int_read(&message);
368 
369     switch (message)
370 	{
371 	case REFRESH_MESSAGE : {
372 	    fprintf(stderr, "REFRESH MESSAGE IS OBSOLETE !!!" NLS);
373 	}
374 	    break;
375 
376 	case TOTALTIME_MESSAGE : {
377 	    int tseconds;
378 	    int minutes,seconds;
379 	    char local_string[20];
380 	    Arg al[10];
381 	    int ac;
382 
383 	    m_pipe_int_read(&tseconds);
384 
385 	    seconds=tseconds;
386 	    minutes=seconds/60;
387 	    seconds-=minutes*60;
388 	    sprintf(local_string,"/ %02d:%02d",minutes,seconds);
389 	    ac=0;
390 	    XtSetArg(al[ac], XmNlabelString,
391 		     XmStringCreate(local_string, char_set)); ac++;
392 	    XtSetValues(totlbl, al, ac);
393 
394 	    /* Readjust the time scale */
395 	    XmScaleSetValue(locator_scale,0);
396 	    ac=0;
397 	    XtSetArg(al[ac], XmNmaximum, tseconds); ac++;
398 	    XtSetValues(locator_scale, al, ac);
399 	    max_sec=tseconds;
400 	}
401 	    break;
402 
403 	case MASTERVOL_MESSAGE: {
404 	    int volume;
405 
406 	    m_pipe_int_read(&volume);
407 	    XmScaleSetValue(volume_scale,volume);
408 	}
409 	    break;
410 
411 	case FILENAME_MESSAGE : {
412 	    char filename[255], separator[255];
413 	    Arg al[10];
414 	    char *pc;
415 	    int ac, i;
416 	    short nbcol;
417 
418 	    m_pipe_string_read(filename);
419 
420 	    /* Extract basename of the file */
421 	    pc=strrchr(filename,'/');
422 	    if (pc==NULL)
423 		pc=filename;
424 	    else
425 		pc++;
426 
427 	    ac=0;
428 	    XtSetArg(al[ac], XmNlabelString,
429 		     XmStringCreate(pc, char_set)); ac++;
430 	    XtSetValues(file_namelbl, al, ac);
431 
432 	    /* Change the icon  */
433 	    ac=0;
434 	    XtSetArg(al[ac], XmNiconName,pc); ac++;
435 	    XtSetValues(toplevel,al,ac);
436 
437 	    /* Put a separator in the text Window */
438 	    ac=0;
439 	    nbcol=10;
440 	    XtSetArg(al[ac], XmNcolumns,&nbcol); ac++;
441 	    XtGetValues(text,al,ac);
442 
443 	    for (i=0;i<nbcol;i++)
444 		separator[i]='*';
445 	    separator[i]='\0';
446 
447 	    XmTextInsert(text,wpr_position, separator);
448 	    wpr_position+= strlen(separator);
449 	    XmTextInsert(text,wpr_position++,"\n");
450 	    XtVaSetValues(text,XmNcursorPosition, wpr_position,NULL);
451 	    XmTextShowPosition(text,wpr_position);
452 	}
453 	    break;
454 
455 	case FILE_LIST_MESSAGE : {
456 	    char filename[255];
457 	    int i, number_of_files;
458 	    XmString s;
459 
460 	    /* reset the playing list : play from the start */
461 	    file_number_to_play=0;
462 
463 	    m_pipe_int_read(&number_of_files);
464 
465 	    for (i=0;i<number_of_files;i++)
466 		{
467 		    m_pipe_string_read(filename);
468 		    s=XmStringCreate(filename,char_set);
469 		    XmListAddItemUnselected(file_list,s,0);
470 		    XmStringFree(s);
471 		}
472 	}
473 	    break;
474 
475 	case ERROR_MESSAGE :
476 	case NEXT_FILE_MESSAGE :
477 	case PREV_FILE_MESSAGE :
478 	case TUNE_END_MESSAGE :{
479 	    Arg al[10];
480 	    int ac;
481 	    int nbfile;
482 	    XmStringTable files;
483 
484 	    /* When a file ends, launch next if auto_next toggle */
485 	    if ((message==TUNE_END_MESSAGE) &&
486 		!XmToggleButtonGetState(auto_next_option))
487 		return;
488 
489 	    /* Total number of file to play in the list */
490 	    ac=0;
491 	    XtSetArg(al[ac], XmNitemCount, &nbfile); ac++;
492 	    XtGetValues(file_list, al, ac);
493 	    XmListDeselectAllItems(file_list);
494 
495 	    if (message==NEXT_FILE_MESSAGE||message==TUNE_END_MESSAGE)
496 		file_number_to_play++;
497 	    else if (message==PREV_FILE_MESSAGE)
498 		file_number_to_play--;
499 		else
500 		{
501 			ac=0;
502 			XtSetArg(al[ac], XmNitems, &files); ac++;
503 			XtGetValues(file_list, al, ac);
504 			XmListDeleteItem(file_list, files[file_number_to_play-1]);
505 			XmListSelectPos(file_list,file_number_to_play,TRUE);
506 			return;
507 		}
508 
509 	    /* Do nothing if requested file is before first one */
510 	    if (file_number_to_play<=0)
511 		{
512 			file_number_to_play=0;
513 			XmScaleSetValue(locator_scale,0);
514 		    return;
515 		}
516 
517 	    /* Stop after playing the last file */
518 	    if (file_number_to_play>nbfile)
519 		{
520 			file_number_to_play=nbfile+1;
521 			XmScaleSetValue(locator_scale,0);
522 		    return;
523 		}
524 
525 	    XmListSelectPos(file_list,file_number_to_play,TRUE);
526 	}
527 	    break;
528 
529 	case CURTIME_MESSAGE : {
530 	    int tseconds;
531 	    int  sec,seconds, minutes;
532 	    int nbvoice;
533 	    char local_string[20];
534 	    Arg al[10];
535 	    int ac;
536 
537 	    m_pipe_int_read(&tseconds);
538 	    m_pipe_int_read(&nbvoice);
539 
540 	    sec=seconds=tseconds;
541 
542 				/* To avoid blinking */
543 	    if (sec!=last_sec)
544 		{
545 		    minutes=seconds/60;
546 		    seconds-=minutes*60;
547 
548 		    sprintf(local_string,"%02d:%02d",
549 			    minutes, seconds);
550 
551 		    ac=0;
552 		    XtSetArg(al[ac], XmNlabelString,
553 			     XmStringCreate(local_string, char_set)); ac++;
554 		    XtSetValues(counterlbl, al, ac);
555 		}
556 
557 	    last_sec=sec;
558 
559 	    /* Readjust the time scale if not dragging the scale */
560 	    if ( (locator_scale_button==ButtonRelease) &&
561 		 (tseconds<max_sec))
562 		XmScaleSetValue(locator_scale, tseconds);
563 	}
564 	    break;
565 
566 	case NOTE_MESSAGE : {
567 	    int channel;
568 	    int note;
569 
570 	    m_pipe_int_read(&channel);
571 	    m_pipe_int_read(&note);
572 #ifdef DEBUG
573 	    fprintf(stderr, "NOTE chn%i %i\n",channel,note);
574 #endif /* DEBUG */
575 	}
576 	    break;
577 
578 	case    PROGRAM_MESSAGE :{
579 	    int channel;
580 	    int pgm;
581 
582 	    m_pipe_int_read(&channel);
583 	    m_pipe_int_read(&pgm);
584 #ifdef DEBUG
585 	    fprintf(stderr, "NOTE chn%i %i\n",channel,pgm);
586 #endif /* DEBUG */
587 	}
588 	    break;
589 
590 	case VOLUME_MESSAGE : {
591 	    int channel;
592 	    int volume;
593 
594 	    m_pipe_int_read(&channel);
595 	    m_pipe_int_read(&volume);
596 #ifdef DEBUG
597 	    fprintf(stderr, "VOLUME= chn%i %i \n",channel, volume);
598 #endif /* DEBUG */
599 	}
600 	    break;
601 
602 
603 	case EXPRESSION_MESSAGE : {
604 	    int channel;
605 	    int express;
606 
607 	    m_pipe_int_read(&channel);
608 	    m_pipe_int_read(&express);
609 #ifdef DEBUG
610 	    fprintf(stderr, "EXPRESSION= chn%i %i \n",channel, express);
611 #endif /* DEBUG */
612 	}
613 	    break;
614 
615 	case PANNING_MESSAGE : {
616 	    int channel;
617 	    int pan;
618 
619 	    m_pipe_int_read(&channel);
620 	    m_pipe_int_read(&pan);
621 #ifdef DEBUG
622 	    fprintf(stderr, "PANNING= chn%i %i \n",channel, pan);
623 #endif /* DEBUG */
624 	}
625 	    break;
626 
627 	case  SUSTAIN_MESSAGE : {
628 	    int channel;
629 	    int sust;
630 
631 	    m_pipe_int_read(&channel);
632 	    m_pipe_int_read(&sust);
633 #ifdef DEBUG
634 	    fprintf(stderr, "SUSTAIN= chn%i %i \n",channel, sust);
635 #endif /* DEBUG */
636 	}
637 	    break;
638 
639 	case  PITCH_MESSAGE : {
640 	    int channel;
641 	    int bend;
642 
643 	    m_pipe_int_read(&channel);
644 	    m_pipe_int_read(&bend);
645 #ifdef DEBUG
646 	    fprintf(stderr, "PITCH BEND= chn%i %i \n",channel, bend);
647 #endif /* DEBUG */
648 	}
649 	    break;
650 
651 	case RESET_MESSAGE : {
652 #ifdef DEBUG
653 	    fprintf(stderr, "RESET_MESSAGE\n");
654 #endif /* DEBUG */
655 	}
656 	    break;
657 
658 	case CLOSE_MESSAGE : {
659 #ifdef DEBUG
660 	    fprintf(stderr, "CLOSE_MESSAGE\n");
661 #endif /* DEBUG */
662 	    exit(0);
663 	}
664 	    break;
665 
666 	case CMSG_MESSAGE : {
667 	    int type;
668 	    char message[1000];
669 
670 	    m_pipe_int_read(&type);
671 	    m_pipe_string_read(message);
672 
673 	    XmTextInsert(text,wpr_position, message);
674 	    wpr_position+= strlen(message);
675 	    XmTextInsert(text,wpr_position++, "\n");
676 	    XtVaSetValues(text,XmNcursorPosition, wpr_position,NULL);
677 	    XmTextShowPosition(text,wpr_position);
678 	}
679 	    break;
680 	case LYRIC_MESSAGE : {
681 	    char message[1000];
682 
683 	    m_pipe_string_read(message);
684 
685 	    XmTextInsert(text, wpr_position, message);
686 	    wpr_position += strlen(message);
687 	    XtVaSetValues(text,XmNcursorPosition, wpr_position,NULL);
688 	    XmTextShowPosition(text,wpr_position);
689 	    XmTextInsert(text,wpr_position, ""); /* Update cursor */
690 	}
691 	    break;
692 	default:
693 	    fprintf(stderr,"UNKNOW MOTIF MESSAGE %i" NLS, message);
694 	}
695 
696 }
697 
698 /* ***************************************
699  *                                       *
700  * Convenience function to create menus  *
701  *                                       *
702  *****************************************/
703 
704 /* adds an accelerator to a menu option. */
add_accelerator(Widget w,char * acc_text,char * key)705 static void add_accelerator(Widget w,char *acc_text,char *key)
706 {
707     int ac;
708     Arg al[10];
709 
710     ac=0;
711     XtSetArg(al[ac],XmNacceleratorText,
712 	     XmStringCreate(acc_text,char_set)); ac++;
713     XtSetArg(al[ac],XmNaccelerator,key); ac++;
714     XtSetValues(w,al,ac);
715 }
716 
717 /* Adds a toggle option to an existing menu. */
make_menu_toggle(char * item_name,int client_data,Widget menu)718 static Widget make_menu_toggle(char *item_name, int client_data, Widget menu)
719 {
720     int ac;
721     Arg al[10];
722     Widget item;
723 
724     ac = 0;
725     XtSetArg(al[ac],XmNlabelString, XmStringCreateLtoR(item_name,
726 						       char_set)); ac++;
727     item=XmCreateToggleButton(menu,item_name,al,ac);
728     XtManageChild(item);
729     XtAddCallback(item, XmNvalueChangedCallback,
730 		  (XtCallbackProc) menuCB,(XtPointer) client_data);
731     XtSetSensitive(item, True);
732     return(item);
733 }
734 
735 /* Adds an option to an existing menu. */
make_menu_option(char * option_name,KeySym mnemonic,int client_data,Widget menu)736 static Widget make_menu_option(char *option_name, KeySym mnemonic,
737 			       int client_data, Widget menu)
738 {
739     int ac;
740     Arg al[10];
741     Widget b;
742 
743     ac = 0;
744     XtSetArg(al[ac], XmNlabelString,
745 	     XmStringCreateLtoR(option_name, char_set)); ac++;
746     XtSetArg (al[ac], XmNmnemonic, mnemonic); ac++;
747     b=XtCreateManagedWidget(option_name,xmPushButtonWidgetClass,
748 			    menu,al,ac);
749     XtAddCallback (b, XmNactivateCallback,
750 		   (XtCallbackProc) menuCB, (XtPointer) client_data);
751     return(b);
752 }
753 
754 /* Creates a new menu on the menu bar. */
make_menu(char * menu_name,KeySym mnemonic,Widget menu_bar)755 static Widget make_menu(char *menu_name,KeySym  mnemonic, Widget menu_bar)
756 {
757     int ac;
758     Arg al[10];
759     Widget menu, cascade;
760 
761     ac = 0;
762     menu = XmCreatePulldownMenu (menu_bar, menu_name, al, ac);
763 
764     ac = 0;
765     XtSetArg (al[ac], XmNsubMenuId, menu); ac++;
766     XtSetArg (al[ac], XmNmnemonic, mnemonic); ac++;
767     XtSetArg(al[ac], XmNlabelString,
768         XmStringCreateLtoR(menu_name, char_set)); ac++;
769     cascade = XmCreateCascadeButton (menu_bar, menu_name, al, ac);
770     XtManageChild (cascade);
771 
772     return(menu);
773 }
774 
775 /* *******************************************
776  *                                           *
777  * Interface initialisation before launching *
778  *                                           *
779  *********************************************/
780 
create_menus(Widget menu_bar)781 static void create_menus(Widget menu_bar)
782 {
783     Widget menu;
784 
785     menu=make_menu("File",'F',menu_bar);
786     open_option = make_menu_option("Open", 'O', MENU_OPEN, menu);
787     add_accelerator(open_option, "meta+o", "Meta<Key>o:");
788 
789     quit_option = make_menu_option("Exit", 'E', MENU_QUIT, menu);
790     add_accelerator(quit_option, "meta+q", "Meta<Key>q:");
791 
792     menu=make_menu("Options",'O',menu_bar);
793     auto_next_option= make_menu_toggle("Auto Next", MENU_TOGGLE, menu);
794     XmToggleButtonSetState( auto_next_option , True , False );
795 }
796 
create_dialog_boxes(void)797 static void create_dialog_boxes(void)
798 {
799     Arg al[10];
800     int ac;
801     XmString add_all = XmStringCreateLocalized("ADD ALL");
802 
803     /* create the file selection box used by MENU_OPEN */
804     ac=0;
805     XtSetArg(al[ac],XmNmustMatch,True); ac++;
806     XtSetArg(al[ac],XmNautoUnmanage,False); ac++;
807     XtSetArg(al[ac],XmNdialogTitle,
808 	     XmStringCreateLtoR("TIMIDITY: Open",char_set)); ac++;
809     open_dialog=XmCreateFileSelectionDialog(toplevel,"open_dialog",al,ac);
810     XtAddCallback(open_dialog, XmNokCallback,
811 		  (XtCallbackProc) openCB, (XtPointer) DIALOG_OK);
812     XtAddCallback(open_dialog, XmNcancelCallback,
813 		  (XtCallbackProc) openCB, (XtPointer) DIALOG_CANCEL);
814     XtUnmanageChild(XmFileSelectionBoxGetChild(open_dialog, XmDIALOG_HELP_BUTTON));
815 
816     ac = 0;
817     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
818     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
819     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
820     XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
821     XtSetArg(al[ac], XmNlabelString, add_all); ac++;
822     add_all_button = XmCreatePushButton(open_dialog, "add_all",al, ac);
823     XtManageChild(add_all_button);
824     XtAddCallback(add_all_button, XmNactivateCallback,
825 		  (XtCallbackProc) openCB, (XtPointer) DIALOG_ALL);
826 }
827 
Launch_Motif_Process(int pipe_number)828 void Launch_Motif_Process(int pipe_number)
829 {
830     Arg al[20];
831     int ac;
832     int argc=0;
833 
834     XtSetLanguageProc(NULL,NULL,NULL); /* By KINOSHITA, K. <kino@krhm.jvc-victor.co.jp> */
835 
836     /* create the toplevel shell */
837     toplevel = XtAppInitialize(&context,"timidity",NULL,0,&argc,NULL,
838 			       NULL,NULL,0);
839 
840     /*******************/
841     /* Main form       */
842     /*******************/
843     ac=0;
844     XtSetArg(al[ac],XmNtopAttachment,XmATTACH_FORM); ac++;
845     XtSetArg(al[ac],XmNbottomAttachment,XmATTACH_FORM); ac++;
846     XtSetArg(al[ac],XmNrightAttachment,XmATTACH_FORM); ac++;
847     XtSetArg(al[ac],XmNleftAttachment,XmATTACH_FORM); ac++;
848 
849     mainForm=XmCreateForm(toplevel,"form",al,ac);
850     XtManageChild(mainForm);
851 
852     CreatePixmaps(mainForm);
853 
854 
855     /* create a menu bar and attach it to the form. */
856     ac=0;
857     XtSetArg(al[ac], XmNtopAttachment,   XmATTACH_FORM); ac++;
858     XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
859     XtSetArg(al[ac], XmNleftAttachment,  XmATTACH_FORM); ac++;
860     menu_bar=XmCreateMenuBar(mainForm,"menu_bar",al,ac);
861     XtManageChild(menu_bar);
862 
863     create_dialog_boxes();
864     create_menus(menu_bar);
865 
866     /*******************/
867     /* Message window  */
868     /*******************/
869 
870     ac=0;
871     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
872     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
873     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
874     XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
875     XtSetArg(al[ac],XmNtopAttachment,XmATTACH_WIDGET); ac++;
876     XtSetArg(al[ac],XmNtopWidget, menu_bar); ac++;
877     XtSetArg(al[ac],XmNrightAttachment,XmATTACH_FORM); ac++;
878     XtSetArg(al[ac],XmNleftAttachment,XmATTACH_FORM); ac++;
879     XtSetArg(al[ac],XmNeditMode,XmMULTI_LINE_EDIT); ac++;
880     XtSetArg(al[ac],XmNrows,10); ac++;
881     XtSetArg(al[ac],XmNcolumns,10); ac++;
882     XtSetArg(al[ac],XmNeditable, False); ac++;
883     XtSetArg(al[ac],XmNwordWrap, True); ac++;
884     XtSetArg(al[ac],XmNvalue, "TIMIDIY RUNNING...\n"); ac++;
885     wpr_position+= strlen("TIMIDIY RUNNING...\n");
886 
887     text=XmCreateScrolledText(mainForm,"text",al,ac);
888     XtManageChild(text);
889 
890     /********************/
891     /* File_name label  */
892     /********************/
893     ac = 0;
894     XtSetArg(al[ac], XmNleftOffset, 20); ac++;
895     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
896     XtSetArg(al[ac], XmNtopOffset, 20); ac++;
897     XtSetArg(al[ac], XmNbottomOffset, 20); ac++;
898     XtSetArg(al[ac], XmNlabelType, XmSTRING); ac++;
899     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
900     XtSetArg(al[ac], XmNtopWidget, text); ac++;
901     XtSetArg(al[ac], XmNleftAttachment,XmATTACH_FORM); ac++;
902     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
903     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
904     XtSetArg(al[ac], XmNalignment,XmALIGNMENT_END); ac++;
905     XtSetArg(al[ac], XmNlabelString,
906 	     XmStringCreate("Playing:",char_set)); ac++;
907     file_headlbl = XmCreateLabel(mainForm,"fileheadlbl",al,ac);
908     XtManageChild(file_headlbl);
909 
910 
911     ac = 0;
912     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
913     XtSetArg(al[ac], XmNtopOffset, 20); ac++;
914     XtSetArg(al[ac], XmNbottomOffset, 20); ac++;
915     XtSetArg(al[ac], XmNlabelType, XmSTRING); ac++;
916     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
917     XtSetArg(al[ac], XmNtopWidget, text); ac++;
918     XtSetArg(al[ac], XmNleftAttachment,XmATTACH_WIDGET); ac++;
919     XtSetArg(al[ac], XmNleftWidget,file_headlbl); ac++;
920     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
921     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
922     XtSetArg(al[ac], XmNalignment,XmALIGNMENT_BEGINNING); ac++;
923     XtSetArg(al[ac], XmNlabelString,
924 	     XmStringCreate("NONE           ",char_set)); ac++;
925     file_namelbl = XmCreateLabel(mainForm,"filenameLbl",al,ac);
926     XtManageChild(file_namelbl);
927 
928     /*****************************/
929     /* TIME LABELS IN A FORM     */
930     /*****************************/
931 
932     /* Counters frame    */
933     ac=0;
934     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
935     XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
936     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
937     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
938     XtSetArg(al[ac],XmNtopAttachment,XmATTACH_WIDGET); ac++;
939     XtSetArg(al[ac],XmNtopWidget,text); ac++;
940     XtSetArg(al[ac],XmNrightAttachment,XmATTACH_FORM); ac++;
941     /*
942       XtSetArg(al[ac],XmNleftAttachment,XmATTACH_WIDGET); ac++;
943       XtSetArg(al[ac],XmNleftWidget,file_namelbl); ac++;
944       */
945     XtSetArg(al[ac],XmNshadowType,XmSHADOW_OUT); ac++;
946     countFrame=XmCreateFrame(mainForm,"countframe",al,ac);
947     XtManageChild(countFrame);
948 
949     /* Counters form       */
950     ac=0;
951     XtSetArg(al[ac],XmNtopAttachment,XmATTACH_FORM); ac++;
952     XtSetArg(al[ac],XmNbottomAttachment,XmATTACH_FORM); ac++;
953     XtSetArg(al[ac],XmNrightAttachment,XmATTACH_FORM); ac++;
954     XtSetArg(al[ac],XmNleftAttachment,XmATTACH_FORM); ac++;
955     XtSetArg(al[ac],XmNleftAttachment,XmATTACH_FORM); ac++;
956 
957     countForm=XmCreateForm(countFrame,"countform",al,ac);
958     XtManageChild(countForm);
959 
960     /* HEADER label       */
961     ac = 0;
962     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
963     XtSetArg(al[ac], XmNlabelType, XmSTRING); ac++;
964     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
965     XtSetArg(al[ac], XmNleftAttachment,XmATTACH_FORM); ac++;
966     XtSetArg(al[ac], XmNrightAttachment,XmATTACH_FORM); ac++;
967     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
968     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
969     XtSetArg(al[ac], XmNlabelString,
970 	     XmStringCreate("Time:",char_set)); ac++;
971     count_headlbl = XmCreateLabel(countForm,"countheadLbl",al,ac);
972     XtManageChild(count_headlbl);
973 
974     /* current Time label       */
975     ac = 0;
976     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
977     XtSetArg(al[ac], XmNtopWidget, count_headlbl); ac++;
978     XtSetArg(al[ac], XmNleftAttachment,XmATTACH_FORM); ac++;
979     XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM); ac++;
980     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
981     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
982     XtSetArg(al[ac], XmNalignment,XmALIGNMENT_END); ac++;
983     XtSetArg(al[ac], XmNlabelString,
984 	     XmStringCreate("00:00",char_set)); ac++;
985     counterlbl = XmCreateLabel(countForm,"counterLbl",al,ac);
986     XtManageChild(counterlbl);
987 
988     /* Total time label */
989 
990     ac = 0;
991     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
992     XtSetArg(al[ac], XmNtopWidget, count_headlbl); ac++;
993     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
994     XtSetArg(al[ac], XmNleftWidget, counterlbl); ac++;
995     XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
996     XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM); ac++;
997     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
998     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
999     XtSetArg(al[ac], XmNalignment,XmALIGNMENT_BEGINNING); ac++;
1000     XtSetArg(al[ac], XmNlabelString,
1001 	     XmStringCreate("/ 00:00",char_set)); ac++;
1002     totlbl = XmCreateLabel(countForm,"TotalTimeLbl",al,ac);
1003     XtManageChild(totlbl);
1004 
1005     /******************/
1006     /* Locator Scale  */
1007     /******************/
1008     {	/*
1009 	 * We need to add an xevent manager for buton pressing since
1010 	 * locator_scale is a critical ressource that can be modified
1011 	 * by shared by the handle input function
1012 	 */
1013 
1014 	WidgetList WList;
1015 	Cardinal Card;
1016 
1017 	ac = 0;
1018 	XtSetArg(al[ac], XmNleftOffset, 10); ac++;
1019 	XtSetArg(al[ac], XmNrightOffset, 10); ac++;
1020 	XtSetArg(al[ac], XmNtopOffset, 10); ac++;
1021 	XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
1022 	XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
1023 	XtSetArg(al[ac], XmNtopWidget, countForm); ac++;
1024 	XtSetArg(al[ac], XmNleftAttachment,XmATTACH_FORM); ac++;
1025 	XtSetArg(al[ac], XmNrightAttachment,XmATTACH_FORM); ac++;
1026 	XtSetArg(al[ac], XmNmaximum, 100); ac++;
1027 	XtSetArg(al[ac], XmNminimum, 0); ac++;
1028 	XtSetArg(al[ac], XmNshowValue, True); ac++;
1029 	XtSetArg(al[ac], XmNdecimalPoints, 0); ac++;
1030 	XtSetArg(al[ac], XmNorientation, XmHORIZONTAL); ac++;
1031 	XtSetArg(al[ac], XmNtraversalOn, False); ac++;
1032 	XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
1033 	locator_scale = XmCreateScale(mainForm,"locator",al,ac);
1034 	XtManageChild(locator_scale);
1035 	XtAddCallback(locator_scale,XmNvalueChangedCallback,
1036 		      (XtCallbackProc) Generic_scaleCB,
1037 		      (XtPointer) MOTIF_CHANGE_LOCATOR);
1038 
1039 	/* Reach the scrollbar child in the scale  */
1040 	ac = 0;
1041 	XtSetArg(al[ac], XtNchildren, &WList); ac++;
1042 	XtSetArg(al[ac], XtNnumChildren, &Card); ac++;
1043 	XtGetValues(locator_scale,al,ac);
1044 	if ((Card!=2)||
1045 	    strcmp(XtName(WList[1]),"Scrollbar"))
1046 	    fprintf(stderr,"PANIC: Scale has be redefined.. may cause bugs\n");
1047 
1048  	XtAddEventHandler(WList[1],ButtonPressMask|ButtonReleaseMask,
1049 			  FALSE,Locator_btn,NULL);
1050     }
1051 
1052     /*****************************/
1053     /* Control buttons in a form */
1054     /*****************************/
1055 
1056     /* create form for the row of control buttons */
1057     ac = 0;
1058     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
1059     XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
1060     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
1061 /*    XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++; */
1062     XtSetArg(al[ac],XmNtopAttachment,XmATTACH_WIDGET); ac++;
1063     XtSetArg(al[ac], XmNtopWidget, locator_scale); ac++;
1064     btnForm = XmCreateForm(mainForm,"btnForm", al, ac);
1065     XtManageChild(btnForm);
1066 
1067     /* Previous Button */
1068     ac = 0;
1069     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1070     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
1071     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
1072     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
1073     XtSetArg(al[ac], XmNshadowThickness, 2); ac++;
1074     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
1075     XtSetArg(al[ac], XmNlabelPixmap, prevPixmap); ac++;
1076     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
1077     prevBtn = XmCreatePushButton(btnForm, "previous",al, ac);
1078     XtManageChild(prevBtn);
1079     XtAddCallback(prevBtn, XmNactivateCallback,
1080 		  (XtCallbackProc) GenericCB, (XtPointer) MOTIF_PREV);
1081 
1082 
1083     /* Backward Button */
1084     ac = 0;
1085     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1086     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
1087     XtSetArg(al[ac], XmNleftWidget, prevBtn); ac++;
1088     XtSetArg(al[ac], XmNleftOffset, 2); ac++;
1089     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
1090     XtSetArg(al[ac], XmNshadowThickness, 2); ac++;
1091     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
1092     XtSetArg(al[ac], XmNlabelPixmap, backPixmap); ac++;
1093     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
1094     backBtn = XmCreatePushButton(btnForm, "backward",al, ac);
1095     XtManageChild(backBtn);
1096     XtAddCallback(backBtn, XmNactivateCallback,
1097 		  (XtCallbackProc) GenericCB, (XtPointer) MOTIF_RWD);
1098 
1099     /* Restart Button */
1100     ac = 0;
1101     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1102     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
1103     XtSetArg(al[ac], XmNleftWidget, backBtn); ac++;
1104     XtSetArg(al[ac], XmNleftOffset, 2); ac++;
1105     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
1106     XtSetArg(al[ac], XmNshadowThickness, 2); ac++;
1107     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
1108     XtSetArg(al[ac], XmNlabelPixmap, restartPixmap); ac++;
1109     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
1110     restartBtn = XmCreatePushButton(btnForm,"restartBtn", al, ac);
1111     XtManageChild(restartBtn);
1112     XtAddCallback(restartBtn, XmNactivateCallback,
1113 		  (XtCallbackProc) GenericCB, (XtPointer) MOTIF_RESTART);
1114 
1115     /* Quit Button */
1116     ac = 0;
1117     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1118     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
1119     XtSetArg(al[ac], XmNleftWidget, restartBtn); ac++;
1120     XtSetArg(al[ac], XmNleftOffset, 2); ac++;
1121     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
1122     XtSetArg(al[ac], XmNshadowThickness, 2); ac++;
1123     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
1124     XtSetArg(al[ac], XmNlabelPixmap, quitPixmap); ac++;
1125     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
1126     quitBtn = XmCreatePushButton(btnForm,"quitBtn", al, ac);
1127     XtManageChild(quitBtn);
1128     XtAddCallback(quitBtn, XmNactivateCallback,
1129 		  (XtCallbackProc) GenericCB, (XtPointer) MOTIF_QUIT);
1130 
1131     /* Pause Button */
1132 
1133     ac = 0;
1134     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1135     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
1136     XtSetArg(al[ac], XmNleftWidget, quitBtn); ac++;
1137     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
1138     XtSetArg(al[ac], XmNshadowThickness, 2); ac++;
1139     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
1140     XtSetArg(al[ac], XmNlabelPixmap, pausePixmap); ac++;
1141     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
1142     pauseBtn =  XmCreatePushButton(btnForm,"pauseBtn", al, ac);
1143     XtManageChild(pauseBtn);
1144     XtAddCallback(pauseBtn, XmNactivateCallback,
1145 		  (XtCallbackProc) GenericCB,(XtPointer) MOTIF_PAUSE);
1146 
1147     /* Forward Button */
1148 
1149     ac = 0;
1150     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1151     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
1152     XtSetArg(al[ac], XmNleftWidget,pauseBtn); ac++;
1153     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
1154     XtSetArg(al[ac], XmNshadowThickness, 2); ac++;
1155     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
1156     XtSetArg(al[ac], XmNlabelPixmap, fwdPixmap); ac++;
1157     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
1158     fwdBtn =  XmCreatePushButton(btnForm,"fwdBtn", al, ac);
1159     XtManageChild(fwdBtn);
1160     XtAddCallback(fwdBtn, XmNactivateCallback,
1161 		  (XtCallbackProc) GenericCB, (XtPointer) MOTIF_FWD);
1162 
1163     /* Next Button */
1164     ac = 0;
1165     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
1166     XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
1167     XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
1168     XtSetArg(al[ac], XmNleftWidget, fwdBtn); ac++;
1169     XtSetArg(al[ac], XmNleftOffset, 2); ac++;
1170     XtSetArg(al[ac], XmNshadowType, XmSHADOW_OUT); ac++;
1171     XtSetArg(al[ac], XmNshadowThickness, 2); ac++;
1172     XtSetArg(al[ac], XmNlabelType, XmPIXMAP); ac++;
1173     XtSetArg(al[ac], XmNlabelPixmap, nextPixmap); ac++;
1174     XtSetArg(al[ac], XmNhighlightThickness, 2); ac++;
1175     nextBtn = XmCreatePushButton(btnForm,"nextBtn", al, ac);
1176     XtManageChild(nextBtn);
1177     XtAddCallback(nextBtn, XmNactivateCallback,
1178 		  (XtCallbackProc) GenericCB, (XtPointer) MOTIF_NEXT);
1179 
1180     /********************/
1181     /* Volume scale     */
1182     /********************/
1183     ac = 0;
1184     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
1185     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
1186     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
1187     XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
1188     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
1189     XtSetArg(al[ac], XmNtopWidget, btnForm); ac++;
1190     XtSetArg(al[ac], XmNleftAttachment,XmATTACH_FORM); ac++;
1191     XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM); ac++;
1192 
1193     XtSetArg(al[ac], XmNmaximum, MAX_AMPLIFICATION); ac++;
1194     XtSetArg(al[ac], XmNminimum, 0); ac++;
1195     XtSetArg(al[ac], XmNshowValue, True); ac++;
1196 
1197     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
1198     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
1199     XtSetArg(al[ac], XmNtitleString,
1200 	     XmStringCreate("VOL",char_set)); ac++;
1201     volume_scale = XmCreateScale(mainForm,"volscale",al,ac);
1202     XtManageChild(volume_scale);
1203     XtAddCallback(volume_scale, XmNvalueChangedCallback,
1204 		  (XtCallbackProc) Generic_scaleCB,
1205 		  (XtPointer) MOTIF_CHANGE_VOLUME);
1206 
1207 
1208     /********************/
1209     /* File list        */
1210     /********************/
1211 
1212     ac = 0;
1213     XtSetArg(al[ac], XmNtopOffset, 10); ac++;
1214     XtSetArg(al[ac], XmNbottomOffset, 10); ac++;
1215     XtSetArg(al[ac], XmNleftOffset, 10); ac++;
1216     XtSetArg(al[ac], XmNrightOffset, 10); ac++;
1217     XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
1218     XtSetArg(al[ac], XmNtopWidget, btnForm ); ac++;
1219     XtSetArg(al[ac], XmNleftAttachment,XmATTACH_WIDGET); ac++;
1220     XtSetArg(al[ac], XmNleftWidget, volume_scale); ac++;
1221     XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
1222     XtSetArg(al[ac], XmNbottomAttachment,XmATTACH_FORM); ac++;
1223 
1224     XtSetArg(al[ac], XmNselectionPolicy ,XmSINGLE_SELECT); ac++;
1225     XtSetArg(al[ac], XmNscrollBarDisplayPolicy ,XmAS_NEEDED); ac++;
1226     XtSetArg(al[ac], XmNlistSizePolicy ,XmRESIZE_IF_POSSIBLE); ac++;
1227 
1228     XtSetArg(al[ac], XmNtraversalOn, False); ac++;
1229     XtSetArg(al[ac], XmNhighlightThickness,0); ac++;
1230 
1231     file_list = XmCreateScrolledList(mainForm,"File List",al,ac);
1232     XtManageChild(file_list);
1233     XtAddCallback(file_list, XmNsingleSelectionCallback,
1234 		  (XtCallbackProc) File_ListCB,
1235 		  NULL);
1236 
1237     /*
1238      * Last details on toplevel
1239      */
1240     ac=0;
1241     /*
1242       XtSetArg(al[ac],XmNwidth,400); ac++;
1243       XtSetArg(al[ac],XmNheight,800); ac++;
1244       */
1245     XtSetArg(al[ac], XmNtitle, "TiMidity"); ac++;
1246     XtSetArg(al[ac], XmNiconName, "NONE"); ac++;
1247     XtSetArg(al[ac], XmNiconPixmap, timidityPixmap); ac++;
1248     XtSetValues(toplevel,al,ac);
1249 
1250 
1251   /*******************************************************/
1252   /* Plug the pipe ..... and heeere we go                */
1253   /*******************************************************/
1254 
1255     XtAppAddInput(context,pipe_number,
1256 		  (XtPointer) XtInputReadMask,handle_input,NULL);
1257 
1258     XtRealizeWidget(toplevel);
1259     XtAppMainLoop(context);
1260 }
1261