1 /*
2 * ui.cc
3 * DIN Is Noise is copyright (c) 2006-2021 Jagannathan Sampath
4 * DIN Is Noise is released under GNU Public License 2.0
5 * For more information, please visit https://dinisnoise.org/
6 */
7 
8 #include "ui_list.h"
9 #include "din.h"
10 #include "morse_code.h"
11 #include "console.h"
12 #include "curve_editor.h"
13 #include "tcl_interp.h"
14 #include "command.h"
15 #include "chrono.h"
16 #include "keyboard_keyboard.h"
17 #include "viewwin.h"
18 #include "authors_note.h"
19 #include "fft.h"
20 #include "main.h"
21 #include "curve_picker.h"
22 #include "capturer.h"
23 #include "fractaliser.h"
24 #include "warper.h"
25 #include "recorder.h"
26 #include "mondrian.h"
27 #include "binaural_drones.h"
28 #include "spiraler.h"
29 #include "circler.h"
30 #include "rose_milker.h"
31 #include "sine_mixer.h"
32 #include <fstream>
33 #include <string>
34 #include "container.h"
35 
36 using namespace std;
37 
38 extern string user_data_dir;
39 extern curve_editor waved, comed, octed, veled, drone_mod_ed, ran_mod_ed, ran_wh_ed, pitch_vol_ed, pomo_ed, delayed, drone_pend_ed, fed;
40 extern int mousex, mousey, mouseyy;
41 extern string INSTRUMENT;
42 extern int rmb;
43 extern oscilloscope scope;
44 extern int line_height;
45 extern sine_mixer sinemixer;
46 extern const char* voice_is_lbls[];
47 extern const int NUM_INSTRUMENTS;
48 
ui_list()49 ui_list::ui_list () :
50 vlis (&cb_voice, &fdr_voice, &din0.dinfo.voice),
51 glis (&cb_gater, &fdr_gater, &din0.dinfo.gater),
52 dlis (&cb_delay, &fdr_delay, &din0.dinfo.delay)
53 {
54   current = 0;
55   prev = 0;
56   crved = 0;
57   esct = -1;
58 	rmb_clicked = 0;
59 	LISTEN (ol_voice_is, &vivl);
60 }
61 
set_current(ui * u)62 void ui_list::set_current (ui* u) {
63 
64   if (current) {
65     current->leave ();
66     ui::over = prev = current;
67   }
68 
69   current = u;
70   cons << YELLOW << "@ " << current->name << eol;
71 
72   if (u->ed)
73 		crved = dynamic_cast<curve_editor*>(u);
74 	else
75     uis[0] = current;
76 
77 	current->enter ();
78 
79 }
80 
load_editor(ui * ed)81 void ui_list::load_editor (ui* ed) {
82 	main_menu.setup_tabs (ed);
83 	set_current (ed);
84 }
85 
bg()86 void ui_list::bg () {
87 
88   current->calc_win_mouse ();
89 
90   for (vector<ui*>::size_type i = 1, j = uis.size(); i < j; ++i) uis[i]->bg (); // bg for instruments and editors
91 
92   // fade fx for voice, gater & delay
93   eval_fade (fdr_voice, cb_voice);
94   flash_gater (); // flashes in sync with gater value
95   eval_fade (fdr_delay, cb_delay);
96 
97 }
98 
eval_fade(fader & fdr,checkbutton & cb)99 float ui_list::eval_fade (fader& fdr, checkbutton& cb) {
100 	if (fdr.eval ()) cb.blend_on_off_color (fdr.alpha);
101 	return fdr.amount;
102 }
103 
flash_gater()104 void ui_list::flash_gater () {
105 
106 	static color clr [2] = {color (1, 0, 0), color (0, 1, 0)};
107 	float dg = aout.gatr [aout.last_sample];
108 	if (fdr_gater.eval ()) {
109 		cb_gater.blend_on_off_color (fdr_gater.alpha);
110 		color& c = const_cast<color&> (cb_gater.clr);
111 		c *= dg;
112 	} else {
113 		int gi = din0.dinfo.gater;
114 		cb_gater.set_color (dg * clr [gi].r, dg * clr [gi].g, dg * clr[gi].b);
115 	}
116 
117 }
118 
is_widget_on_screen(widget * w,ui * scr)119 int ui_list::is_widget_on_screen (widget* w, ui* scr) {
120   vector<widget*>& widgets = widgets_of [scr];
121   for (int i = 0, j = widgets.size (); i < j; ++i) if (w == widgets[i]) return 1;
122   return 0;
123 }
124 
125 
set_editor(const string & name,int screen)126 int ui_list::set_editor (const string& name, int screen) {
127   if (screen > 0) {
128     ui* ei = 0;
129     for (int i = 0, j = uis.size(); i < j; ++i) {
130       if (uis[i]->name == name) {
131         ei = uis[i];
132         break;
133       }
134     }
135     if (ei) {
136       ed [screen - 2] = ei;
137       return 1;
138     } else {
139       cmdlst.result = "bad editor name";
140       return 0;
141     }
142   } else {
143     cmdlst.result = "bad screen number (valid: 2 to 8)";
144     return 0;
145   }
146 }
147 
draw()148 void ui_list::draw () {
149   glClear (GL_COLOR_BUFFER_BIT);
150   glMatrixMode (GL_MODELVIEW);
151   glLoadIdentity ();
152   current->draw ();
153   glMatrixMode (GL_PROJECTION);
154   glLoadIdentity ();
155   glOrtho (0, view.xmax, 0, view.ymax, 0, 1);
156   vector<widget*> widgets = widgets_of [current];
157   for (vector<widget*>::size_type i = 0, j = widgets.size (); i < j; ++i) {
158     widget* wi = widgets[i];
159     if (wi->visible) wi->draw ();
160   }
161 }
162 
163 // all screens
164 ui* SCREENS [] = {
165 	&keybd2,
166 	&mondrian0,
167 	&din0,
168 	&binaural_drones0,
169   &din0.waved,
170 	&din0.droneed,
171 	&drone_mod_ed,
172   &din0.moded,
173   &din0.gated,
174 	&keybd2.waved,
175 	&keybd2.attacked,
176 	&keybd2.decayed,
177 	&keybd2.veled,
178   &delayed,
179   &octed,
180   &comed,
181   &mc.ed,
182 	&mondrian0.waved,
183 	&mondrian0.attacked,
184 	&mondrian0.decayed,
185 	&binaural_drones0.waved,
186 	&ran_mod_ed,
187 	&ran_wh_ed,
188 	&pitch_vol_ed,
189 	&pomo_ed,
190 	&noiser::ed,
191 	&drone_pend_ed,
192 	&fed,
193   &fractaliser_.ed,
194 	&warper_.ed,
195 	&spiraler_.scr.sin_ed,
196 	&spiraler_.scr.cos_ed,
197 	&spiraler_.scr.rad_ed,
198 	&rosemilker.scr.sin_ed,
199 	&rosemilker.scr.cos_ed,
200 	&circler_.scr.sin_ed,
201 	&circler_.scr.cos_ed,
202 	&circler_.scr.rad_ed,
203 	&sinemixer.sin_ed,
204 	&rosemilker.scr.rad_ed,
205   &din0.dinfo.gravity.mod.ed,
206   0
207 };
208 
show_hide_widgets(int sh)209 void ui_list::show_hide_widgets (int sh) {
210 	for (ui** p = SCREENS; *p != 0; ++p) {
211 		ui* u = *p;
212 		vector<widget*>& vu = widgets_of [u];
213 		int j = vu.size ();
214 		if (j) {
215 			if (sh)
216 				for (int i = 0; i < j; ++i) vu[i]->show();
217 			else
218 				for (int i = 0; i < j; ++i) vu[i]->hide();
219 		}
220 	}
221 	curve_picker.hide ();
222 }
223 
add_widgets()224 void ui_list::add_widgets () {
225 
226 	widget* wall [] = {&cons, &main_menu, &b_settings}; // appears on all screens
227 	for (ui** p = SCREENS; *p != 0; ++p) for (int i = 0; i < 3; ++i) widgets_of[*p].push_back (wall[i]);
228 
229 	// add selectors to microtonal keyboard and mondrian
230 	mkb_selector.set_listener (&din0);
231 	mon_selector.set_listener (&mondrian0);
232 
233 	// add fft display on waveform editors
234   ui* uwav [] = {&din0.waved, &keybd2.waved, &din0.droneed, &mondrian0.waved, &binaural_drones0.waved};
235   for (int i = 0; i < 5; ++i) widgets_of[uwav[i]].push_back (&fft0);
236 
237   // add plugin browser to these editors
238   ui* ueds [] = {
239     &din0.waved,
240 		&din0.moded,
241     &din0.droneed,
242     &drone_mod_ed,
243     &keybd2.waved,
244 		&fractaliser_.ed,
245 		&warper_.ed,
246     &mondrian0.waved,
247 		&din0.gated,
248 		&binaural_drones0.waved,
249     &ran_mod_ed,
250     &pitch_vol_ed,
251     &pomo_ed,
252     &drone_pend_ed,
253     &noiser::ed,
254     &din0.dinfo.gravity.mod.ed,
255   };
256 
257   for (int i = 0; i < 16; ++i) widgets_of[ueds[i]].push_back (&plugin__browser);
258 
259   // depth, bpm spinners to drone pendulum editor
260 	widget* dpeuw [] = {&dpeu.depth, &dpeu.bpm};
261 	widget_load ("d_dpeu", dpeuw, 2);
262 	dpeu.depth.set ("Depth", 1.0f, -MILLION, MILLION, &dpeul, 0);
263 	dpeu.bpm.set ("BPM", 1.0f, -MILLION, MILLION, &dpeul, 0);
264 	widgets_of [&drone_pend_ed].push_back (&dpeu.depth);
265 	widgets_of [&drone_pend_ed].push_back (&dpeu.bpm);
266 
267 	// add widgets for curve editors only
268   for (ui** p = SCREENS + NUM_INSTRUMENTS; *p != 0; ++p) {
269     ui* u = *p;
270 		vector<widget*>& wu = widgets_of [u];
271 		curve_editor* ce = dynamic_cast<curve_editor*>(u);
272 		wu.insert (wu.begin(), &ce->capturer);
273 		wu.insert (wu.begin(), &ce->pomo);
274     wu.push_back (&curve_picker);
275 		ce->capturer.setup (ce);
276 		ce->pomo.setup (ce);
277   }
278 
279 	// add scope to all instruments
280 	extern instrument* INSTRUMENT_PTR[];
281 	for (int i = 0; i < NUM_INSTRUMENTS; ++i) widgets_of[(ui *)INSTRUMENT_PTR[i]].push_back (&scope);
282 
283   // no menu on author's note & settings screen
284   widgets_of[&anote].push_back(&cons);
285   widgets_of[&settings_scr].push_back (&cons);
286 
287   widget* wdin [] = {
288 		&ol_voice_is,
289   	&cb_voice,
290 		&cb_gater,
291 		&cb_delay,
292 		&cb_compress,
293 		&ab_scroll_left,
294 		&ab_scroll_right,
295     &ab_scroll_up,
296 		&ab_scroll_down,
297 		&cb_show_pitch_volume_board,
298 		&cb_show_pitch_volume_drones,
299 		&cb_record,
300     &din0.dinfo.gravity,
301     &mkb_selector,
302  };
303  for (int i = 0, j = 14; i < j; ++i) widgets_of [&din0].push_back (wdin[i]);
304 
305   widget* wkeybd2 [] = {
306     &cb_delay,
307 		&cb_compress,
308     &sp_attack_time,
309 		&sp_decay_time,
310 		&sp_voices,
311 		&sp_pitch_bend,
312 		&cb_show_nearby_notes,
313 		&d_parameters,
314 		&ab_parameters,
315     &l_waveform_display,
316 		&ab_prev_wav,
317 		&ab_next_wav,
318     &cd_waveform_display,
319     &l_octave_shift,
320     &ab_octave_down,
321     &ab_octave_up,
322     &sp_octave_shift_bpm,
323 		&b_abort_octave_shift,
324 		&cb_record,
325 		&ol_trig_what
326   };
327 
328   for (int i = 0, j = 20; i < j; ++i) widgets_of [&keybd2].push_back (wkeybd2[i]);
329 
330   widget* wmondrian [] = {
331 		&l_mondrian_voices,
332     &cb_delay,
333     &cb_compress,
334     &cb_record,
335 		&mon_selector,
336   };
337 	for (int i = 0, j = 5; i < j; ++i) widgets_of [&mondrian0].push_back (wmondrian[i]);
338 	l_mondrian_voices.set_text ("Voices: ** / **");
339 
340 	widget* wsbd [] = {
341 		&cb_delay,
342 		&cb_compress,
343 		&cb_record,
344 	};
345 
346 	for (int i = 0, j = 3; i < j; ++i) widgets_of [&binaural_drones0].push_back (wsbd[i]);
347 
348 }
349 
350 
update_widgets(int wnow,int hnow,int wprev,int hprev)351 void ui_list::update_widgets (int wnow, int hnow, int wprev, int hprev) {
352 
353   main_menu.update ();
354 
355   plugin__browser.update ();
356 
357   cb_gater.set_text ("Gater");
358   cb_delay.set_text ("Delay");
359   cb_compress.set_text ("Compressor");
360   b_settings.set_text ("Settings");
361 	cb_record.set_text ("Record");
362 	l_mondrian_voices.update ();
363 
364 	int lh = line_height;
365 	int y = update_bottom_line ();
366   y += lh;
367 
368   arrow_button* scrl [] = {&ab_scroll_left, &ab_scroll_right, &ab_scroll_up, &ab_scroll_down};
369   int nscrls = 4;
370   int w = ab_scroll_left.extents.width;
371   int dw [] = {5, 7, 0, 0};
372   int x = (view.xmax - nscrls * w) / 2;
373   for (int i = 0; i < nscrls; ++i) {
374     arrow_button* ab = scrl[i];
375     ab->set_pos (x, y);
376     x = x + w + dw[i];
377   }
378 
379 	x += w;
380   cb_show_pitch_volume_board.set_pos (x, ab_scroll_down.extents.bottom - fnt.lift);
381   cb_show_pitch_volume_board.set_text ("i");
382 
383 	x += w;
384   cb_show_pitch_volume_drones.set_pos (x + 1, ab_scroll_down.extents.bottom - fnt.lift);
385   cb_show_pitch_volume_drones.set_text ("j");
386 
387   d_parameters.set_text ("Parameters");
388 
389   sp_attack_time.update ();
390   sp_decay_time.update ();
391   sp_voices.update ();
392   sp_pitch_bend.update ();
393   cb_show_nearby_notes.set_text ("Show nearby notes");
394 
395   l_waveform_display.update ();
396 
397   l_octave_shift.update ();
398   ab_octave_up.update ();
399   ab_octave_down.update ();
400   sp_octave_shift_bpm.update ();
401 
402 	settings_scr.update_widgets ();
403 
404 }
405 
dofft()406 void ui_list::dofft () {
407   if (crved && crved->num_curves && !fft0.folded ()) fft0.go (crved->curveinfo[0].curve);
408 }
409 
after_fade(fader & f)410 void fade_button_listener::after_fade (fader& f) {
411 	cb->enabled = 1;
412 	f.afl = 0;
413 }
414 
changed(checkbutton & cb)415 void voice_listener::changed (checkbutton& cb) {
416 	fade_button_listener::changed (cb);
417 	MENU.next_tab = MENUP.cb_mkb_voice;
418 	MENU.next_tab_instr = &din0;
419 }
420 
fade_button_listener(checkbutton * _cb,fader * _f,int * _t)421 fade_button_listener::fade_button_listener (checkbutton* _cb, fader* _f, int* _t) {cb = _cb; f = _f; target = _t; lsnr = 0;}
422 
changed(checkbutton & cb)423 void fade_button_listener::changed (checkbutton& cb) {
424   if (f->on == 0) {
425 		int on = cb.is_on ();
426 		*target = on;
427     if (on) f->set (0, 1); else f->set (1, 0);
428 		cb.enabled = 0;
429 		f->afl = this;
430   }
431 }
432 
changed(checkbutton & cb)433 void compress__listener::changed (checkbutton& cb) {
434   din0.dinfo.compress = cb.is_on ();
435 }
436 
clicked(button & b)437 void settings__listener::clicked (button& b) {
438 	uis.set_current (&uis.settings_scr);
439 }
440 
changed(field & f)441 void pitch_bend_listener::changed (field& f) {
442   PITCH_BEND_PER_PIXEL = f;
443   PITCH_BEND = PITCH_BEND_PER_PIXEL * 100;
444 }
445 
changed(checkbutton & cb)446 void pitch_bend_listener::changed (checkbutton& cb) {
447   keybd2.show_nearby_notes = cb.state;
448 }
449 
clicked(button & b)450 void waveform_display_listener::clicked (button& b) {
451 	CRVED = &keybd2.waved;
452   if (&b == &uis.ab_prev_wav) {
453     CRVED->win.calc ();
454     CRVED->load_curve (-1);
455   } else {
456     CRVED->win.calc ();
457     CRVED->load_curve (+1);
458   }
459 }
460 
clicked(button & b)461 void parameters_listener::clicked (button& b) {
462   arrow_button& ab = dynamic_cast<arrow_button&> (b);
463   if (ab.dir == arrow_button::down) {
464     ab.set_dir (arrow_button::right);
465     uis.d_parameters.hide (widget::only_children);
466   } else {
467     uis.d_parameters.show ();
468     ab.set_dir (arrow_button::down);
469   }
470   ab.show ();
471 }
472 
~ui_list()473 ui_list::~ui_list () {
474 
475 	dlog << "--- destroying uis ---" << endl;
476 
477 	DEFINE_PARAMETERS
478 	widget_save ("d_parameters", pw, npars);
479 
480 	widget* dpeuw [] = {&dpeu.depth, &dpeu.bpm};
481 	widget_save ("d_dpeu", dpeuw, 2);
482 
483 	dlog << "--- destroyed uis ---" << endl;
484 
485 }
486 
enter()487 void ui::enter () {
488 	warp_mouse (prev_mousex, prev_mousey);
489 }
490 
leave()491 void ui::leave () {
492   if (hide_menu () == 0) {
493     prev_mousex = mousex;
494     prev_mousey = mousey;
495   }
496 	if (!ed) scope.save_current_instrument ();
497 	mouse_slider0.deactivate ();
498 }
499 
500 extern const float MIN_TIME;
501 
changed(field & F)502 void attack_val::changed (field& F) {
503 	float f = F;
504 	if (equals (f, 0.0f)) ATTACK_TIME = MIN_TIME; else ATTACK_TIME = f;
505 }
506 
changed(field & F)507 void decay_val::changed (field& F) {
508 	float f = F;
509 	if (equals (f, 0.0f)) DECAY_TIME = MIN_TIME; else DECAY_TIME = f;
510 }
511 
changed(field & F)512 void voices_val::changed (field& F) {
513 	int i = F;
514 	int j = i; if (i < 1) j = 1;
515   NOTE_VOLUME = 1.0f / j;
516   keybd2.calc_visual_params ();
517 }
518 
clicked(button & b)519 void scroll_arrow_listener::clicked (button& b) {
520   if (&b == &uis.ab_scroll_left) {
521     din0.scroll (-din0.dinfo.scroll.dx, 0, 0);
522   } else if (&b == &uis.ab_scroll_right) {
523     din0.scroll (din0.dinfo.scroll.dx, 0, 0);
524   } else if (&b == &uis.ab_scroll_up) {
525     din0.scroll (0, -din0.dinfo.scroll.dy, 0);
526   } else {
527     din0.scroll (0, din0.dinfo.scroll.dy, 0);
528   }
529 }
530 
changed(checkbutton & cb)531 void show_pitch_volume_listener::changed (checkbutton& cb) {
532 	if (&cb == &uis.cb_show_pitch_volume_board)
533 		din0.dinfo.show_pitch_volume.board = cb.state;
534 	else
535 		din0.dinfo.show_pitch_volume.drones = cb.state;
536 }
537 
clicked(button & b)538 void fft::clicked (button& b) {
539   if (ab_fold.dir == arrow_button::down) {
540     ab_fold.set_dir (arrow_button::right);
541     l_title.hide (widget::only_children);
542 		ab_fold.show ();
543   } else {
544     ab_fold.set_dir (arrow_button::down);
545     l_title.show ();
546     uis.dofft ();
547   }
548 }
549 
folded()550 int fft::folded () {
551   return (ab_fold.dir == arrow_button::right);
552 }
553 
handle_plugin(widget * which,int what)554 void ui_list::handle_plugin (widget* which, int what) {
555   enum {INSTALL = 1, REMOVE = 0};
556  	ui* ueds [] = {
557 		&din0.waved,
558 		&din0.moded,
559 		&din0.droneed,
560 		&keybd2.waved,
561 		&fractaliser_.ed
562 	};
563 
564 	int num_editors = 5;
565   if (what == INSTALL) {
566     for (int i = 0; i < num_editors; ++i) widgets_of[ueds[i]].push_back (which);
567   } else {
568     for (int i = 0; i < num_editors; ++i) {
569       vector<widget*>& widgets = widgets_of [ueds[i]];
570       vector<widget*>::iterator iter = find (widgets.begin (), widgets.end(), which);
571       if (iter != widgets.end()) widgets.erase (iter);
572     }
573   }
574   main_menu.toggle ();
575 }
576 
update_bottom_line()577 int ui_list::update_bottom_line () {
578 	widget** winst = 0;
579 	widget* wdin[] = {&cb_voice, &cb_gater, &cb_delay, &cb_compress, &main_menu.b_menu, &b_settings, &cb_record};
580 	widget* wmon[] = {&l_mondrian_voices, &cb_delay, &cb_compress,  &main_menu.b_menu, &b_settings, &cb_record};
581 	widget* wcom[] = {&cb_delay, &cb_compress, &main_menu.b_menu, &b_settings, &cb_record};
582 	widget* wed [] = {&main_menu.b_menu, &b_settings};
583 	instrument* inst = get_current_instrument ();
584 	int n = 0;
585 	if (inst == &din0) {
586 		winst = wdin;
587 		n = 7;
588 	} else if (inst == &mondrian0) {
589 		winst = wmon;
590 		n = 6;
591 	} else if (inst == &binaural_drones0 || inst == &keybd2) {
592 		winst = wcom;
593 		n = 5;
594 	} else {
595 		winst = wed;
596 		n = 2;
597 	}
598 	int dx = 25, w = 0;
599 	for (int i = 0; i < n; ++i) w += winst[i]->extents.width;
600 	w += n * dx;
601 	int x = (view.xmax - w) / 2, y = 2; //(int)(0.25f * get_line_height() + 0.5);
602 	for (int i = 0; i < n; ++i) {
603 		widget& b = *winst[i];
604 		const box<int>& e = b.extents;
605 		b.set_extents (x, y, x + e.width, y + e.height);
606 		b.set_pos (x, y);
607 		x = e.right + dx;
608 	}
609 
610 	ol_voice_is.set_pos (cb_voice.posx - 3 * ol_voice_is.left.extents.width - 2, cb_voice.posy);
611 	return y;
612 }
613 
remove(widget * w)614 int ui_list::remove (widget* w) {
615 	return erase (widgets_of [current], w);
616 }
617 
add(ui * u,widget * w)618 void ui_list::add (ui* u, widget* w) { widgets_of [u].push_back (w); }
619 
escape_from_things()620 int ui_list::escape_from_things () {
621 
622   int ret = 1;
623   if (UI_OFF) turn_on_ui ();
624 	else if (mkb_selector()) mkb_selector.abort ();
625   else if (mon_selector()) mon_selector.abort ();
626   else if (mouse_slider0.deactivate ()) ;
627 	else if (esc_octave_shift (get_current_instrument()));
628   else if (main_menu.b_close.visible) main_menu.b_close.call_listener ();
629 	else if (main_menu.show) main_menu.toggle ();
630 	else if (current->ed) ret = current->esc();
631 	else if (current == &din0) {
632     if (din0.gab.n) din0.gab.abort ();
633 		else if (din0.moving_drones) din0.toggle_moving_drones ();
634 		else if (din0.adding) {
635       din0.adding = 0;
636       cons << RED << "Stopped adding drones!" << eol;
637       add (&din0, &mkb_selector);
638     }
639     else if (din0.stopwanding()) ;
640     else if (din0.meshh.create) din0.stop_creating_mesh ();
641 		else if (din0.create_drone_pend) din0.stop_creating_drone_pendulum ();
642 		else if (din0.finish_phrase_recording());
643 		else if (din0.dinfo.gravity.stop_editing ());
644 		else ret = 0;
645 	}
646 	else if (keybd2.turn_off_bend ());
647 	else if (mondrian0.stop_doing_stuff ());
648 	else if (binaural_drones0.aborted ());
649 	else if (current == &settings_scr) settings_scr.clicked (settings_scr.b_go_back);
650   else ret = 0;
651   return ret;
652 }
653 
is_menu_visible()654 int is_menu_visible () {
655 	return uis.main_menu.show;
656 }
657 
abort_selectors()658 void abort_selectors () {
659 	mon_selector.abort ();
660 	mkb_selector.abort ();
661 }
662 
PICKED_OPTION(ui_list,trig_what_lis)663 PICKED_OPTION (ui_list,trig_what_lis) {
664 	int& tw = keybd2.trig_what;
665 	tw = !tw;
666 	extern const char* keys_trig_what [];
667 	set_label (l, keys_trig_what, tw);
668 }
669 
PICKED_OPTION(ui_list,ol_voice_is_lis)670 PICKED_OPTION (ui_list, ol_voice_is_lis) {
671 	din0.dinfo.voice_is_voice = !din0.dinfo.voice_is_voice;
672 	extern ui_list uis;
673 	const char* viv = voice_is_lbls [din0.dinfo.voice_is_voice];
674 	uis.cb_voice.set_text (viv);
675 	MENU.handle_voice_tab_items (viv);
676 }
677 
VALUE_CHANGED(ui_list,dpeu_lis)678 VALUE_CHANGED (ui_list, dpeu_lis) {
679 	din0.update_drone_pendulums ();
680 }
681