1 /*
2 * xmmix - Motif(tm) Audio Mixer
3 *
4 * Copyright (C) 1994-1996 Ti Kan
5 * E-mail: ti@amb.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22 #ifndef LINT
23 static char *_widget_c_ident_ = "@(#)widget.c 3.3 96/07/14";
24 #endif
25
26 #include "appenv.h"
27 #include "widget.h"
28 #include "mixer.h"
29 #include "xmmix.xbm"
30
31
32 extern appdata_t app_data;
33 extern widgets_t widgets;
34 extern int maxdevs;
35
36 #define CTL_DISTANCE 48
37
38
39 #define PD_FILE_LOAD 0
40 #define PD_FILE_SAVE 1
41 #define PD_FILE_SEP 2
42 #define PD_FILE_EXIT 3
43
44 STATIC btinfo_t file_btinfo[] = {
45 { NULL, "Load...", "loadButton", "l", "L" },
46 { NULL, "Save...", "saveButton", "s", "S" },
47 { NULL, NULL, "fileSeparator", NULL, NULL },
48 { NULL, "Exit", "exitButton", "x", "x" },
49 { NULL, NULL, NULL, NULL, NULL },
50 };
51
52 #define PD_OPTS_RESET 0
53
54 STATIC btinfo_t options_btinfo[] = {
55 { NULL, "Reset", "resetButton", "r", "R" },
56 { NULL, NULL, NULL, NULL, NULL },
57 };
58
59 #define PD_HELP_MANPG 0
60 #define PD_HELP_ABOUT 1
61
62 STATIC btinfo_t help_btinfo[] = {
63 { NULL, "Man page...", "manPageButton", "m", "M" },
64 { NULL, "About...", "aboutButton", "a", "A" },
65 { NULL, NULL, NULL, NULL, NULL },
66 };
67
68 STATIC pdinfo_t file_pd = {
69 NULL, "File", "file", "f", "F", file_btinfo
70 };
71
72 STATIC pdinfo_t opts_pd = {
73 NULL, "Options", "options", "o", "O", options_btinfo
74 };
75
76 STATIC pdinfo_t help_pd = {
77 NULL, "Help", "help", "h", "H", help_btinfo
78 };
79
80 STATIC slinfo_t slinfo[] = {
81 { /* 0 */
82 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
83 "Master", "master", CTL_OUTPUT, 17, TRUE, FALSE
84 },
85 { /* 1 */
86 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
87 "Bass", "bass", CTL_MISC, 10, TRUE, FALSE
88 },
89 { /* 2 */
90 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
91 "Treble", "treble", CTL_MISC, 11, TRUE, FALSE
92 },
93 { /* 3 */
94 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
95 "Synth", "synth", CTL_INPUT, 1, TRUE, TRUE
96 },
97 { /* 4 */
98 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
99 "PCM", "pcm", CTL_INPUT, 2, TRUE, TRUE
100 },
101 { /* 5 */
102 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
103 "Speaker", "speaker", CTL_OUTPUT, 16, TRUE, FALSE
104 },
105 { /* 6 */
106 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
107 "Line", "line", CTL_INPUT, 4, TRUE, TRUE
108 },
109 { /* 7 */
110 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
111 "Mic", "mic", CTL_INPUT, 8, TRUE, TRUE
112 },
113 { /* 8 */
114 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
115 "CD", "cd", CTL_INPUT, 9, TRUE, TRUE
116 },
117 { /* 9 */
118 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
119 "Rec Mon", "recmon", CTL_OUTPUT, 12, TRUE, FALSE
120 },
121 { /* 10 */
122 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
123 "Alt PCM", "altpcm", CTL_INPUT, 3, TRUE, TRUE
124 },
125 { /* 11 */
126 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
127 "Rec Out", "recout", CTL_OUTPUT, 13, TRUE, FALSE
128 },
129 { /* 12 */
130 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
131 "In Gain", "igain", CTL_MISC, 14, TRUE, FALSE
132 },
133 { /* 13 */
134 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
135 "Out Gain", "ogain", CTL_MISC, 15, TRUE, FALSE
136 },
137 { /* 14 */
138 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
139 "Line-1", "line1", CTL_INPUT, 5, TRUE, TRUE
140 },
141 { /* 15 */
142 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
143 "Line-2", "line2", CTL_INPUT, 6, TRUE, TRUE
144 },
145 { /* 16 */
146 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
147 "Line-3", "line3", CTL_INPUT, 7, TRUE, TRUE
148 },
149 { /* 17 */
150 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
151 NULL, NULL, 0, 0, FALSE, FALSE
152 },
153 { /* 18 */
154 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
155 NULL, NULL, 0, 0, FALSE, FALSE
156 },
157 { /* 19 */
158 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
159 NULL, NULL, 0, 0, FALSE, FALSE
160 },
161 { /* 20 */
162 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
163 NULL, NULL, 0, 0, FALSE, FALSE
164 },
165 { /* 21 */
166 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
167 NULL, NULL, 0, 0, FALSE, FALSE
168 },
169 { /* 22 */
170 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
171 NULL, NULL, 0, 0, FALSE, FALSE
172 },
173 { /* 23 */
174 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
175 NULL, NULL, 0, 0, FALSE, FALSE
176 },
177 { /* 24 */
178 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
179 NULL, NULL, 0, 0, FALSE, FALSE
180 },
181 { /* 25 */
182 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
183 NULL, NULL, 0, 0, FALSE, FALSE
184 },
185 { /* 26 */
186 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
187 NULL, NULL, 0, 0, FALSE, FALSE
188 },
189 { /* 27 */
190 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
191 NULL, NULL, 0, 0, FALSE, FALSE
192 },
193 { /* 28 */
194 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
195 NULL, NULL, 0, 0, FALSE, FALSE
196 },
197 { /* 29 */
198 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
199 NULL, NULL, 0, 0, FALSE, FALSE
200 },
201 { /* 30 */
202 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
203 NULL, NULL, 0, 0, FALSE, FALSE
204 },
205 { /* 31 */
206 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
207 NULL, NULL, 0, 0, FALSE, FALSE
208 }
209 };
210
211 STATIC XmString xs_lock,
212 xs_rec,
213 xs_left,
214 xs_right;
215
216 STATIC Atom delw;
217
218
219 /***********************
220 * internal routines *
221 ***********************/
222
223 /*
224 * Widget-related functions
225 */
226
227 /*
228 * create_pdmnu
229 * Create a pulldown menu
230 *
231 * Args:
232 * parent - The parent widget
233 * pd - The pulldown menu info structure
234 *
235 * Return:
236 * The menu widget
237 */
238 STATIC Widget
create_pdmnu(Widget parent,pdinfo_t * pd)239 create_pdmnu(Widget parent, pdinfo_t *pd)
240 {
241 int i,
242 n;
243 Arg arg[10];
244 XmString xs;
245 XmString xs_acc;
246 char wname[STR_BUF_SZ];
247 Widget ret_widget;
248
249 /* Create File pulldown menu */
250 sprintf(wname, "%sMenu", pd->name);
251 ret_widget = XmCreatePulldownMenu(parent, wname, NULL, 0);
252
253 for (i = 0; pd->btip[i].name != NULL; i++) {
254 n = 0;
255 if (pd->btip[i].label == NULL) {
256 /* Separator */
257 pd->btip[i].widget = XmCreateSeparator(
258 ret_widget, pd->btip[i].name, NULL, 0
259 );
260 XtManageChild(pd->btip[i].widget);
261 }
262 else {
263 /* Button */
264 if (pd->btip[i].label != NULL) {
265 xs = XmStringCreateSimple(pd->btip[i].label);
266 XtSetArg(arg[n], XmNlabelString, xs); n++;
267 }
268
269 if (pd->btip[i].acc != NULL) {
270 xs_acc = XmStringCreateSimple(pd->btip[i].acc);
271 XtSetArg(arg[n], XmNaccelerator, xs_acc); n++;
272 }
273
274 if (pd->btip[i].mne != NULL) {
275 XtSetArg(arg[n], XmNmnemonic,
276 XStringToKeysym(pd->btip[i].mne)); n++;
277 }
278
279 pd->btip[i].widget = XmCreatePushButton(
280 ret_widget, pd->btip[i].name, arg, n
281 );
282 XtManageChild(pd->btip[i].widget);
283
284 if (pd->btip[i].label != NULL)
285 XmStringFree(xs);
286 if (pd->btip[i].acc != NULL)
287 XmStringFree(xs_acc);
288 }
289 }
290
291 /* Create cascade button as menu activator */
292 sprintf(wname, "%sButton", pd->name);
293
294 n = 0;
295 if (pd->label != NULL) {
296 xs = XmStringCreateSimple(pd->label);
297 XtSetArg(arg[n], XmNlabelString, xs); n++;
298 }
299 if (pd->acc != NULL) {
300 xs_acc = XmStringCreateSimple(pd->acc);
301 XtSetArg(arg[n], XmNaccelerator, xs_acc); n++;
302 }
303 if (pd->mne != NULL) {
304 XtSetArg(arg[n], XmNmnemonic, XStringToKeysym(pd->mne)); n++;
305 }
306
307 XtSetArg(arg[n], XmNsubMenuId, ret_widget); n++;
308 pd->widget = XmCreateCascadeButton(parent, wname, arg, n);
309 XtManageChild(pd->widget);
310
311 if (pd->label != NULL)
312 XmStringFree(xs);
313 if (pd->acc != NULL)
314 XmStringFree(xs_acc);
315
316 return (ret_widget);
317 }
318
319
320 /*
321 * create_vert_controls
322 * Create a group of mixer controls including the vertical slider
323 * and associated toggle buttons and labels.
324 *
325 * Args:
326 * m - Pointer to the main widgets structure
327 * dev - The mixer control device index
328 * y1 - The top reference position (percent)
329 * y2 - The bottom reference position (percent)
330 * pos - The display position number
331 * tot - Total number of controls to be displayed
332 *
333 * Return:
334 * Nothing
335 */
336 STATIC void
create_vert_controls(widgets_t * m,int dev,int y1,int y2,int pos,int tot)337 create_vert_controls(widgets_t *m, int dev, int y1, int y2, int pos, int tot)
338 {
339 int x,
340 n;
341 Arg arg[20];
342 char wname[STR_BUF_SZ];
343 XmString xs;
344
345 x = CTL_DISTANCE * pos;
346
347 /* Right slider */
348 sprintf(wname, "%sRightScale", slinfo[dev].name);
349 n = 0;
350 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
351 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_NONE); n++;
352 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
353 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
354 XtSetArg(arg[n], XmNleftOffset, x); n++;
355 XtSetArg(arg[n], XmNtopPosition, y1); n++;
356 XtSetArg(arg[n], XmNbottomPosition, y2); n++;
357 XtSetArg(arg[n], XmNshowValue, False); n++;
358 XtSetArg(arg[n], XmNorientation, XmVERTICAL); n++;
359 XtSetArg(arg[n], XmNprocessingDirection, XmMAX_ON_TOP); n++;
360 XtSetArg(arg[n], XmNminimum, 0); n++;
361 XtSetArg(arg[n], XmNmaximum, 100); n++;
362 XtSetArg(arg[n], XmNhighlightOnEnter, True); n++;
363 slinfo[dev].widget_r = XmCreateScale(m->form, wname, arg, n);
364 XtManageChild(slinfo[dev].widget_r);
365
366 /* Left slider */
367 sprintf(wname, "%sLeftScale", slinfo[dev].name);
368 n = 0;
369 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_NONE); n++;
370 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
371 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
372 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
373 XtSetArg(arg[n], XmNrightWidget, slinfo[dev].widget_r); n++;
374 XtSetArg(arg[n], XmNtopPosition, y1); n++;
375 XtSetArg(arg[n], XmNbottomPosition, y2); n++;
376 XtSetArg(arg[n], XmNshowValue, False); n++;
377 XtSetArg(arg[n], XmNorientation, XmVERTICAL); n++;
378 XtSetArg(arg[n], XmNprocessingDirection, XmMAX_ON_TOP); n++;
379 XtSetArg(arg[n], XmNminimum, 0); n++;
380 XtSetArg(arg[n], XmNmaximum, 100); n++;
381 XtSetArg(arg[n], XmNhighlightOnEnter, True); n++;
382 slinfo[dev].widget_l = XmCreateScale(m->form, wname, arg, n);
383 XtManageChild(slinfo[dev].widget_l);
384
385 /* Left label */
386 sprintf(wname, "%sLeftLabel", slinfo[dev].name);
387 n = 0;
388 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
389 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_NONE); n++;
390 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
391 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
392 XtSetArg(arg[n], XmNleftWidget, slinfo[dev].widget_l); n++;
393 XtSetArg(arg[n], XmNtopPosition, y1 - 4); n++;
394 XtSetArg(arg[n], XmNbottomWidget, slinfo[dev].widget_l); n++;
395 XtSetArg(arg[n], XmNlabelString, xs_left); n++;
396 slinfo[dev].widget_lbl_l = XmCreateLabel(
397 m->form, wname, arg, n
398 );
399 XtManageChild(slinfo[dev].widget_lbl_l);
400
401 /* Right label */
402 sprintf(wname, "%sRightLabel", slinfo[dev].name);
403 n = 0;
404 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_NONE); n++;
405 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
406 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
407 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
408 XtSetArg(arg[n], XmNrightWidget, slinfo[dev].widget_r); n++;
409 XtSetArg(arg[n], XmNtopPosition, y1 - 4); n++;
410 XtSetArg(arg[n], XmNbottomWidget, slinfo[dev].widget_r); n++;
411 XtSetArg(arg[n], XmNlabelString, xs_right); n++;
412 slinfo[dev].widget_lbl_r = XmCreateLabel(
413 m->form, wname, arg, n
414 );
415 XtManageChild(slinfo[dev].widget_lbl_r);
416
417 /* Slider label */
418 sprintf(wname, "%sLabel", slinfo[dev].name);
419 xs = XmStringCreateSimple(slinfo[dev].label);
420 n = 0;
421 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
422 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
423 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
424 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_WIDGET); n++;
425 XtSetArg(arg[n], XmNleftWidget, slinfo[dev].widget_lbl_l); n++;
426 XtSetArg(arg[n], XmNrightWidget, slinfo[dev].widget_lbl_r); n++;
427 XtSetArg(arg[n], XmNleftOffset, -4); n++;
428 XtSetArg(arg[n], XmNrightOffset, -4); n++;
429 XtSetArg(arg[n], XmNtopWidget, m->menu_bar); n++;
430 XtSetArg(arg[n], XmNtopOffset, 3); n++;
431 XtSetArg(arg[n], XmNbottomWidget, slinfo[dev].widget_lbl_l); n++;
432 XtSetArg(arg[n], XmNlabelString, xs); n++;
433 slinfo[dev].widget_lbl = XmCreateLabel(
434 m->form, slinfo[dev].name, arg, n
435 );
436 XtManageChild(slinfo[dev].widget_lbl);
437 XmStringFree(xs);
438
439 /* Lock button */
440 sprintf(wname, "%sLockButton", slinfo[dev].name);
441 n = 0;
442 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
443 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_OPPOSITE_WIDGET); n++;
444 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
445 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
446 XtSetArg(arg[n], XmNleftWidget, slinfo[dev].widget_l); n++;
447 XtSetArg(arg[n], XmNrightWidget, slinfo[dev].widget_r); n++;
448 XtSetArg(arg[n], XmNtopWidget, slinfo[dev].widget_l); n++;
449 XtSetArg(arg[n], XmNlabelString, xs_lock); n++;
450 slinfo[dev].widget_lock_btn = XmCreateToggleButton(
451 m->form, wname, arg, n
452 );
453 XtManageChild(slinfo[dev].widget_lock_btn);
454
455 /* Record selector buttons */
456 if (slinfo[dev].recsupp) {
457 sprintf(wname, "%sRecButton", slinfo[dev].name);
458 n = 0;
459 XtSetArg(arg[n], XmNleftAttachment,
460 XmATTACH_OPPOSITE_WIDGET); n++;
461 XtSetArg(arg[n], XmNrightAttachment,
462 XmATTACH_OPPOSITE_WIDGET); n++;
463 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
464 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
465 XtSetArg(arg[n], XmNleftWidget, slinfo[dev].widget_l); n++;
466 XtSetArg(arg[n], XmNrightWidget, slinfo[dev].widget_r); n++;
467 XtSetArg(arg[n], XmNtopWidget,
468 slinfo[dev].widget_lock_btn); n++;
469 XtSetArg(arg[n], XmNlabelString, xs_rec); n++;
470 slinfo[dev].widget_rec_btn = XmCreateToggleButton(
471 m->form, wname, arg, n
472 );
473 XtManageChild(slinfo[dev].widget_rec_btn);
474 }
475 }
476
477
478 /*
479 * bm_to_px
480 * Convert a bitmap into a pixmap.
481 *
482 * Args:
483 * w - A widget the pixmap should be associated with
484 * bits - Pointer to the raw bitmap data
485 * width, height - The resultant pixmap dimensions
486 *
487 * Return:
488 * The pixmap ID, or NULL if failure.
489 */
490 Pixmap
bm_to_px(Widget w,void * bits,int width,int height,int depth)491 bm_to_px(Widget w, void *bits, int width, int height, int depth)
492 {
493 Display *display = XtDisplay(w);
494 Window window = XtWindow(w);
495 int screen = DefaultScreen(display);
496 Pixmap ret_pixmap;
497 Pixel fg,
498 bg;
499
500 /* Allocate colors for pixmap if on color screen */
501 if (DisplayCells(display, screen) > 2 && depth > 1) {
502 XtVaGetValues(w,
503 XmNforeground, &fg,
504 XmNbackground, &bg,
505 NULL
506 );
507 }
508 else {
509 fg = BlackPixel(display, screen);
510 bg = WhitePixel(display, screen);
511 }
512
513 ret_pixmap = XCreatePixmapFromBitmapData(
514 display, window, (char *) bits, width, height, fg, bg, depth
515 );
516
517 if (ret_pixmap == (Pixmap) NULL)
518 return ((Pixmap) NULL);
519
520 return (ret_pixmap);
521 }
522
523
524 /***********************
525 * public routines *
526 ***********************/
527
528
529 /*
530 * widget_init
531 * Initialize widget-related structures.
532 *
533 * Args:
534 * m - Pointer to the main widgets structure
535 *
536 * Return:
537 * Nothing
538 */
539 void
widget_init(widgets_t * m)540 widget_init(widgets_t *m)
541 {
542 /* Initialize structures */
543 m->sl = slinfo;
544 m->file_pd = &file_pd;
545 m->opts_pd = &opts_pd;
546 m->help_pd = &help_pd;
547 }
548
549
550 /*
551 * create_widgets
552 * Top-level function to create all widgets.
553 *
554 * Args:
555 * m - Pointer to the main widgets structure
556 *
557 * Return:
558 * Nothing
559 */
560 void
create_widgets(widgets_t * m)561 create_widgets(widgets_t *m)
562 {
563 int i, j, k, n,
564 ctls,
565 form_width;
566 Arg arg[20];
567 char wname[STR_BUF_SZ],
568 str[STR_BUF_SZ];
569 XmString xs;
570
571 /* Count the number of slider controls we will display */
572 for (i = 0, ctls = 0; i < maxdevs; i++) {
573 if (slinfo[i].supp)
574 ctls++;
575 }
576
577 /* Create compound strings that will be used repetitively */
578 xs_left = XmStringCreateSimple("L");
579 xs_right = XmStringCreateSimple("R");
580 xs_lock = XmStringCreateSimple("lock");
581 xs_rec = XmStringCreateSimple("rec");
582
583 /* Create form widget as container */
584 if ((form_width = (ctls + 1) * CTL_DISTANCE) < 300)
585 form_width = 300;
586 n = 0;
587 XtSetArg(arg[n], XmNwidth, form_width); n++;
588 XtSetArg(arg[n], XmNheight, 320); n++;
589 XtSetArg(arg[n], XmNresizePolicy, XmRESIZE_NONE); n++;
590 m->form = XmCreateForm(m->toplevel, "mainForm", arg, n);
591 XtManageChild(m->form);
592
593 /* Create logo label */
594 n = 0;
595 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
596 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_NONE); n++;
597 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
598 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
599 XtSetArg(arg[n], XmNleftOffset, (form_width/2) - (xmmix_width/2)); n++;
600 XtSetArg(arg[n], XmNtopPosition, 88); n++;
601 XtSetArg(arg[n], XmNlabelType, XmPIXMAP); n++;
602 XtSetArg(arg[n], XmNmarginHeight, 0); n++;
603 XtSetArg(arg[n], XmNmarginWidth, 0); n++;
604 XtSetArg(arg[n], XmNhighlightThickness, 0); n++;
605 XtSetArg(arg[n], XmNwidth, xmmix_width); n++;
606 XtSetArg(arg[n], XmNheight, xmmix_height); n++;
607 m->logolbl = XmCreateLabel(m->form, "logoLabel", arg, n);
608 XtManageChild(m->logolbl);
609
610 /* Create menu bar */
611 n = 0;
612 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
613 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
614 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_FORM); n++;
615 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
616 m->menu_bar = XmCreateMenuBar(m->form, "menuBar", arg, n);
617 XtManageChild(m->menu_bar);
618
619 /* Create File pulldown menu */
620 m->file_mnu = create_pdmnu(m->menu_bar, &file_pd);
621
622 /* Create Options pulldown menu */
623 m->options_mnu = create_pdmnu(m->menu_bar, &opts_pd);
624
625 /* Create Help pulldown menu */
626 m->help_mnu = create_pdmnu(m->menu_bar, &help_pd);
627 XtVaSetValues(m->menu_bar,
628 XmNmenuHelpWidget, help_pd.widget,
629 NULL
630 );
631
632 /* Create all sliders and associated labels and buttons */
633 for (j = 1, k = 0; j <= MAXDEVS; j++) {
634 for (i = 0; i < maxdevs; i++) {
635 if (j == slinfo[i].order && slinfo[i].supp) {
636 create_vert_controls(m, i, 22, 70, ++k, ctls);
637 }
638 }
639 }
640
641 /* Horizontal separator */
642 n = 0;
643 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
644 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
645 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
646 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
647 XtSetArg(arg[n], XmNtopPosition, 84); n++;
648 XtSetArg(arg[n], XmNleftOffset, 1); n++;
649 XtSetArg(arg[n], XmNrightOffset, 1); n++;
650 XtSetArg(arg[n], XmNorientation, XmHORIZONTAL); n++;
651 m->hsep = XmCreateSeparator(m->form, "horizontalSeparator", arg, n);
652 XtManageChild(m->hsep);
653
654 /*
655 * Flat button
656 */
657 if (slinfo[SOUND_MIXER_BASS].supp || slinfo[SOUND_MIXER_TREBLE].supp) {
658 xs = XmStringCreateSimple("Flat");
659 n = 0;
660 XtSetArg(arg[n], XmNleftAttachment,
661 XmATTACH_OPPOSITE_WIDGET); n++;
662 XtSetArg(arg[n], XmNrightAttachment,
663 XmATTACH_OPPOSITE_WIDGET); n++;
664 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
665 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
666 if (slinfo[SOUND_MIXER_BASS].supp) {
667 XtSetArg(arg[n], XmNleftWidget,
668 m->sl[SOUND_MIXER_BASS].widget_l); n++;
669 XtSetArg(arg[n], XmNtopWidget,
670 m->sl[SOUND_MIXER_BASS].widget_lock_btn); n++;
671 }
672 else {
673 XtSetArg(arg[n], XmNleftWidget,
674 m->sl[SOUND_MIXER_TREBLE].widget_l); n++;
675 XtSetArg(arg[n], XmNtopWidget,
676 m->sl[SOUND_MIXER_TREBLE].widget_lock_btn); n++;
677 }
678 if (slinfo[SOUND_MIXER_TREBLE].supp) {
679 XtSetArg(arg[n], XmNrightWidget,
680 m->sl[SOUND_MIXER_TREBLE].widget_r); n++;
681 XtSetArg(arg[n], XmNtopWidget,
682 m->sl[SOUND_MIXER_TREBLE].widget_lock_btn); n++;
683 }
684 else {
685 XtSetArg(arg[n], XmNrightWidget,
686 m->sl[SOUND_MIXER_BASS].widget_r); n++;
687 XtSetArg(arg[n], XmNtopWidget,
688 m->sl[SOUND_MIXER_BASS].widget_lock_btn); n++;
689 }
690 XtSetArg(arg[n], XmNlabelString, xs); n++;
691 m->flat_btn = XmCreatePushButton(m->form, "flatButton", arg, n);
692 XtManageChild(m->flat_btn);
693 XmStringFree(xs);
694 }
695
696 /*
697 * Mute button
698 */
699 if (m->mute_supp) {
700 xs = XmStringCreateSimple("Mute");
701 n = 0;
702 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
703 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_NONE); n++;
704 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
705 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
706 XtSetArg(arg[n], XmNleftOffset, form_width - 100); n++;
707 XtSetArg(arg[n], XmNtopPosition, 87); n++;
708 XtSetArg(arg[n], XmNbottomPosition, 92); n++;
709 XtSetArg(arg[n], XmNwidth, 66); n++;
710 XtSetArg(arg[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
711 XtSetArg(arg[n], XmNlabelString, xs); n++;
712 m->mute_btn = XmCreateToggleButton(
713 m->form, "muteButton", arg, n
714 );
715 XtManageChild(m->mute_btn);
716 XmStringFree(xs);
717 }
718
719 /*
720 * Loudness button
721 */
722 if (m->loud_supp) {
723 xs = XmStringCreateSimple("Loudness");
724 n = 0;
725 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
726 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_NONE); n++;
727 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
728 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
729 XtSetArg(arg[n], XmNleftOffset, form_width - 100); n++;
730 XtSetArg(arg[n], XmNtopPosition, 92); n++;
731 XtSetArg(arg[n], XmNbottomPosition, 97); n++;
732 XtSetArg(arg[n], XmNwidth, 66); n++;
733 XtSetArg(arg[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
734 XtSetArg(arg[n], XmNlabelString, xs); n++;
735 m->loud_btn = XmCreateToggleButton(
736 m->form, "loudnessButton", arg, n
737 );
738 XtManageChild(m->loud_btn);
739 XmStringFree(xs);
740 }
741
742 /*
743 * Enhance option menu
744 */
745 if (m->enh_supp) {
746 m->enh_mnu = XmCreatePulldownMenu(
747 m->form, "enhancePulldownMenu", NULL, 0
748 );
749
750 for (i = 0; i < NENHANCE; i++) {
751 sprintf(wname, "enhanceButton%d", i);
752 sprintf(str, "%d", i);
753 xs = XmStringCreateSimple(str);
754 n = 0;
755 XtSetArg(arg[n], XmNlabelString, xs); n++;
756 m->enh_btn[i] = XmCreatePushButton(
757 m->enh_mnu, wname, arg, n
758 );
759 XtManageChild(m->enh_btn[i]);
760 XmStringFree(xs);
761 }
762
763 xs = XmStringCreateSimple("Enhance");
764 n = 0;
765 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
766 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_NONE); n++;
767 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
768 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
769 XtSetArg(arg[n], XmNleftOffset, 28); n++;
770 XtSetArg(arg[n], XmNtopPosition, 88); n++;
771 XtSetArg(arg[n], XmNsubMenuId, m->enh_mnu); n++;
772 m->enh_opt = XmCreateOptionMenu(
773 m->form, "enhanceOptionMenu", arg, n
774 );
775 XtVaSetValues(
776 XmOptionLabelGadget(m->enh_opt),
777 XmNlabelString, xs,
778 NULL
779 );
780 XtManageChild(m->enh_opt);
781 XmStringFree(xs);
782 }
783
784 /*
785 * File selection box form
786 */
787 n = 0;
788 XtSetArg(arg[n], XmNresizePolicy, XmRESIZE_NONE); n++;
789 XtSetArg(arg[n], XmNautoUnmanage, False); n++;
790 XtSetArg(arg[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
791 XtSetArg(arg[n], XmNwidth, 330); n++;
792 XtSetArg(arg[n], XmNheight, 370); n++;
793 m->fsform = XmCreateFormDialog(
794 m->toplevel, "fileSelectionForm", arg, n
795 );
796
797 /*
798 * File selection box
799 */
800 xs = XmStringCreateSimple("*.mxr");
801 n = 0;
802 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
803 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
804 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_FORM); n++;
805 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_FORM); n++;
806 XtSetArg(arg[n], XmNmustMatch, False); n++;
807 XtSetArg(arg[n], XmNpattern, xs); n++;
808 m->fsbox = XmCreateFileSelectionBox(
809 m->fsform, "fileSelectionBox", arg, n
810 );
811 XtUnmanageChild(
812 XmFileSelectionBoxGetChild(m->fsbox, XmDIALOG_HELP_BUTTON)
813 );
814 XtManageChild(m->fsbox);
815 XmStringFree(xs);
816
817 XmStringFree(xs_left);
818 XmStringFree(xs_right);
819 XmStringFree(xs_lock);
820 XmStringFree(xs_rec);
821
822 /*
823 * Man page window widgets
824 */
825
826 /* Create form widget as container */
827 xs = XmStringCreateSimple("Xmmix Help");
828 n = 0;
829 XtSetArg(arg[n], XmNdialogTitle, xs); n++;
830 XtSetArg(arg[n], XmNautoUnmanage, True); n++;
831 XtSetArg(arg[n], XmNresizePolicy, XmRESIZE_NONE); n++;
832 XtSetArg(arg[n], XmNwidth, 460); n++;
833 XtSetArg(arg[n], XmNheight, 340); n++;
834 m->helpform = XmCreateFormDialog(m->form, "helpForm", arg, n);
835 XmStringFree(xs);
836
837 /* Create text widget as help text viewer */
838 n = 0;
839 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_POSITION); n++;
840 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_POSITION); n++;
841 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
842 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
843 XtSetArg(arg[n], XmNleftPosition, 2); n++;
844 XtSetArg(arg[n], XmNrightPosition, 98); n++;
845 XtSetArg(arg[n], XmNtopPosition, 4); n++;
846 XtSetArg(arg[n], XmNbottomPosition, 81); n++;
847 XtSetArg(arg[n], XmNeditable, False); n++;
848 XtSetArg(arg[n], XmNeditMode, XmMULTI_LINE_EDIT); n++;
849 XtSetArg(arg[n], XmNcursorPositionVisible, False); n++;
850 XtSetArg(arg[n], XmNcursorPosition, 0); n++;
851 m->helptxt = XmCreateScrolledText(m->helpform, "helpText", arg, n);
852 XtManageChild(m->helptxt);
853
854 /* Create separator bar widget */
855 n = 0;
856 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_FORM); n++;
857 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_FORM); n++;
858 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
859 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
860 XtSetArg(arg[n], XmNleftOffset, 2); n++;
861 XtSetArg(arg[n], XmNrightOffset, 2); n++;
862 XtSetArg(arg[n], XmNtopPosition, 84); n++;
863 m->helpsep = XmCreateSeparator(m->helpform, "helpSeparator", arg, n);
864 XtManageChild(m->helpsep);
865
866 /* Create pushbutton widget as OK button */
867 xs = XmStringCreateSimple("OK");
868 n = 0;
869 XtSetArg(arg[n], XmNleftAttachment, XmATTACH_POSITION); n++;
870 XtSetArg(arg[n], XmNrightAttachment, XmATTACH_POSITION); n++;
871 XtSetArg(arg[n], XmNtopAttachment, XmATTACH_POSITION); n++;
872 XtSetArg(arg[n], XmNbottomAttachment, XmATTACH_NONE); n++;
873 XtSetArg(arg[n], XmNleftPosition, 44); n++;
874 XtSetArg(arg[n], XmNrightPosition, 56); n++;
875 XtSetArg(arg[n], XmNtopPosition, 89); n++;
876 XtSetArg(arg[n], XmNlabelString, xs); n++;
877 m->helpok_btn = XmCreatePushButton(
878 m->helpform, "helpOkButton", arg, n
879 );
880 XtManageChild(m->helpok_btn);
881 XmStringFree(xs);
882
883 /*
884 * Info dialog widget for the About popup
885 */
886 xs = XmStringCreateSimple("About");
887 n = 0;
888 XtSetArg(arg[n], XmNdialogTitle, xs); n++;
889 XtSetArg(arg[n], XmNdialogStyle, XmDIALOG_MODELESS); n++;
890 m->about = XmCreateInformationDialog(
891 m->toplevel, "aboutDialog", arg, n
892 );
893 XtUnmanageChild(
894 XmMessageBoxGetChild(m->about, XmDIALOG_HELP_BUTTON)
895 );
896 XtUnmanageChild(
897 XmMessageBoxGetChild(m->about, XmDIALOG_CANCEL_BUTTON)
898 );
899 XmStringFree(xs);
900
901 /*
902 * Info dialog widget for warning popups
903 */
904 xs = XmStringCreateSimple("Warning");
905 n = 0;
906 XtSetArg(arg[n], XmNdialogTitle, xs); n++;
907 XtSetArg(arg[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
908 m->warning = XmCreateWarningDialog(
909 m->toplevel, "warningDialog", arg, n
910 );
911 XtUnmanageChild(
912 XmMessageBoxGetChild(m->warning, XmDIALOG_HELP_BUTTON)
913 );
914 XtUnmanageChild(
915 XmMessageBoxGetChild(m->warning, XmDIALOG_CANCEL_BUTTON)
916 );
917 XmStringFree(xs);
918 }
919
920
921 /*
922 * post_realize_config
923 * Top-level function to perform set-up and initialization tasks
924 * after realizing all widgets.
925 *
926 * Args:
927 * m - Pointer to the main widgets structure
928 *
929 * Return:
930 * Nothing
931 */
932 void
post_realize_config(widgets_t * m)933 post_realize_config(widgets_t *m)
934 {
935 int i, n;
936 Display *display = XtDisplay(m->toplevel);
937 Pixmap px;
938 char title[STR_BUF_SZ],
939 *p;
940
941 /* Set main window title bar string */
942 if (app_data.demo)
943 strcpy(title, "Motif Audio Mixer (Demo)");
944 else {
945 n = 0;
946 if ((i = strlen(app_data.device)) > 0) {
947 /* Find mixer device number */
948 p = app_data.device + i;
949 while (p > app_data.device) {
950 if (!isdigit(*(p - 1)))
951 break;
952 p--;
953 }
954 if (isdigit(*p))
955 n = atoi(p);
956 }
957 sprintf(title, "Motif Audio Mixer %d", n);
958 }
959 XStoreName(display, XtWindow(m->toplevel), title);
960
961 /*
962 * Create logo pixmap
963 */
964 px = bm_to_px(m->logolbl, xmmix_bits, xmmix_width, xmmix_height, 1);
965 XtVaSetValues(m->toplevel, XmNiconPixmap, px, NULL);
966
967 px = bm_to_px(m->logolbl, xmmix_bits, xmmix_width, xmmix_height,
968 DefaultDepth(display, DefaultScreen(display)));
969 XtVaSetValues(m->logolbl, XmNlabelPixmap, px, NULL);
970 XtVaSetValues(m->about, XmNsymbolPixmap, px, NULL);
971
972 /* Get WM_DELETE_WINDOW atom */
973 delw = XmInternAtom(display, "WM_DELETE_WINDOW", False);
974 }
975
976
977 /*
978 * register_callbacks
979 * Top-level function to register all callback routines.
980 *
981 * Args:
982 * m - Pointer to the main widgets structure
983 *
984 * Return:
985 * Nothing
986 */
987 void
register_callbacks(widgets_t * m)988 register_callbacks(widgets_t *m)
989 {
990 int i;
991
992 /*
993 * Main window callbacks
994 */
995
996 /* Callbacks for each control group */
997 for (i = 0; i < maxdevs; i++) {
998 if (!slinfo[i].supp)
999 continue;
1000
1001 /* Left Slider callbacks */
1002 XtAddCallback(slinfo[i].widget_l,
1003 XmNvalueChangedCallback,
1004 (XtCallbackProc) mx_slider_l, (XtPointer) i
1005 );
1006 XtAddCallback(slinfo[i].widget_l,
1007 XmNdragCallback,
1008 (XtCallbackProc) mx_slider_l, (XtPointer) i
1009 );
1010
1011 /* Right Slider callbacks */
1012 XtAddCallback(slinfo[i].widget_r,
1013 XmNvalueChangedCallback,
1014 (XtCallbackProc) mx_slider_r, (XtPointer) i
1015 );
1016 XtAddCallback(slinfo[i].widget_r,
1017 XmNdragCallback,
1018 (XtCallbackProc) mx_slider_r, (XtPointer) i
1019 );
1020
1021 /* Lock button callback */
1022 XtAddCallback(slinfo[i].widget_lock_btn,
1023 XmNvalueChangedCallback,
1024 (XtCallbackProc) mx_lock_btn, (XtPointer) i
1025 );
1026
1027 /* Rec button callback */
1028 if (slinfo[i].recsupp) {
1029 XtAddCallback(slinfo[i].widget_rec_btn,
1030 XmNvalueChangedCallback,
1031 (XtCallbackProc) mx_rec_btn, (XtPointer) i
1032 );
1033 }
1034 }
1035
1036 /* Flat button callback */
1037 if (slinfo[SOUND_MIXER_BASS].supp || slinfo[SOUND_MIXER_TREBLE].supp) {
1038 XtAddCallback(m->flat_btn,
1039 XmNactivateCallback,
1040 (XtCallbackProc) mx_flat_btn, NULL
1041 );
1042 }
1043
1044 /* Mute button callback */
1045 if (m->mute_supp) {
1046 XtAddCallback(m->mute_btn,
1047 XmNvalueChangedCallback,
1048 (XtCallbackProc) mx_mute_btn, NULL
1049 );
1050 }
1051
1052 /* Loudness button callback */
1053 if (m->loud_supp) {
1054 XtAddCallback(m->loud_btn,
1055 XmNvalueChangedCallback,
1056 (XtCallbackProc) mx_loud_btn, NULL
1057 );
1058 }
1059
1060 /* Stereo enhance button callbacks */
1061 if (m->enh_supp) {
1062 for (i = 0; i < NENHANCE; i++) {
1063 XtAddCallback(m->enh_btn[i],
1064 XmNactivateCallback,
1065 (XtCallbackProc) mx_enhance_btn, (XtPointer) i
1066 );
1067 }
1068 }
1069
1070 /* Load button callback */
1071 XtAddCallback(file_pd.btip[PD_FILE_LOAD].widget,
1072 XmNactivateCallback,
1073 (XtCallbackProc) mx_load, NULL
1074 );
1075
1076 /* Save button callback */
1077 XtAddCallback(file_pd.btip[PD_FILE_SAVE].widget,
1078 XmNactivateCallback,
1079 (XtCallbackProc) mx_save, NULL
1080 );
1081
1082 /* Exit button callback */
1083 XtAddCallback(file_pd.btip[PD_FILE_EXIT].widget,
1084 XmNactivateCallback,
1085 (XtCallbackProc) mx_exit, NULL
1086 );
1087
1088 /* Reset button callback */
1089 XtAddCallback(opts_pd.btip[PD_OPTS_RESET].widget,
1090 XmNactivateCallback,
1091 (XtCallbackProc) mx_reset, NULL
1092 );
1093
1094 /* Man Page button callback */
1095 XtAddCallback(help_pd.btip[PD_HELP_MANPG].widget,
1096 XmNactivateCallback,
1097 (XtCallbackProc) mx_manpg, NULL
1098 );
1099
1100 /* About button callback */
1101 XtAddCallback(help_pd.btip[PD_HELP_ABOUT].widget,
1102 XmNactivateCallback,
1103 (XtCallbackProc) mx_about, NULL
1104 );
1105
1106 /*
1107 * File Selection Box callbacks
1108 */
1109
1110 /* OK button callback */
1111 XtAddCallback(m->fsbox,
1112 XmNokCallback,
1113 (XtCallbackProc) mx_fsok_btn, NULL
1114 );
1115
1116 /* Cancel button callback */
1117 XtAddCallback(m->fsbox,
1118 XmNcancelCallback,
1119 (XtCallbackProc) mx_fscancel_btn, NULL
1120 );
1121
1122 /*
1123 * Focus change callback
1124 */
1125 XtAddCallback(m->form,
1126 XmNfocusCallback,
1127 (XtCallbackProc) mx_focuschg, (XtPointer) m->form
1128 );
1129
1130 /*
1131 * Install WM_DELETE_WINDOW handler
1132 */
1133 XmAddWMProtocolCallback(
1134 m->toplevel,
1135 delw,
1136 (XtCallbackProc) mx_exit, (XtPointer) NULL
1137 );
1138 }
1139
1140
1141