1 /*
2  * Copyright (C) 2013 Andreas Degert
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  * --------------------------------------------------------------------------
18  */
19 
20 #include "engine.h"
21 
22 /****************************************************************
23  ** class TunerSwitcher
24  */
25 
26 static const int no_note = 1000;
27 static const int bad_note = 1002;
28 
is_no_note(float n)29 inline bool is_no_note(float n) {
30     return std::abs(n - no_note) < 1;
31 }
32 
TunerSwitcher(gx_preset::GxSettings & settings_,gx_engine::GxEngine & engine_)33 TunerSwitcher::TunerSwitcher(gx_preset::GxSettings& settings_, gx_engine::GxEngine& engine_)
34     : settings(settings_),
35       engine(engine_),
36       display(),
37       set_state(),
38       selection_done(),
39       switcher_conn(),
40       timeout_conn(),
41       current_note(),
42       state(normal_mode),
43       old_engine_state(),
44       new_engine_state(),
45       old_tuner_active(),
46       new_tuner_active(),
47       last_bank_idx(),
48       last_preset_idx() {
49 }
50 
display_bank_key(int idx)51 bool TunerSwitcher::display_bank_key(int idx) {
52     last_bank_idx = settings.banks.size() - idx - 1;
53     Glib::ustring bank = settings.banks.get_name(last_bank_idx);
54     if (bank.empty()) {
55 	display("--", "--");
56 	return false;
57     }
58     display(bank, "");
59     return true;
60 }
61 
display_preset_key(int idx)62 bool TunerSwitcher::display_preset_key(int idx) {
63     last_preset_idx = idx;
64     Glib::ustring bank = settings.banks.get_name(last_bank_idx);
65     if (bank.empty()) {
66 	display("??", gx_system::to_string(idx+1));
67 	return false;
68     }
69     gx_system::PresetFile *f = settings.banks.get_file(bank);
70     if (idx >= f->size()) {
71 	display(bank, gx_system::to_string(idx+1));
72 	return false;
73     }
74     display(bank, f->get_name(idx));
75     return true;
76 }
77 
try_load_preset()78 void TunerSwitcher::try_load_preset() {
79     switch (last_bank_idx) {
80     case mute_on:    new_engine_state = gx_engine::kEngineOff;    break;
81     case mute_off:   new_engine_state = gx_engine::kEngineOn;     break;
82     case bypass_on:  new_engine_state = gx_engine::kEngineBypass; break;
83     case bypass_off: new_engine_state = gx_engine::kEngineOn;     break;
84     case tuner_on:   new_tuner_active = true;  break;
85     case tuner_off:  new_tuner_active = false; break;
86     default:
87 	Glib::ustring bank = settings.banks.get_name(last_bank_idx);
88 	if (!bank.empty()) {
89 	    gx_system::PresetFile *f = settings.banks.get_file(bank);
90 	    if (last_preset_idx < f->size()) {
91 		Glib::ustring preset = f->get_name(last_preset_idx);
92 		if (preset != settings.get_current_name() || bank != settings.get_current_bank()) {
93 		    settings.load_preset(f, preset);
94 		}
95 	    }
96 	}
97 	break;
98     }
99 }
100 
change_state(SwitcherState newstate)101 void TunerSwitcher::change_state(SwitcherState newstate) {
102     if (state == newstate) {
103 	return;
104     }
105     state = newstate;
106     set_state(state);
107 }
108 
on_note_timeout()109 bool TunerSwitcher::on_note_timeout() {
110     if (-24 <= current_note && current_note < -10) {
111 	change_state(listening);
112 	display_bank_key(current_note - (-24));
113     } else if (current_note >= -10 && current_note <= 7) {
114 	if (display_preset_key(current_note - (-10))) {
115 	    change_state(wait_stop);
116 	} else {
117 	    change_state(listening);
118 	}
119     } else if (current_note == -25) {
120 	if (old_engine_state != gx_engine::kEngineOff) {
121 	    display("", _("MUTE"));
122 	    last_bank_idx = mute_on;
123 	} else {
124 	    display("", _("UNMUTE"));
125 	    last_bank_idx = mute_off;
126 	}
127 	change_state(wait_stop);
128     } else if (current_note == -26) {
129 	if (old_engine_state != gx_engine::kEngineBypass) {
130 	    display("", _("BYPASS"));
131 	    last_bank_idx = bypass_on;
132 	} else {
133 	    display("", _("BYPASS OFF"));
134 	    last_bank_idx = bypass_off;
135 	}
136 	change_state(wait_stop);
137     } else if (current_note < 26) {
138 	if (!old_tuner_active) {
139 	    display("", _("TUNER ON"));
140 	    last_bank_idx = tuner_on;
141 	} else {
142 	    display("", _("TUNER OFF"));
143 	    last_bank_idx = tuner_off;
144 	}
145 	change_state(wait_stop);
146     }
147     return false;
148 }
149 
on_state_timeout()150 bool TunerSwitcher::on_state_timeout() {
151     if (state == wait_start) {
152 	change_state(listening);
153 	current_note = no_note;
154 	if (settings.setting_is_preset()) {
155 	    last_bank_idx = settings.banks.get_index(settings.get_current_bank());
156 	    last_preset_idx = settings.get_current_bank_file()->get_index(settings.get_current_name());
157 	} else {
158 	    last_bank_idx = last_preset_idx = 0; //FIXME
159 	}
160     } else {
161 	assert(state == wait_stop);
162 	try_load_preset();
163 	deactivate();
164     }
165     return false;
166 }
167 
on_tuner_freq_changed()168 void TunerSwitcher::on_tuner_freq_changed() {
169     const float precision = 0.3;
170     float note = engine.tuner.get_note();
171     if (state == wait_start) {
172 	if (is_no_note(note)) {
173 	    if (!timeout_conn.connected()) {
174 		current_note = no_note;
175 		timeout_conn = Glib::signal_timeout().connect(
176 		    sigc::mem_fun(this, &TunerSwitcher::on_state_timeout),
177 		    40);
178 	    }
179 	} else {
180 	    timeout_conn.disconnect();
181 	}
182 	return;
183     }
184     if (std::abs(current_note - note) < precision) {
185 	return;
186     }
187     if (state == wait_stop) {
188 	if (is_no_note(note)) {
189 	    if (!is_no_note(current_note)) {
190 		timeout_conn.disconnect();
191 	    }
192 	    if (!timeout_conn.connected()) {
193 		current_note = no_note;
194 		timeout_conn = Glib::signal_timeout().connect(
195 		    sigc::mem_fun(this, &TunerSwitcher::on_state_timeout),
196 		    40);
197 	    }
198 	    return;
199 	}
200     }
201     timeout_conn.disconnect();
202     float n = round(note);
203     if (std::abs(note - n) < precision) {
204 	current_note = n;
205 	if (!is_no_note(current_note)) {
206 	    timeout_conn = Glib::signal_timeout().connect(
207 		sigc::mem_fun(this, &TunerSwitcher::on_note_timeout),
208 		40);
209 	}
210     } else {
211 	current_note = bad_note;
212     }
213 }
214 
activate(bool tuner_active)215 void TunerSwitcher::activate(bool tuner_active) {
216     if (get_active()) {
217 	return;
218     }
219     bool running = engine.tuner.plugin.get_on_off();
220     engine.tuner.used_for_switching(true);
221     state = normal_mode;
222     change_state(wait_start);
223     new_engine_state = old_engine_state = engine.get_state();
224     engine.set_state(gx_engine::kEngineOff);
225     new_tuner_active = old_tuner_active = tuner_active;
226     switcher_conn = engine.tuner.signal_freq_changed().connect(
227 	sigc::mem_fun(this, &TunerSwitcher::on_tuner_freq_changed));
228     if (running) {
229 	on_tuner_freq_changed();
230     }
231 }
232 
deactivate()233 void TunerSwitcher::deactivate() {
234     if (!get_active()) {
235 	return;
236     }
237     switcher_conn.disconnect();
238     timeout_conn.disconnect();
239     engine.tuner.used_for_switching(false);
240     change_state(normal_mode);
241     if (new_tuner_active && new_engine_state == gx_engine::kEngineOn) {
242 	new_engine_state = gx_engine::kEngineBypass;
243     }
244     engine.set_state(new_engine_state);
245     selection_done(new_tuner_active);
246 }
247 
toggle(bool tuner_active)248 void TunerSwitcher::toggle(bool tuner_active) {
249     if (get_active()) {
250 	deactivate();
251     } else {
252 	if (tuner_active) {
253 	    if (engine.get_state() == gx_engine::kEngineBypass) {
254 		engine.set_state(gx_engine::kEngineOn);
255 	    }
256 	    selection_done(false);
257 	} else {
258 	    activate(false);
259 	}
260     }
261 }
262