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