1 
2 
3 /*
4  *  Author: Arvin Schnell
5  */
6 
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 
11 #include <Xm/Xm.h>
12 #include <Xm/Form.h>
13 #include <Xm/Label.h>
14 #include <Xm/PushB.h>
15 #include <Xm/ToggleB.h>
16 #include <Xm/Scale.h>
17 #include <Xm/RowColumn.h>
18 #include <Xm/Label.h>
19 #include <Xm/LabelG.h>
20 #include <Xm/Frame.h>
21 #include <Xm/DrawingA.h>
22 #include <Xm/Protocols.h>
23 
24 #include "Sample.h"
25 #include "help.h"
26 #include "utils.h"
27 #include "Analyser.h"
28 #include "Scope.h"
29 #include "main.h"
30 #include "control.h"
31 
32 
33 Widget control_w;
34 Widget card_w, disk_w;
35 Widget analyseron_w, alpha_w, decay_w, search_w;
36 Widget scopeon_w, zoom_w;
37 
38 enum {
39     QUIT, ANALYSERON, SCOPEON, SOUNDCARD, DISKFILE, DECAY, ALPHA,
40     SEARCH, HELP, ZOOM
41 };
42 
43 
44 Widget scope_w;
45 Widget scope_drawing_w;
46 int scope_visibility;
47 
48 Widget analyser_w;
49 Widget analyser_drawing_w[2];
50 int analyser_visibility;
51 
52 XtWorkProcId workproc_id;
53 
54 bool run_analyser = false;
55 bool run_scope = false;
56 
57 Analyser analyser[2];
58 
59 Scope scope;
60 
61 
62 bool
run()63 run ()
64 {
65     return run_analyser || run_scope;
66 }
67 
68 
69 Boolean
workproc(XtPointer)70 workproc (XtPointer)
71 {
72     if (sample.shot ()) {
73 
74 	if (run_analyser) {
75 
76 	    if (xanalyser.stereo) {
77 
78 		analyser[0].shot (sample.buffer, Analyser::LEFT,
79 				  analyser_visibility);
80 		analyser[1].shot (sample.buffer, Analyser::RIGHT,
81 				  analyser_visibility);
82 		XFlush (XtDisplay (toplevel));
83 
84 	    } else {
85 
86 		analyser[0].shot (sample.buffer, Analyser::MONO,
87 				  analyser_visibility);
88 		XFlush (XtDisplay (toplevel));
89 
90 	    }
91 	}
92 
93 	if (run_scope) {
94 
95 	    scope.shot (sample.buffer, scope_visibility);
96 	    XFlush (XtDisplay (toplevel));
97 
98 	}
99 
100 	return FALSE;
101 
102     } else {
103 
104 	sample.close ();
105 
106 	run_analyser = false;
107 	run_scope = false;
108 
109 	set_sensitivity ();
110 
111 	return TRUE;
112 
113     }
114 }
115 
116 
117 void
startstop()118 startstop ()
119 {
120     if (run ()) {
121 
122 	if (!sample.isopen ())
123 	    if (sample.open ()) {
124 		workproc_id = XtAppAddWorkProc (app_context, workproc, 0);
125 	    } else {
126 		run_analyser = false;
127 		run_scope = false;
128 	    }
129 
130     } else {
131 
132 	if (sample.isopen ()) {
133 	    XtRemoveWorkProc (workproc_id);
134 	    sample.close ();
135 	    run_analyser = false;
136 	    run_scope = false;
137 	}
138 
139     }
140 
141     set_sensitivity ();
142 }
143 
144 
145 void
control_close()146 control_close ()
147 {
148     if (sample.isopen ())
149 	sample.close ();
150 
151     XtDestroyApplicationContext (app_context);
152 
153     exit (EXIT_SUCCESS);
154 }
155 
156 
157 void
control_close(Widget,XtPointer,XtPointer)158 control_close (Widget, XtPointer, XtPointer)
159 {
160     control_close ();
161 }
162 
163 
164 void
analyser_close(Widget,XtPointer,XtPointer)165 analyser_close (Widget, XtPointer, XtPointer)
166 {
167     XtUnmanageChild (analyser_w);
168 
169     XmToggleButtonSetState (analyseron_w, False, False);
170 
171     run_analyser = false;
172 
173     startstop ();
174 }
175 
176 
177 void
scope_close(Widget,XtPointer,XtPointer)178 scope_close (Widget, XtPointer, XtPointer)
179 {
180     XtUnmanageChild (scope_w);
181 
182     XmToggleButtonSetState (scopeon_w, False, False);
183 
184     run_scope = false;
185 
186     startstop ();
187 }
188 
189 
190 void
set_sensitivity()191 set_sensitivity ()
192 {
193     XtSetSensitive (card_w, run ()? False : True);
194     XtSetSensitive (disk_w, run ()? False : True);
195 
196     XmToggleButtonSetState (card_w, sample.source == Sample::SOUNDCARD ?
197 			    True : False, False);
198     XmToggleButtonSetState (disk_w, sample.source == Sample::DISKFILE ?
199 			    True : False, False);
200 
201     XmToggleButtonSetState (analyseron_w, run_analyser ? True : False, False);
202     XmToggleButtonSetState (scopeon_w, run_scope ? True : False, False);
203 }
204 
205 
206 void
control_set_default()207 control_set_default ()
208 {
209     double alpha = xanalyser.alpha;
210     myXmScaleSetValue (alpha_w, alpha);
211     analyser[0].set_alpha (alpha);
212     analyser[1].set_alpha (alpha);
213 
214     double decay = xanalyser.decay;
215     myXmScaleSetValue (decay_w, decay);
216     analyser[0].set_decay (decay);
217     analyser[1].set_decay (decay);
218 
219     double zoom = xanalyser.zoom;
220     myXmScaleSetValue (zoom_w, xanalyser.zoom);
221     scope.set_zoom (zoom);
222 }
223 
224 
225 void
control_callback(Widget widget,XtPointer client_data,XtPointer)226 control_callback (Widget widget, XtPointer client_data, XtPointer)
227 {
228     switch ((long int) client_data) {
229 
230 	case SOUNDCARD: {
231 	    sample.source = Sample::SOUNDCARD;
232 	} break;
233 
234 	case DISKFILE: {
235 	    sample.source = Sample::DISKFILE;
236 	} break;
237 
238 	case DECAY: {
239 	    double decay = myXmScaleGetValue (widget);
240 	    analyser[0].set_decay (decay);
241 	    analyser[1].set_decay (decay);
242 	} break;
243 
244 	case ALPHA: {
245 	    double alpha = myXmScaleGetValue (widget);
246 	    analyser[0].set_alpha (alpha);
247 	    analyser[1].set_alpha (alpha);
248 	} break;
249 
250 	case SEARCH: {
251 	    int search = XmToggleButtonGetState (widget);
252 	    analyser[0].set_search (search);
253 	    analyser[1].set_search (search);
254 	} break;
255 
256 	case ZOOM: {
257 	    double zoom = myXmScaleGetValue (widget);
258 	    scope.set_zoom (zoom);
259 	} break;
260 
261 	case ANALYSERON: {
262 	    run_analyser = XmToggleButtonGetState (widget);
263 	    if (run_analyser)
264 		analyser_manage ();
265 	    startstop ();
266 	} break;
267 
268 	case SCOPEON: {
269 	    run_scope = XmToggleButtonGetState (widget);
270 	    if (run_scope)
271 		scope_manage ();
272 	    startstop ();
273 	} break;
274 
275 	case HELP: {
276 	    help_manage ();
277 	} break;
278 
279 	case QUIT: {
280 	    control_close ();
281 	} break;
282 
283     }
284 }
285 
286 
287 void
control_create()288 control_create ()
289 {
290     Arg args[10];
291     int n;
292 
293     // control
294 
295     n = 0;
296     control_w = XmCreateForm (toplevel, "Control", args, n);
297     XtManageChild (control_w);
298 
299     // frame1 - Source
300 
301     Widget frame1_w, form1_w, label11_w, box1_w;
302 
303     n = 0;
304     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
305     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
306     frame1_w = XmCreateFrame (control_w, "Frame1", args, n);
307     XtManageChild (frame1_w);
308 
309     // form1
310 
311     n = 0;
312     form1_w = XmCreateForm (frame1_w, "Form1", args, n);
313     XtManageChild (form1_w);
314 
315     // label: source
316 
317     n = 0;
318     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
319     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
320     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
321     label11_w = XmCreateLabel (form1_w, "Source", args, n);
322     XtManageChild (label11_w);
323 
324     // radiobox1
325 
326     n = 0;
327     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
328     XtSetArg (args[n], XmNtopWidget, label11_w); n++;
329     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
330     box1_w = XmCreateRadioBox (form1_w, "RadioBox1", args, n);
331     XtManageChild (box1_w);
332 
333     // radio button: card
334 
335     n = 0;
336     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
337     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
338     card_w = XmCreateToggleButton (box1_w, "Soundcard", args, n);
339     XtManageChild (card_w);
340     XtAddCallback (card_w, XmNvalueChangedCallback,
341 		   control_callback, (XtPointer) SOUNDCARD);
342 
343     // radio button: disk
344 
345     n = 0;
346     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
347     XtSetArg (args[n], XmNtopWidget, card_w); n++;
348     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
349     disk_w = XmCreateToggleButton (box1_w, "Diskfile", args, n);
350     XtManageChild (disk_w);
351     XtAddCallback (disk_w, XmNvalueChangedCallback,
352 		   control_callback, (XtPointer) DISKFILE);
353 
354     // frame2 - Analyser
355 
356     Widget frame2_w, form2_w, label21_w;
357 
358     n = 0;
359     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
360     XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
361     XtSetArg (args[n], XmNleftWidget, frame1_w); n++;
362     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
363     frame2_w = XmCreateFrame (control_w, "Frame2", args, n);
364     XtManageChild (frame2_w);
365 
366     // form2
367 
368     n = 0;
369     form2_w = XmCreateForm (frame2_w, "Form2", args, n);
370     XtManageChild (form2_w);
371 
372     // label
373 
374     n = 0;
375     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
376     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
377     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
378     label21_w = XmCreateLabel (form2_w, "Freq. Analyser", args, n);
379     XtManageChild (label21_w);
380 
381     // toggle: run
382 
383     n = 0;
384     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
385     XtSetArg (args[n], XmNtopWidget, label21_w); n++;
386     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
387     analyseron_w = XmCreateToggleButton (form2_w, "Run", args, n);
388     XtManageChild (analyseron_w);
389     XtAddCallback (analyseron_w, XmNvalueChangedCallback,
390 		   control_callback, (XtPointer) ANALYSERON);
391 
392     // scale: alpha
393 
394     n = 0;
395     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
396     XtSetArg (args[n], XmNtopWidget, analyseron_w); n++;
397     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
398     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
399     alpha_w = XmCreateScale (form2_w, "Alpha", args, n);
400     XtManageChild (alpha_w);
401     XtAddCallback (alpha_w, XmNdragCallback, control_callback, (XtPointer) ALPHA);
402     XtAddCallback (alpha_w, XmNvalueChangedCallback,
403 		   control_callback, (XtPointer) ALPHA);
404 
405     // scale: decay
406 
407     n = 0;
408     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
409     XtSetArg (args[n], XmNtopWidget, alpha_w); n++;
410     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
411     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
412     decay_w = XmCreateScale (form2_w, "Decay", args, n);
413     XtManageChild (decay_w);
414     XtAddCallback (decay_w, XmNdragCallback, control_callback, (XtPointer) DECAY);
415     XtAddCallback (decay_w, XmNvalueChangedCallback,
416 		   control_callback, (XtPointer) DECAY);
417 
418     // toggle: search
419 
420     n = 0;
421     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
422     XtSetArg (args[n], XmNtopWidget, decay_w); n++;
423     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
424     search_w = XmCreateToggleButton (form2_w, "Peak Search", args, n);
425     XtManageChild (search_w);
426     XtAddCallback (search_w, XmNvalueChangedCallback,
427 		   control_callback, (XtPointer) SEARCH);
428 
429     // frame3 - Scope
430 
431     Widget frame3_w, form3_w, label31_w;
432 
433     n = 0;
434     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
435     XtSetArg (args[n], XmNleftAttachment, XmATTACH_WIDGET); n++;
436     XtSetArg (args[n], XmNleftWidget, frame2_w); n++;
437     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
438     frame3_w = XmCreateFrame (control_w, "Frame3", args, n);
439     XtManageChild (frame3_w);
440 
441     // form3
442 
443     n = 0;
444     form3_w = XmCreateForm (frame3_w, "Form3", args, n);
445     XtManageChild (form3_w);
446 
447     // label: Scope
448 
449     n = 0;
450     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
451     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
452     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
453     label31_w = XmCreateLabel (form3_w, "XY Scope", args, n);
454     XtManageChild (label31_w);
455 
456     // toggle: run
457 
458     n = 0;
459     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
460     XtSetArg (args[n], XmNtopWidget, label31_w); n++;
461     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
462     scopeon_w = XmCreateToggleButton (form3_w, "Run", args, n);
463     XtManageChild (scopeon_w);
464     XtAddCallback (scopeon_w, XmNvalueChangedCallback,
465 		   control_callback, (XtPointer) SCOPEON);
466 
467     // scale: zoom
468 
469     n = 0;
470     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
471     XtSetArg (args[n], XmNtopWidget, scopeon_w); n++;
472     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
473     zoom_w = XmCreateScale (form3_w, "Zoom", args, n);
474     XtManageChild (zoom_w);
475     XtAddCallback (zoom_w, XmNdragCallback, control_callback, (XtPointer) ZOOM);
476     XtAddCallback (zoom_w, XmNvalueChangedCallback,
477 		   control_callback, (XtPointer) ZOOM);
478 
479     // frame5 - Help
480 
481     Widget frame5_w, form5_w, label51_w, help_w;
482 
483     n = 0;
484     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
485     XtSetArg (args[n], XmNtopWidget, frame1_w); n++;
486     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
487     XtSetArg (args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
488     XtSetArg (args[n], XmNrightWidget, frame2_w); n++;
489     frame5_w = XmCreateFrame (control_w, "Frame5", args, n);
490     XtManageChild (frame5_w);
491 
492     // form5
493 
494     n = 0;
495     form5_w = XmCreateForm (frame5_w, "Form5", args, n);
496     XtManageChild (form5_w);
497 
498     // label: help
499 
500     n = 0;
501     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
502     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
503     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
504     label51_w = XmCreateLabel (form5_w, "Help", args, n);
505     XtManageChild (label51_w);
506 
507     // button: help
508 
509     n = 0;
510     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
511     XtSetArg (args[n], XmNtopWidget, label51_w); n++;
512     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
513     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
514     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
515     help_w = XmCreatePushButton (form5_w, "Help", args, n);
516     XtManageChild (help_w);
517     XtAddCallback (help_w, XmNactivateCallback, control_callback, (XtPointer) HELP);
518 
519     // frame6 - Quit
520 
521     Widget frame6_w, form6_w, quit_w;
522 
523     n = 0;
524     XtSetArg (args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
525     XtSetArg (args[n], XmNtopWidget, frame5_w); n++;
526     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
527     XtSetArg (args[n], XmNrightAttachment, XmATTACH_WIDGET); n++;
528     XtSetArg (args[n], XmNrightWidget, frame2_w); n++;
529     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
530     frame6_w = XmCreateFrame (control_w, "Frame6", args, n);
531     XtManageChild (frame6_w);
532 
533     // form6
534 
535     n = 0;
536     form6_w = XmCreateForm (frame6_w, "Form6", args, n);
537     XtManageChild (form6_w);
538 
539     // button: quit
540 
541     n = 0;
542     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
543     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
544     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
545     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
546     quit_w = XmCreatePushButton (form6_w, "Quit", args, n);
547     XtManageChild (quit_w);
548     XtAddCallback (quit_w, XmNactivateCallback, control_callback,
549 		   (XtPointer) QUIT);
550 }
551 
552 
553 void
analyser_callback(Widget,XtPointer client_data,XtPointer call_data)554 analyser_callback (Widget, XtPointer client_data, XtPointer call_data)
555 {
556     XmDrawingAreaCallbackStruct* c = (XmDrawingAreaCallbackStruct*) call_data;
557 
558     switch (c->reason) {
559 
560 	case XmCR_EXPOSE: {
561 
562 	    int n = (long int) client_data;
563 
564 	    if (!analyser[n].isrealized ())
565 		analyser[n].realize (XtDisplay (analyser_drawing_w[n]),
566 				     XtWindow (analyser_drawing_w[n]));
567 
568 	    XExposeEvent* e = (XExposeEvent*) c->event;
569 	    XRectangle rect = { static_cast<short>(e->x), static_cast<short>(e->y), static_cast<unsigned short>(e->width), static_cast<unsigned short>(e->height) };
570 	    analyser[n].draw (rect);
571 
572 	} break;
573 
574 	case XmCR_RESIZE: {
575 
576 	    int n = (long int) client_data;
577 	    analyser[n].resize (1);
578 
579 	} break;
580 
581 	case XmCR_INPUT: {
582 
583 	    switch (c->event->type) {
584 
585 		case ButtonPress:
586 		case MotionNotify: {
587 		    XButtonPressedEvent* e = (XButtonPressedEvent*) c->event;
588 		    XPoint point = { static_cast<short>(e->x),static_cast<short>(e->y) };
589 
590 		    analyser[0].set_marker (point.x);
591 		    analyser[1].set_marker (point.x);
592 
593 		} break;
594 
595 	    }
596 
597 	} break;
598 
599     }
600 }
601 
602 
603 void
analyser_notify(Widget,XtPointer,XEvent * event,Boolean *)604 analyser_notify (Widget, XtPointer, XEvent* event, Boolean*)
605 {
606     switch (event->type) {
607 
608 	case UnmapNotify:
609 	    analyser_visibility = 0;
610 	    break;
611 
612 	case VisibilityNotify:
613 	    analyser_visibility = ((XVisibilityEvent*) (event))->state
614 		!= VisibilityFullyObscured;
615 	    break;
616 
617     }
618 }
619 
620 
621 void
analyser_create()622 analyser_create ()
623 {
624     Arg args[10];
625     int n;
626 
627     // form
628 
629     n = 0;
630     XtSetArg (args[n], XtNiconPixmap, a_iconpixmap); n++;
631     XtSetArg (args[n], XtNiconMask, a_iconmask); n++;
632     analyser_w = XmCreateFormDialog (toplevel, "Analyser", args, n);
633     XmAddWMProtocolCallback (XtParent (analyser_w), wm_delete_window,
634 			     analyser_close, 0);
635     XtAddEventHandler (XtParent (analyser_w), StructureNotifyMask, False,
636 		       analyser_notify, 0);
637     XtAddEventHandler (XtParent (analyser_w), VisibilityChangeMask, False,
638 		       analyser_notify, 0);
639 
640     // drawingarea 0
641 
642     n = 0;
643     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
644     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
645     if (xanalyser.stereo) {
646 	XtSetArg (args[n], XmNbottomAttachment, XmATTACH_POSITION); n++;
647     } else {
648 	XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
649     }
650     XtSetArg (args[n], XmNbottomPosition, 50); n++;
651     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
652     XtSetArg (args[n], XmNwidth, sample.length / 2 + 1); n++; // FIXME
653     analyser_drawing_w[0] = XmCreateDrawingArea (analyser_w, "Display0", args, n);
654     XtManageChild (analyser_drawing_w[0]);
655     XtAddCallback (analyser_drawing_w[0], XmNexposeCallback, analyser_callback,
656 		   (XtPointer) 0);
657     XtAddCallback (analyser_drawing_w[0], XmNresizeCallback, analyser_callback,
658 		   (XtPointer) 0);
659     XtAddCallback (analyser_drawing_w[0], XmNinputCallback, analyser_callback,
660 		   (XtPointer) 0);
661 
662     // drawingarea 1
663 
664     if (xanalyser.stereo) {
665 	n = 0;
666 	XtSetArg (args[n], XmNtopAttachment, XmATTACH_POSITION); n++;
667 	XtSetArg (args[n], XmNtopPosition, 50); n++;
668 	XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
669 	XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
670 	XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
671 	XtSetArg (args[n], XmNwidth, sample.length / 2 + 1); n++; // FIXME
672 	analyser_drawing_w[1] = XmCreateDrawingArea (analyser_w, "Display1", args, n);
673 	XtManageChild (analyser_drawing_w[1]);
674 	XtAddCallback (analyser_drawing_w[1], XmNexposeCallback, analyser_callback,
675 		       (XtPointer) 1);
676 	XtAddCallback (analyser_drawing_w[1], XmNresizeCallback, analyser_callback,
677 		       (XtPointer) 1);
678 	XtAddCallback (analyser_drawing_w[1], XmNinputCallback, analyser_callback,
679 		       (XtPointer) 1);
680     }
681 }
682 
683 
684 void
analyser_manage()685 analyser_manage ()
686 {
687     if (!analyser_w)
688 	analyser_create ();
689 
690     if (!XtIsManaged (analyser_w))
691 	XtManageChild (analyser_w);
692 #if 1
693     else
694 	XMapRaised (XtDisplay (analyser_w), XtWindow (XtParent (analyser_w)));
695 #endif
696 }
697 
698 
699 void
scope_callback(Widget,XtPointer,XtPointer call_data)700 scope_callback (Widget, XtPointer, XtPointer call_data)
701 {
702     XmDrawingAreaCallbackStruct* c = (XmDrawingAreaCallbackStruct*) call_data;
703 
704     switch (c->reason) {
705 
706 	case XmCR_EXPOSE: {
707 
708 	    if (!scope.isrealized ())
709 		scope.realize (XtDisplay (scope_drawing_w), XtWindow (scope_drawing_w));
710 
711 	    XExposeEvent* e = (XExposeEvent*) c->event;
712 	    XRectangle rect = { static_cast<short>(e->x),static_cast<short>(e->y), static_cast<unsigned short>(e->width), static_cast<unsigned short>(e->height) };
713 	    scope.draw (rect);
714 
715 	} break;
716 
717 	case XmCR_RESIZE: {
718 
719 	    scope.resize (1);
720 
721 	} break;
722 
723     }
724 }
725 
726 
727 void
scope_notify(Widget,XtPointer,XEvent * event,Boolean *)728 scope_notify (Widget, XtPointer, XEvent* event, Boolean*)
729 {
730     switch (event->type) {
731 
732 	case UnmapNotify:
733 	    scope_visibility = 0;
734 	    break;
735 
736 	case VisibilityNotify:
737 	    scope_visibility =
738 		((XVisibilityEvent*) (event))->state != VisibilityFullyObscured;
739 	    break;
740 
741     }
742 }
743 
744 
745 void
scope_create()746 scope_create ()
747 {
748     Arg args[10];
749     int n;
750 
751     // form
752 
753     n = 0;
754     XtSetArg (args[n], XtNiconPixmap, s_iconpixmap); n++;
755     XtSetArg (args[n], XtNiconMask, s_iconmask); n++;
756     scope_w = XmCreateFormDialog (toplevel, "Scope", args, n);
757     XmAddWMProtocolCallback (XtParent (scope_w), wm_delete_window,
758 			     scope_close, 0);
759     XtAddEventHandler (XtParent (scope_w), StructureNotifyMask, False,
760 		       scope_notify, 0);
761     XtAddEventHandler (XtParent (scope_w), VisibilityChangeMask, False,
762 		       scope_notify, 0);
763 
764     // drawingarea
765 
766     n = 0;
767     XtSetArg (args[n], XmNtopAttachment, XmATTACH_FORM); n++;
768     XtSetArg (args[n], XmNleftAttachment, XmATTACH_FORM); n++;
769     XtSetArg (args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
770     XtSetArg (args[n], XmNrightAttachment, XmATTACH_FORM); n++;
771     scope_drawing_w = XmCreateDrawingArea (scope_w, "Drawing", args, n);
772     XtManageChild (scope_drawing_w);
773     XtAddCallback (scope_drawing_w, XmNexposeCallback, scope_callback, 0);
774     XtAddCallback (scope_drawing_w, XmNresizeCallback, scope_callback, 0);
775 }
776 
777 
778 void
scope_manage()779 scope_manage ()
780 {
781     if (!scope_w)
782 	scope_create ();
783 
784     if (!XtIsManaged (scope_w))
785 	XtManageChild (scope_w);
786 #if 1
787     else
788 	XMapRaised (XtDisplay (scope_w), XtWindow (XtParent (scope_w)));
789 #endif
790 }
791