1 // -----------------------------------------------------------------------------
2 //
3 //  Copyright (C) 2006-2018 Fons Adriaensen <fons@linuxaudio.org>
4 //
5 //  This program is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation; either version 2 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 //
18 // -----------------------------------------------------------------------------
19 
20 
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include "styles.h"
25 #include "global.h"
26 #include "bformat.h"
27 #include "mainwin.h"
28 
29 
30 static const char *laba [4] = { "LF", "RF", "LB", "RB" };
31 static const char *labb [4] = { "W", "X", "Y", "Z" };
32 
33 
Mainwin(X_rootwin * parent,X_resman * xres,int xp,int yp,Jclient * jclient)34 Mainwin::Mainwin (X_rootwin *parent, X_resman *xres, int xp, int yp, Jclient *jclient) :
35     A_thread ("Main"),
36     X_window (parent, xp, yp, 100, 100, XftColors [C_MAIN_BG]->pixel),
37     _xres (xres),
38     _stop (false),
39     _jclient (jclient)
40 {
41     char        s [1024];
42     const char  *p;
43     X_hints     H;
44 
45     _atom = XInternAtom (dpy (), "WM_DELETE_WINDOW", True);
46     XSetWMProtocols (dpy (), win (), &_atom, 1);
47     _atom = XInternAtom (dpy (), "WM_PROTOCOLS", True);
48 
49     sprintf (s, "TETRAPROC - Tetrahedral Microphone Processor - %s  [ %s ]", VERSION, jclient->jname ());
50     H.position (xp, yp);
51     H.size (1000, 170);
52     H.minsize (1000, 170);
53     H.maxsize (1000, 170);
54     H.rname (xres->rname ());
55     H.rclas (xres->rclas ());
56     x_apply (&H);
57     x_set_title (s);
58     x_resize (1000, 170);
59 
60     _confwin = new Confwin (parent, this, xres, 100, 100);
61     makegui ();
62     _bfnorm = Bformat::FM_FUMA;
63     p = xres->get (".bformat", "fuma");
64     if (p)
65     {
66 	if (!strcmp (p, "sn3d")) _bfnorm = Bformat::FM_SN3D;
67 	if (!strcmp (p, "n3d"))  _bfnorm = Bformat::FM_N3D;
68     }
69     setformat ();
70 
71     x_map ();
72     XFlush (dpy ());
73 
74     _jclient->set_hpfil (_f_hpfil->get_val ());
75     _jclient->set_mute (_kmute = 0);
76     _jclient->set_invb (_kinvb = 0);
77     _jclient->set_endf (0);
78     _jclient->set_meter (Jclient::METER_MON);
79     _jclient->set_monit (Jclient::MONIT_REC);
80     _jclient->set_azim (-_f_azim->get_val ());
81     _jclient->set_elev (_f_elev->get_val ());
82     _jclient->set_angle (_f_angle->get_val ());
83     _jclient->set_direc (_f_direc->get_val ());
84     _jclient->set_xtalk (0);
85     _jclient->set_mono (0);
86     _jclient->set_volum (_f_volum->get_val ());
87 
88     set_time (0);
89     inc_time (100000);
90 }
91 
92 
~Mainwin(void)93 Mainwin::~Mainwin (void)
94 {
95 }
96 
97 
process(void)98 int Mainwin::process (void)
99 {
100     int e;
101 
102     if (_stop) handle_stop ();
103     e = get_event_timed ();
104     switch (e)
105     {
106     case EV_TIME:
107         handle_time ();
108 	break;
109     }
110     return e;
111 }
112 
113 
handle_event(XEvent * E)114 void Mainwin::handle_event (XEvent *E)
115 {
116     switch (E->type)
117     {
118     case Expose:
119 	expose ((XExposeEvent *) E);
120 	break;
121 
122     case ClientMessage:
123         clmesg ((XClientMessageEvent *) E);
124         break;
125     }
126 }
127 
128 
expose(XExposeEvent * E)129 void Mainwin::expose (XExposeEvent *E)
130 {
131     if (E->count) return;
132     if (E->window == _w_level->win ()) redraw ();
133 }
134 
135 
clmesg(XClientMessageEvent * E)136 void Mainwin::clmesg (XClientMessageEvent *E)
137 {
138     if (E->message_type == _atom) _stop = true;
139 }
140 
141 
handle_time(void)142 void Mainwin::handle_time (void)
143 {
144     int   i;
145     float rms, dpk;
146 
147     for (i = 0; i < 4; i++)
148     {
149 	_jclient->get_level (i, &rms, &dpk);
150 	_meters [i]->update (rms, dpk);
151     }
152     XFlush (dpy ());
153     inc_time (50000);
154 }
155 
156 
handle_stop(void)157 void Mainwin::handle_stop (void)
158 {
159     put_event (EV_EXIT, 1);
160 }
161 
162 
handle_callb(int type,X_window * W,XEvent * E)163 void Mainwin::handle_callb (int type, X_window *W, XEvent *E)
164 {
165     int        i, k;
166     X_button   *B;
167     X_slider   *F;
168     ABconfig  *C;
169 
170     switch (type)
171     {
172     case X_callback::BUTTON | X_button::PRESS:
173 	B = (X_button *) W;
174 	k = B->cbid ();
175         switch (k)
176 	{
177 	case B_HPFIL:
178  	    B->set_stat (B->stat () ^ 1);
179 	    _jclient->set_hpfil (B->stat () ? _f_hpfil->get_val () : 1.0f);
180 	    break;
181 	case B_MUTE1:
182 	case B_MUTE2:
183 	case B_MUTE3:
184 	case B_MUTE4:
185  	    B->set_stat (B->stat () ^ 2);
186 	    _kmute ^= 1 << (k - B_MUTE1);
187 	    _jclient->set_mute (_kmute);
188 	    break;
189 	case B_ENDF:
190  	    B->set_stat (B->stat () ^ 1);
191 	    _jclient->set_endf (B->stat ());
192 	    break;
193 	case B_INVX:
194 	case B_INVY:
195 	case B_INVZ:
196  	    B->set_stat (B->stat () ^ 1);
197 	    _kinvb ^= 1 << (1 + k - B_INVX);
198 	    _jclient->set_invb (_kinvb);
199 	    break;
200 	case B_INPUT:
201 	    _b_input->set_stat (1);
202 	    _b_monit->set_stat (0);
203 	    for (i = 0; i < 4; i++)
204 	    {
205 		_t_laba [i]->x_map ();
206 		_t_labb [i]->x_unmap ();
207 	    }
208 	    _jclient->set_meter (Jclient::METER_INP);
209 	    break;
210 	case B_MONIT:
211 	    _b_input->set_stat (0);
212 	    _b_monit->set_stat (1);
213 	    for (i = 0; i < 4; i++)
214 	    {
215 		_t_laba [i]->x_unmap ();
216 		_t_labb [i]->x_map ();
217 	    }
218 	    _jclient->set_meter (Jclient::METER_MON);
219 	    break;
220 	case B_MREC:
221 	    _b_mrec->set_stat (1);
222 	    _b_mext->set_stat (0);
223 	    _jclient->set_monit (Jclient::MONIT_REC);
224 	    break;
225 	case B_MEXT:
226 	    _b_mrec->set_stat (0);
227 	    _b_mext->set_stat (1);
228 	    _jclient->set_monit (Jclient::MONIT_EXT);
229 	    break;
230 	case B_XTALK:
231  	    B->set_stat (B->stat () ^ 1);
232             _jclient->set_xtalk (B->stat ());
233 	    break;
234 	case B_MONO:
235  	    B->set_stat (B->stat () ^ 2);
236             _jclient->set_mono (B->stat ());
237 	    break;
238 	case B_CONF:
239 	    C = new ABconfig;
240 	    *C = _config;
241 	    _confwin->open (C);
242 	    break;
243 	}
244 	break;
245 
246     case X_callback::SLIDER | X_slider::MOVE:
247     case X_callback::SLIDER | X_slider::STOP:
248 	F = (X_slider *) W;
249 	k = F->cbid ();
250         switch (k)
251 	{
252 	case F_HPFIL:
253 	    if (_b_hpfil->stat ()) _jclient->set_hpfil (_f_hpfil->get_val ());
254 	    break;
255 	case F_AZIM:
256 	    _jclient->set_azim (-_f_azim->get_val ());
257 	    break;
258 	case F_ELEV:
259 	    _jclient->set_elev (_f_elev->get_val ());
260 	    break;
261 	case F_ANGLE:
262 	    _jclient->set_angle (_f_angle->get_val ());
263 	    break;
264 	case F_DIREC:
265 	    _jclient->set_direc (_f_direc->get_val ());
266 	    break;
267 	case F_VOLUM:
268 	    _jclient->set_volum (_f_volum->get_val ());
269 	    break;
270 	}
271 	break;
272 
273     case CB_CONF_CANC:
274 	C = new ABconfig;
275 	*C = _config;;
276 	_confwin->open (C);
277 	break;
278 
279     case CB_CONF_APPL:
280 	C = _confwin->config ();
281 	_config = *C;
282 	applconf ();
283 	break;
284     }
285 }
286 
287 
loadconf(void)288 void Mainwin::loadconf (void)
289 {
290     const char *p;
291 
292     p = _xres->get (".config", 0);
293     if (p && *p) _config.load (p);
294     _config._update = ABconfig::EN_ALL;
295     applconf ();
296 }
297 
298 
applconf(void)299 void Mainwin::applconf (void)
300 {
301     int err = 0;
302     int upd = _config._update & (ABconfig::EN_CONV | ABconfig::EN_MATR);
303 
304     if (upd) syncaudio (EV_GO_IDLE);
305     if (_config._update & ABconfig::EN_LFEQ) err |= _jclient->set_lffilt (&_config);
306     if (_config._update & ABconfig::EN_MATR) err |= _jclient->set_matrix (&_config);
307     if (_config._update & ABconfig::EN_CONV) err |= _jclient->set_convol (&_config);
308     if (_config._update & ABconfig::EN_PMEQ) err |= _jclient->set_hffilt (&_config);
309     if (upd) syncaudio (EV_GO_PROC);
310     _confwin->applyrep (err);
311     _t_mcid->set_text (_config._micident);
312 }
313 
314 
setformat(void)315 void Mainwin::setformat (void)
316 {
317     _jclient->set_form (_bfnorm);
318     switch (_bfnorm)
319     {
320     case Bformat::FM_FUMA:
321         _t_form->set_text ("FuMa");
322 	_t_form->set_color (XftColors [C_DISP_BG]->pixel, XftColors [C_DISP_FG1]);
323 	break;
324     case Bformat::FM_SN3D:
325         _t_form->set_text ("SN3D");
326 	_t_form->set_color (XftColors [C_DISP_BG]->pixel, XftColors [C_DISP_FG2]);
327 	break;
328     case Bformat::FM_N3D:
329         _t_form->set_text ("N3D");
330 	_t_form->set_color (XftColors [C_DISP_BG]->pixel, XftColors [C_DISP_FG2]);
331 	break;
332     default:
333         _t_form->set_text ("???");
334 	_t_form->set_color (XftColors [C_DISP_BG]->pixel, XftColors [C_DISP_FG2]);
335     }
336 }
337 
338 
syncaudio(int e)339 void Mainwin::syncaudio (int e)
340 {
341     send_event (e, 1);
342     e = get_event (1 << e);
343 }
344 
345 
makegui(void)346 void Mainwin::makegui (void)
347 {
348     int i, x, y;
349 
350     x = 10;
351     y = 10;
352     Bst0.size.x = 40;
353     Bst0.size.y = 18;
354     _b_hpfil = new X_tbutton (this, this, &Bst0, x, y + 12, "HPF", 0, B_HPFIL);
355     _b_hpfil->set_stat (1);
356     _b_hpfil->x_map ();
357     (new X_hscale (this, &sca_hpfr, x + 55, y, 18))->x_map ();
358     _f_hpfil = new X_hslider (this, this, &Fst1, &sca_hpfr, x + 55, y + 18, 13, F_HPFIL);
359     _f_hpfil->set_val (20.0f);
360     _f_hpfil->x_map ();
361 
362     y += 50;
363     addtext (this, &Tst1, x, y + 2, 45, 12, "Mute", -1);
364     _b_mute1 = new X_tbutton (this, this, &Bst0, x +  50, y, "LF", 0, B_MUTE1);
365     _b_mute1->x_map ();
366     _b_mute2 = new X_tbutton (this, this, &Bst0, x +  92, y, "RF", 0, B_MUTE2);
367     _b_mute2->x_map ();
368     _b_mute3 = new X_tbutton (this, this, &Bst0, x + 134, y, "LB", 0, B_MUTE3);
369     _b_mute3->x_map ();
370     _b_mute4 = new X_tbutton (this, this, &Bst0, x + 176, y, "RB", 0, B_MUTE4);
371     _b_mute4->x_map ();
372     y += 23;
373     addtext (this, &Tst1, x, y + 2, 45, 12, "Invert", -1);
374     _b_invx = new X_tbutton (this, this, &Bst0, x +  50, y, "X", 0, B_INVX);
375     _b_invx->x_map ();
376     _b_invy = new X_tbutton (this, this, &Bst0, x +  92, y, "Y", 0, B_INVY);
377     _b_invy->x_map ();
378     _b_invz = new X_tbutton (this, this, &Bst0, x + 134, y, "Z", 0, B_INVZ);
379     _b_invz->x_map ();
380     Bst0.size.x = 60;
381     Bst0.size.y = 18;
382     _b_endf = new X_tbutton (this, this, &Bst0, x + 176, y, "EndFire", 0, B_ENDF);
383     _b_endf->x_map ();
384     y += 45;
385     Bst0.size.x = 50;
386     Bst0.size.y = 18;
387     _b_conf = new X_tbutton (this, this, &Bst0, x, y, "Config", 0, B_CONF);
388     _b_conf->x_map ();
389 
390     _w_level = new X_subwin (this, 285, 5, 502, 124, XftColors [C_DISP_BG]->pixel);
391     y = 24;
392     for (i = 0; i < 4; i++)
393     {
394         _meters [i] = new Kmeter (_w_level, 26, y + 4, Kmeter::HOR, Kmeter::K20);
395 	_meters [i]->x_map ();
396 	_t_laba [i] = new X_textln (_w_level, &Tst2, 2, y, 24, 14, laba [i], 0);
397 	_t_labb [i] = new X_textln (_w_level, &Tst2, 2, y, 24, 14, labb [i], 0);
398 	_t_labb [i]->x_map ();
399          y += Kmeter::LINEW + 8;
400     }
401     _t_mcid = new X_textip (_w_level, 0, &Tst2,   2, 102, 300, 18, 64);
402     _t_mcid->x_map ();
403     _t_form = new X_textip (_w_level, 0, &Tst2, 420, 102,  80, 18, 64);
404     _t_form->x_map ();
405     _w_level->x_add_events (ExposureMask);
406     _w_level->x_map ();
407 
408     x = 805;
409     y = 5;
410     (new X_hscale (this, &sca_elev, x, y, 18))->x_map ();
411     _f_elev = new X_hslider (this, this, &Fst1, &sca_elev, x, y + 17, 13, F_ELEV);
412     _f_elev->set_val (0.0f);
413     _f_elev->x_map ();
414     y += 30;
415     (new X_hscale (this, &sca_azim, x, y, 18))->x_map ();
416     _f_azim = new X_hslider (this, this, &Fst1, &sca_azim, x, y + 17, 13, F_AZIM);
417     _f_azim->set_val (0.0f);
418     _f_azim->x_map ();
419     y += 30;
420     (new X_hscale (this, &sca_angle, x, y, 18))->x_map ();
421     _f_angle = new X_hslider (this, this, &Fst1, &sca_angle, x, y + 17, 13, F_ANGLE);
422     _f_angle->set_val (0.25f);
423     _f_angle->x_map ();
424     y += 30;
425     (new X_hscale (this, &sca_direc, x, y, 18))->x_map ();
426     _f_direc = new X_hslider (this, this, &Fst1, &sca_direc, x, y + 17, 13, F_DIREC);
427     _f_direc->set_val (1.00f);
428     _f_direc->x_map ();
429 
430     x = 190;
431     y = 142;
432     addtext (this, &Tst1, x, y, 50, 18, "Meters", 1);
433     Bst0.size.x = 45;
434     Bst0.size.y = 18;
435     _b_input = new X_tbutton (this, this, &Bst0, x +  60, y, "Inp", 0, B_INPUT);
436     _b_input->x_map ();
437     _b_monit = new X_tbutton (this, this, &Bst0, x + 106, y, "Mon", 0, B_MONIT);
438     _b_monit->x_map ();
439     _b_monit->set_stat (1);
440     x += 160;
441     addtext (this, &Tst1, x, y, 50, 18, "Monit", 1);
442     _b_mrec  = new X_tbutton (this, this, &Bst0, x +  60, y, "Rec", 0, B_MREC);
443     _b_mrec->x_map ();
444     _b_mrec->set_stat(1);
445     _b_mext  = new X_tbutton (this, this, &Bst0, x + 106, y, "Ext", 0, B_MEXT);
446     _b_mext->x_map ();
447     x += 180;
448     addtext (this, &Tst1, x, y, 50, 18, "Volume",  1);
449     (new X_hscale (this, &sca_volume, x + 60, y - 12, 18))->x_map ();
450     _f_volum = new X_hslider (this, this, &Fst1, &sca_volume, x + 60, y + 5, 13, F_VOLUM);
451     _f_volum->set_val (-10.0f);
452     _f_volum->x_map ();
453     Bst0.size.x = 50;
454     Bst0.size.y = 18;
455     _b_xtalk = new X_tbutton (this, this, &Bst0, x + 355, y, "Xtalk", 0, B_XTALK);
456     _b_xtalk->x_map ();
457     _b_mono  = new X_tbutton (this, this, &Bst0, x + 406, y, "Mono", 0, B_MONO);
458     _b_mono->x_map ();
459 }
460 
461 
addtext(X_window * W,X_textln_style * T,int xp,int yp,int xs,int ys,const char * text,int align)462 void Mainwin::addtext (X_window *W, X_textln_style *T, int xp, int yp, int xs, int ys, const char *text, int align)
463 {
464     (new X_textln (W, T, xp, yp, xs, ys, text, align))->x_map ();
465 }
466 
467 
redraw(void)468 void Mainwin::redraw (void)
469 {
470     int     i, y;
471     X_draw  D (dpy (), _w_level->win (), dgc (), 0);
472     XImage  *I = _meters [0]->scale ();
473 
474     D.setcolor (XftColors [C_MAIN_DS]->pixel);
475     D.move (0, 122);
476     D.draw (0, 0);
477     D.draw (500, 0);
478     D.setcolor (XftColors [C_MAIN_LS]->pixel);
479     D.move (501, 0);
480     D.draw (501, 123);
481     D.draw (1, 123);
482 
483     y = 24;
484     XPutImage (dpy (), _w_level->win (), dgc (), I, 0, 4, 26, y - 14, I->width, 16);
485     for (i = 1; i < 4; i++)
486     {
487         XPutImage (dpy (), _w_level->win (), dgc (), I, 0, 0, 26, y + 12, I->width, 4);
488 	y += Kmeter::LINEW + 8;
489     }
490     XPutImage (dpy (), _w_level->win (), dgc (), I, 0, 0, 26, y + 12, I->width, 16);
491 
492 }
493 
494