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