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