ardour
patch_change_dialog.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 Paul Davis
3  Author: Carl Hetherington <cth@carlh.net>
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, write to the Free Software
17  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 
19 */
20 
21 #include <gtkmm/stock.h>
22 #include <gtkmm/table.h>
23 
24 #include <boost/algorithm/string.hpp>
25 
26 #include "gtkmm2ext/utils.h"
27 
28 #include "midi++/midnam_patch.h"
29 
31 #include "ardour/instrument_info.h"
32 
33 #include "patch_change_dialog.h"
34 #include "gui_thread.h"
35 
36 #include "i18n.h"
37 
38 using namespace std;
39 using namespace Gtk;
40 using namespace Gtkmm2ext;
41 
45  ARDOUR::Session* session,
48  const Gtk::BuiltinStockID& ok,
49  bool allow_delete)
50  : ArdourDialog (_("Patch Change"), true)
51  , _time_converter (tc)
52  , _info (info)
53  , _time (X_("patchchangetime"), true, "", true, false)
54  , _channel (*manage (new Adjustment (1, 1, 16, 1, 4)))
55  , _program (*manage (new Adjustment (1, 1, 128, 1, 16)))
56  , _bank (*manage (new Adjustment (1, 1, 16384, 1, 64)))
57  , _ignore_signals (false)
58 {
59  Table* t = manage (new Table (4, 2));
60  Label* l;
61  t->set_spacings (6);
62  int r = 0;
63 
64  if (_time_converter) {
65 
66  l = manage (left_aligned_label (_("Time")));
67  t->attach (*l, 0, 1, r, r + 1);
68  t->attach (_time, 1, 2, r, r + 1);
69  ++r;
70 
71  _time.set_session (session);
73  _time.set (_time_converter->to (patch.time ()), true);
74  }
75 
76  l = manage (left_aligned_label (_("Patch Bank")));
77  t->attach (*l, 0, 1, r, r + 1);
78  t->attach (_bank_combo, 1, 2, r, r + 1);
79  ++r;
80 
81  _bank_combo.signal_changed().connect (sigc::mem_fun (*this, &PatchChangeDialog::bank_combo_changed));
82 
83  l = manage (left_aligned_label (_("Patch")));
84  t->attach (*l, 0, 1, r, r + 1);
85  t->attach (_patch_combo, 1, 2, r, r + 1);
86  ++r;
87 
88  _patch_combo.signal_changed().connect (sigc::mem_fun (*this, &PatchChangeDialog::patch_combo_changed));
89 
90  l = manage (left_aligned_label (_("Channel")));
91  t->attach (*l, 0, 1, r, r + 1);
92  t->attach (_channel, 1, 2, r, r + 1);
93  ++r;
94 
95  _channel.set_value (patch.channel() + 1);
96  _channel.signal_changed().connect (sigc::mem_fun (*this, &PatchChangeDialog::channel_changed));
97 
98  l = manage (left_aligned_label (_("Program")));
99  t->attach (*l, 0, 1, r, r + 1);
100  t->attach (_program, 1, 2, r, r + 1);
101  ++r;
102 
103  _program.set_value (patch.program () + 1);
104  _program.signal_changed().connect (sigc::mem_fun (*this, &PatchChangeDialog::program_changed));
105 
106  l = manage (left_aligned_label (_("Bank")));
107  t->attach (*l, 0, 1, r, r + 1);
108  t->attach (_bank, 1, 2, r, r + 1);
109  ++r;
110 
111  _bank.set_value (patch.bank() + 1);
112  _bank.signal_changed().connect (sigc::mem_fun (*this, &PatchChangeDialog::bank_changed));
113 
114  get_vbox()->add (*t);
115 
116  add_button (Stock::CANCEL, RESPONSE_CANCEL);
117  add_button (ok, RESPONSE_ACCEPT);
118  if (allow_delete) {
119  add_button (Gtk::StockID(GTK_STOCK_DELETE), RESPONSE_REJECT);
120  }
121  set_default_response (RESPONSE_ACCEPT);
122 
123  fill_bank_combo ();
126 
129 
130  show_all ();
131 }
132 
133 void
135 {
136  _bank_combo.clear ();
137  _patch_combo.clear ();
138  fill_bank_combo ();
139  fill_patch_combo ();
140 }
141 
144 {
146 
147  if (_time_converter) {
149  }
150 
152  t,
153  _channel.get_value_as_int() - 1,
154  _program.get_value_as_int() - 1,
155  _bank.get_value_as_int() - 1
156  );
157 }
158 
160 void
162 {
163  _bank_combo.clear ();
164 
166 
167  if (!cns) {
168  return;
169  }
170 
171  for (MIDI::Name::ChannelNameSet::PatchBanks::const_iterator i = cns->patch_banks().begin(); i != cns->patch_banks().end(); ++i) {
172  string n = (*i)->name ();
173  boost::replace_all (n, "_", " ");
174  _bank_combo.append_text (n);
175  }
176 }
177 
179 void
181 {
183 
185 
186  if (!cns) {
187  return;
188  }
189 
190  for (MIDI::Name::ChannelNameSet::PatchBanks::const_iterator i = cns->patch_banks().begin(); i != cns->patch_banks().end(); ++i) {
191 
192  string n = (*i)->name ();
193  boost::replace_all (n, "_", " ");
194 
195  if ((*i)->number() == _bank.get_value () - 1) {
196  _current_patch_bank = *i;
197  _ignore_signals = true;
198  _bank_combo.set_active_text (n);
199  _ignore_signals = false;
200  return;
201  }
202  }
203 
204  _ignore_signals = true;
205  _bank_combo.set_active (-1);
206  _ignore_signals = false;
207 }
208 
212 void
214 {
215  if (_ignore_signals) {
216  return;
217  }
218 
220 
222 
223  if (!cns) {
224  return;
225  }
226 
227  for (MIDI::Name::ChannelNameSet::PatchBanks::const_iterator i = cns->patch_banks().begin(); i != cns->patch_banks().end(); ++i) {
228  string n = (*i)->name ();
229  boost::replace_all (n, "_", " ");
230  if (n == _bank_combo.get_active_text()) {
231  _current_patch_bank = *i;
232  }
233  }
234 
235  if (_current_patch_bank == 0) {
236  return;
237  }
238 
239  /* Reflect */
240 
241  fill_patch_combo ();
243 
244  _ignore_signals = true;
245  _bank.set_value (_current_patch_bank->number() + 1);
246  _ignore_signals = false;
247 }
248 
250 void
252 {
253  _patch_combo.clear ();
254 
255  if (_current_patch_bank == 0) {
256  return;
257  }
258 
259  const MIDI::Name::PatchNameList& patches = _current_patch_bank->patch_name_list ();
260  for (MIDI::Name::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
261  string n = (*j)->name ();
262  boost::replace_all (n, "_", " ");
263  _patch_combo.append_text (n);
264  }
265 }
266 
268 void
270 {
271  if (_ignore_signals) {
272  return;
273  }
274 
275  if (_current_patch_bank == 0) {
276  _ignore_signals = true;
277  _patch_combo.set_active (-1);
278  _ignore_signals = false;
279  return;
280  }
281 
282  const MIDI::Name::PatchNameList& patches = _current_patch_bank->patch_name_list ();
283  for (MIDI::Name::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
284  string n = (*j)->name ();
285  boost::replace_all (n, "_", " ");
286 
287  MIDI::Name::PatchPrimaryKey const & key = (*j)->patch_primary_key ();
288  if (key.program() == _program.get_value() - 1) {
289  _ignore_signals = true;
290  _patch_combo.set_active_text (n);
291  _ignore_signals = false;
292  return;
293  }
294  }
295 
296  _ignore_signals = true;
297  _patch_combo.set_active (-1);
298  _ignore_signals = false;
299 }
300 
302 void
304 {
305  if (_ignore_signals || _current_patch_bank == 0) {
306  return;
307  }
308 
309  const MIDI::Name::PatchNameList& patches = _current_patch_bank->patch_name_list ();
310 
311  for (MIDI::Name::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
312  string n = (*j)->name ();
313  boost::replace_all (n, "_", " ");
314 
315  if (n == _patch_combo.get_active_text ()) {
316  _ignore_signals = true;
317  _program.set_value ((*j)->program_number() + 1);
318  _ignore_signals = false;
319  break;
320  }
321  }
322 }
323 
324 void
326 {
327  fill_bank_combo ();
329  fill_patch_combo ();
331 }
332 
333 void
335 {
336  if (_ignore_signals) {
337  return;
338  }
339 
341 }
342 
343 void
345 {
346  if (_ignore_signals) {
347  return;
348  }
349 
351  fill_patch_combo ();
353 }
354 
Gtk::SpinButton _bank
framepos_t current_time(framepos_t position=0) const
void set(framepos_t, bool force=false, ARDOUR::framecnt_t offset=0)
Definition: audio_clock.cc:956
void set_session(ARDOUR::Session *s)
Definition: ardour_ui.h:130
const ARDOUR::BeatsFramesConverter * _time_converter
boost::shared_ptr< MIDI::Name::ChannelNameSet > get_patches(uint8_t channel)
PBD::Signal0< void > Changed
Definition: Beats.hpp:239
uint8_t program() const
Definition: PatchChange.hpp:95
uint8_t channel() const
LIBPBD_API int replace_all(std::string &str, const std::string &target, const std::string &replacement)
Definition: strreplace.cc:24
#define invalidator(x)
Definition: gui_thread.h:40
Gtk::SpinButton _channel
boost::shared_ptr< MIDI::Name::PatchBank > _current_patch_bank
#define _(Text)
Definition: i18n.h:11
Evoral::PatchChange< Evoral::Beats > patch() const
#define X_(Text)
Definition: i18n.h:13
#define gui_context()
Definition: gui_thread.h:36
Gtk::ComboBoxText _bank_combo
LIBGTKMM2EXT_API Gtk::Label * left_aligned_label(std::string const &)
Evoral::Beats from(framepos_t frames) const
Gtk::SpinButton _program
void set_mode(Mode)
LIBPBD_API Transmitter info
ARDOUR::InstrumentInfo & _info
Time time() const
Definition: PatchChange.hpp:76
Gtk::ComboBoxText _patch_combo
std::list< boost::shared_ptr< Patch > > PatchNameList
LIBEVORAL_API uint64_t Beats
PBD::ScopedConnection _info_changed_connection
framepos_t to(Evoral::Beats beats) const
PatchChangeDialog(const ARDOUR::BeatsFramesConverter *, ARDOUR::Session *, Evoral::PatchChange< Evoral::Beats > const &, ARDOUR::InstrumentInfo &, const Gtk::BuiltinStockID &, bool allow_delete=false)