Initial version of MIDI Trigger patch override UI
This commit is contained in:
parent
f57bef7c93
commit
ba32ee0e87
|
@ -23,14 +23,15 @@
|
|||
|
||||
#include "pbd/unwind.h"
|
||||
|
||||
#include "evoral/midi_events.h"
|
||||
#include "evoral/PatchChange.h"
|
||||
#include "evoral/midi_events.h"
|
||||
|
||||
#include "midi++/midnam_patch.h"
|
||||
|
||||
#include "ardour/instrument_info.h"
|
||||
#include "ardour/midi_track.h"
|
||||
#include "ardour/plugin_insert.h"
|
||||
#include "ardour/triggerbox.h"
|
||||
|
||||
#include "gtkmm2ext/menu_elems.h"
|
||||
#include "gtkmm2ext/utils.h"
|
||||
|
@ -248,6 +249,148 @@ PatchBankList::set_active_pgm (uint8_t p)
|
|||
|
||||
/* ****************************************************************************/
|
||||
|
||||
PatchChangeTab::PatchChangeTab (boost::shared_ptr<Route> r, boost::shared_ptr<MIDITrigger> t, int channel)
|
||||
: PatchBankList (r)
|
||||
, _enable_btn (_("Override Patch Changes"), ArdourWidgets::ArdourButton::led_default_elements)
|
||||
, _channel (channel)
|
||||
, _bank (0)
|
||||
, _ignore_callback (false)
|
||||
, _trigger (t)
|
||||
{
|
||||
if (_trigger->patch_change_set (_channel)) {
|
||||
_bank = _trigger->patch_change (_channel).bank ();
|
||||
_enable_btn.set_active (true);
|
||||
} else {
|
||||
_enable_btn.set_active (false);
|
||||
}
|
||||
|
||||
Box* box;
|
||||
box = manage (new HBox ());
|
||||
box->set_border_width (2);
|
||||
box->set_spacing (4);
|
||||
box->pack_start (_enable_btn, false, false);
|
||||
box->pack_start (*manage (new Label (_("Bank:"))), false, false);
|
||||
box->pack_start (_bank_select, true, true);
|
||||
box->pack_start (*manage (new Label (_("MSB:"))), false, false);
|
||||
box->pack_start (_bank_msb_spin, false, false);
|
||||
box->pack_start (*manage (new Label (_("LSB:"))), false, false);
|
||||
box->pack_start (_bank_lsb_spin, false, false);
|
||||
|
||||
pack_start (*box, false, false);
|
||||
|
||||
_program_table.set_spacings (1);
|
||||
pack_start (_program_table, true, true);
|
||||
|
||||
set_spacing (4);
|
||||
show_all ();
|
||||
|
||||
_enable_btn.signal_clicked.connect (sigc::mem_fun (*this, &PatchChangeTab::enable_toggle));
|
||||
|
||||
_trigger->PropertyChanged.connect (_trigger_connection, invalidator (*this), boost::bind (&PatchChangeTab::trigger_property_changed, this, _1), gui_context ());
|
||||
if (!boost::dynamic_pointer_cast<MidiTrack> (_route)) {
|
||||
processors_changed ();
|
||||
}
|
||||
refill_banks ();
|
||||
update_sensitivity ();
|
||||
}
|
||||
|
||||
void
|
||||
PatchChangeTab::enable_toggle ()
|
||||
{
|
||||
if (_ignore_callback) {
|
||||
return;
|
||||
}
|
||||
if (_enable_btn.get_active ()) {
|
||||
_trigger->unset_patch_change (_channel);
|
||||
} else {
|
||||
select_program (program ());
|
||||
}
|
||||
update_sensitivity ();
|
||||
}
|
||||
|
||||
void
|
||||
PatchChangeTab::update_sensitivity ()
|
||||
{
|
||||
bool en = _trigger->patch_change_set (_channel);
|
||||
_program_table.set_sensitive (en);
|
||||
_bank_select.set_sensitive (en);
|
||||
_bank_msb_spin.set_sensitive (en);
|
||||
_bank_lsb_spin.set_sensitive (en);
|
||||
}
|
||||
|
||||
void
|
||||
PatchChangeTab::trigger_property_changed (PBD::PropertyChange const& what_changed)
|
||||
{
|
||||
if (what_changed.contains (Properties::patch_change)) {
|
||||
PBD::Unwinder<bool> uw (_ignore_callback, true);
|
||||
_enable_btn.set_active (_trigger->patch_change_set (_channel));
|
||||
refill_banks ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PatchChangeTab::select_bank (uint32_t bank)
|
||||
{
|
||||
_bank = bank;
|
||||
select_program (program ());
|
||||
}
|
||||
|
||||
void
|
||||
PatchChangeTab::select_program (uint8_t pgm)
|
||||
{
|
||||
if (pgm > 127) {
|
||||
return;
|
||||
}
|
||||
|
||||
Evoral::PatchChange<MidiBuffer::TimeType> pc (0, _channel, pgm, _bank);
|
||||
_trigger->set_patch_change (pc);
|
||||
}
|
||||
|
||||
void
|
||||
PatchChangeTab::refresh ()
|
||||
{
|
||||
refill_banks ();
|
||||
}
|
||||
|
||||
void
|
||||
PatchChangeTab::refill_banks ()
|
||||
{
|
||||
refill (_channel);
|
||||
set_active_pgm (program ());
|
||||
}
|
||||
|
||||
int
|
||||
PatchChangeTab::bank (uint8_t c) const
|
||||
{
|
||||
assert (c == _channel);
|
||||
if (_trigger->patch_change_set (_channel)) {
|
||||
return _trigger->patch_change (_channel).bank ();
|
||||
}
|
||||
return _bank;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
PatchChangeTab::program () const
|
||||
{
|
||||
if (_trigger->patch_change_set (_channel)) {
|
||||
return _trigger->patch_change (_channel).program ();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
PatchChangeTab::instrument_info_changed ()
|
||||
{
|
||||
refill_banks ();
|
||||
}
|
||||
|
||||
void
|
||||
PatchChangeTab::processors_changed ()
|
||||
{
|
||||
}
|
||||
|
||||
/* ****************************************************************************/
|
||||
|
||||
PatchChangeWidget::PatchChangeWidget (boost::shared_ptr<ARDOUR::Route> r)
|
||||
: PatchBankList (r)
|
||||
, _channel (-1)
|
||||
|
@ -277,7 +420,7 @@ PatchChangeWidget::PatchChangeWidget (boost::shared_ptr<ARDOUR::Route> r)
|
|||
pack_start (_program_table, true, true);
|
||||
|
||||
if (!boost::dynamic_pointer_cast<MidiTrack> (_route)) {
|
||||
pack_start ( *manage (new Label (_("Note: Patch Selection is volatile (only Midi-Tracks retain bank/patch selection)."))), false, false);
|
||||
pack_start (*manage (new Label (_("Note: Patch Selection is volatile (only Midi-Tracks retain bank/patch selection)."))), false, false);
|
||||
}
|
||||
|
||||
box = manage (new HBox ());
|
||||
|
@ -657,6 +800,29 @@ PatchChangeWidget::program (uint8_t chn) const
|
|||
|
||||
/* ***************************************************************************/
|
||||
|
||||
PatchChangeTriggerDialog::PatchChangeTriggerDialog (boost::shared_ptr<Route> r, boost::shared_ptr<MIDITrigger> t)
|
||||
: ArdourDialog (string_compose (_("Select Patch for \"%1\""), t->name ()), false, false)
|
||||
{
|
||||
for (uint32_t chn = 0; chn < 16; ++chn) {
|
||||
_w[chn] = manage (new PatchChangeTab (r, t, chn));
|
||||
_notebook.append_page (*_w[chn], string_compose (_("Chn %1"), chn + 1));
|
||||
}
|
||||
|
||||
_notebook.signal_switch_page ().connect (sigc::mem_fun (*this, &PatchChangeTriggerDialog::on_switch_page));
|
||||
_notebook.set_current_page (0);
|
||||
|
||||
get_vbox ()->add (_notebook);
|
||||
_notebook.show_all ();
|
||||
}
|
||||
|
||||
void
|
||||
PatchChangeTriggerDialog::on_switch_page (GtkNotebookPage*, guint page_num)
|
||||
{
|
||||
_w[page_num]->refresh ();
|
||||
}
|
||||
|
||||
/* ***************************************************************************/
|
||||
|
||||
PatchChangeGridDialog::PatchChangeGridDialog (boost::shared_ptr<ARDOUR::Route> r)
|
||||
: ArdourDialog (string_compose (_("Select Patch for \"%1\""), r->name()), false, false)
|
||||
, w (r)
|
||||
|
|
|
@ -20,11 +20,12 @@
|
|||
#define __gtkardour_patch_change_widget_h__
|
||||
|
||||
#include <gtkmm/box.h>
|
||||
#include <gtkmm/notebook.h>
|
||||
#include <gtkmm/spinbutton.h>
|
||||
#include <gtkmm/table.h>
|
||||
|
||||
#include "pbd/signals.h"
|
||||
#include "midi++/midnam_patch.h"
|
||||
#include "pbd/signals.h"
|
||||
|
||||
#include "ardour/route.h"
|
||||
|
||||
|
@ -34,6 +35,10 @@
|
|||
#include "ardour_dialog.h"
|
||||
#include "pianokeyboard.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
class MIDITrigger;
|
||||
};
|
||||
|
||||
class PatchBankList : virtual public sigc::trackable
|
||||
{
|
||||
public:
|
||||
|
@ -69,6 +74,39 @@ private:
|
|||
PBD::ScopedConnection _route_connection;
|
||||
};
|
||||
|
||||
class PatchChangeTab : public Gtk::VBox, public PatchBankList
|
||||
{
|
||||
public:
|
||||
PatchChangeTab (boost::shared_ptr<ARDOUR::Route>, boost::shared_ptr<ARDOUR::MIDITrigger>, int channel);
|
||||
|
||||
void refresh ();
|
||||
|
||||
protected:
|
||||
int bank (uint8_t) const;
|
||||
uint8_t program () const;
|
||||
|
||||
/* Implement PatchBankList */
|
||||
void select_bank (uint32_t);
|
||||
void select_program (uint8_t);
|
||||
void instrument_info_changed ();
|
||||
void processors_changed ();
|
||||
|
||||
private:
|
||||
void refill_banks ();
|
||||
void trigger_property_changed (PBD::PropertyChange const&);
|
||||
void enable_toggle ();
|
||||
void update_sensitivity ();
|
||||
|
||||
ArdourWidgets::ArdourButton _enable_btn;
|
||||
|
||||
int _channel;
|
||||
int _bank;
|
||||
bool _ignore_callback;
|
||||
|
||||
boost::shared_ptr<ARDOUR::MIDITrigger> _trigger;
|
||||
PBD::ScopedConnection _trigger_connection;
|
||||
};
|
||||
|
||||
class PatchChangeWidget : public Gtk::VBox, public PatchBankList
|
||||
{
|
||||
public:
|
||||
|
@ -129,6 +167,18 @@ private:
|
|||
void note_off_event_handler (int);
|
||||
};
|
||||
|
||||
class PatchChangeTriggerDialog : public ArdourDialog
|
||||
{
|
||||
public:
|
||||
PatchChangeTriggerDialog (boost::shared_ptr<ARDOUR::Route>, boost::shared_ptr<ARDOUR::MIDITrigger>);
|
||||
|
||||
private:
|
||||
void on_switch_page (GtkNotebookPage*, guint page_num);
|
||||
|
||||
Gtk::Notebook _notebook;
|
||||
PatchChangeTab* _w[16];
|
||||
};
|
||||
|
||||
class PatchChangeGridDialog : public ArdourDialog
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "ardour_ui.h"
|
||||
#include "gui_thread.h"
|
||||
#include "keyboard.h"
|
||||
#include "patch_change_widget.h"
|
||||
#include "public_editor.h"
|
||||
#include "region_view.h"
|
||||
#include "trigger_jump_dialog.h"
|
||||
|
@ -201,6 +202,19 @@ TriggerUI::choose_color ()
|
|||
_color_dialog.hide ();
|
||||
}
|
||||
|
||||
void
|
||||
TriggerUI::choose_patch ()
|
||||
{
|
||||
/* XXX can we get a shared_from (owner()) ? */
|
||||
SessionObject* obj = trigger ()->box ().owner ();
|
||||
Session* s = AudioEngine::instance ()->session ();
|
||||
boost::shared_ptr<Stripable> stripable = s->stripable_by_id (obj->id ());
|
||||
assert (boost::dynamic_pointer_cast<MIDITrigger> (trigger ()) != 0);
|
||||
|
||||
PatchChangeTriggerDialog pcd (boost::dynamic_pointer_cast<Route> (stripable), boost::dynamic_pointer_cast<MIDITrigger> (trigger ()));
|
||||
pcd.run ();
|
||||
}
|
||||
|
||||
void
|
||||
TriggerUI::choose_sample (bool allow_multiple_select)
|
||||
{
|
||||
|
@ -442,11 +456,15 @@ TriggerUI::context_menu ()
|
|||
#if DOUBLE_CLICK_IS_NOT_OBVIOUS_ENOUGH
|
||||
items.push_back (MenuElem (_("Edit..."), sigc::mem_fun (*this, &TriggerUI::edit_trigger)));
|
||||
#endif
|
||||
if (boost::dynamic_pointer_cast<MIDITrigger> (trigger ())) {
|
||||
items.push_back (MenuElem (_("Select Patch.."), sigc::mem_fun (*this, &TriggerUI::choose_patch)));
|
||||
}
|
||||
items.push_back (SeparatorElem());
|
||||
items.push_back (MenuElem (_("Color..."), sigc::mem_fun (*this, &TriggerUI::choose_color)));
|
||||
items.push_back (SeparatorElem());
|
||||
items.push_back (MenuElem (_("Clear"), sigc::mem_fun (*this, &TriggerUI::clear_trigger)));
|
||||
|
||||
|
||||
_context_menu->popup (1, gtk_get_current_event_time ());
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
ARDOUR::TriggerBox& triggerbox() const { return trigger()->box(); }
|
||||
|
||||
void choose_color ();
|
||||
void choose_patch ();
|
||||
void choose_sample (bool allow_multiple_select);
|
||||
void sample_chosen (int r);
|
||||
|
||||
|
|
Loading…
Reference in New Issue