summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2012-06-11 22:59:35 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2012-06-11 22:59:35 +0000
commitd97312d438a813985916dd35f613510e9448441f (patch)
tree5be2844fc16359c2eb550b72c9f84737c534d614
parentc81691741118ab34c5f6f458c2d84f431e481ada (diff)
lots more work trying to create a common structure for accessing plugin and MIDNAME patch/preset/program names. still not done
git-svn-id: svn://localhost/ardour2/branches/3.0@12665 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/canvas_patch_change.cc51
-rw-r--r--gtk2_ardour/canvas_patch_change.h12
-rw-r--r--gtk2_ardour/editor_ops.cc5
-rw-r--r--gtk2_ardour/midi_region_view.cc25
-rw-r--r--gtk2_ardour/midi_region_view.h14
-rw-r--r--gtk2_ardour/midi_time_axis.cc4
-rw-r--r--gtk2_ardour/patch_change_dialog.cc48
-rw-r--r--gtk2_ardour/patch_change_dialog.h9
-rw-r--r--libs/ardour/ardour/instrument_info.h11
-rw-r--r--libs/ardour/ardour/plugin.h30
-rw-r--r--libs/ardour/ardour/route.h2
-rw-r--r--libs/ardour/audio_unit.cc2
-rw-r--r--libs/ardour/instrument_info.cc107
-rw-r--r--libs/ardour/route.cc37
-rw-r--r--libs/ardour/vst_plugin.cc4
-rw-r--r--libs/midi++2/midi++/midnam_patch.h4
-rw-r--r--libs/midi++2/midnam_patch.cc152
17 files changed, 389 insertions, 128 deletions
diff --git a/gtk2_ardour/canvas_patch_change.cc b/gtk2_ardour/canvas_patch_change.cc
index 44389ae96c..b3d8caa488 100644
--- a/gtk2_ardour/canvas_patch_change.cc
+++ b/gtk2_ardour/canvas_patch_change.cc
@@ -22,7 +22,7 @@
#include <glibmm/regex.h>
#include "gtkmm2ext/keyboard.h"
-#include "ardour/midi_patch_manager.h"
+#include "ardour/instrument_info.h"
#include "ardour_ui.h"
#include "midi_region_view.h"
@@ -44,8 +44,7 @@ CanvasPatchChange::CanvasPatchChange(
double height,
double x,
double y,
- string& model_name,
- string& custom_device_mode,
+ ARDOUR::InstrumentInfo& info,
ARDOUR::MidiModel::PatchChangePtr patch,
bool active_channel)
: CanvasFlag(
@@ -60,12 +59,11 @@ CanvasPatchChange::CanvasPatchChange(
ARDOUR_UI::config()->canvasvar_MidiPatchChangeInactiveChannelFill.get(),
x,
y)
- , _model_name(model_name)
- , _custom_device_mode(custom_device_mode)
+ , _info (info)
, _patch (patch)
, _popup_initialized(false)
{
- set_text(text);
+ set_text (text);
}
CanvasPatchChange::~CanvasPatchChange()
@@ -75,9 +73,7 @@ CanvasPatchChange::~CanvasPatchChange()
void
CanvasPatchChange::initialize_popup_menus()
{
- boost::shared_ptr<ChannelNameSet> channel_name_set =
- MidiPatchManager::instance()
- .find_channel_name_set(_model_name, _custom_device_mode, _patch->channel());
+ boost::shared_ptr<ChannelNameSet> channel_name_set = _info.get_patches (_patch->channel());
if (!channel_name_set) {
return;
@@ -193,22 +189,28 @@ CanvasPatchChange::on_event (GdkEvent* ev)
break;
case GDK_SCROLL:
- if (ev->scroll.direction == GDK_SCROLL_UP) {
- if (Keyboard::modifier_state_contains (ev->scroll.state, Keyboard::PrimaryModifier)) {
- _region.previous_bank (*this);
- } else {
- _region.previous_patch (*this);
- }
- return true;
- } else if (ev->scroll.direction == GDK_SCROLL_DOWN) {
- if (Keyboard::modifier_state_contains (ev->scroll.state, Keyboard::PrimaryModifier)) {
- _region.next_bank (*this);
- } else {
- _region.next_patch (*this);
+ {
+ /* XXX: icky dcast */
+ Editor* e = dynamic_cast<Editor*> (&_region.get_time_axis_view().editor());
+ if (e->current_mouse_mode() == Editing::MouseObject && e->internal_editing()) {
+ if (ev->scroll.direction == GDK_SCROLL_UP) {
+ if (Keyboard::modifier_state_contains (ev->scroll.state, Keyboard::PrimaryModifier)) {
+ _region.previous_bank (*this);
+ } else {
+ _region.previous_patch (*this);
+ }
+ return true;
+ } else if (ev->scroll.direction == GDK_SCROLL_DOWN) {
+ if (Keyboard::modifier_state_contains (ev->scroll.state, Keyboard::PrimaryModifier)) {
+ _region.next_bank (*this);
+ } else {
+ _region.next_patch (*this);
+ }
+ return true;
}
- return true;
+ break;
}
- break;
+ }
case GDK_ENTER_NOTIFY:
_region.patch_entered (this);
@@ -218,6 +220,9 @@ CanvasPatchChange::on_event (GdkEvent* ev)
_region.patch_left (this);
break;
+ case GDK_KEY_RELEASE:
+ return true;
+
case GDK_BUTTON_RELEASE:
return true;
diff --git a/gtk2_ardour/canvas_patch_change.h b/gtk2_ardour/canvas_patch_change.h
index 2a219fdbb6..20c0067ae7 100644
--- a/gtk2_ardour/canvas_patch_change.h
+++ b/gtk2_ardour/canvas_patch_change.h
@@ -30,6 +30,10 @@ namespace MIDI {
}
}
+namespace ARDOUR {
+ class InstrumentInfo;
+}
+
namespace Gnome {
namespace Canvas {
@@ -43,8 +47,7 @@ public:
double height,
double x,
double y,
- string& model_name,
- string& custom_device_mode,
+ ARDOUR::InstrumentInfo& info,
ARDOUR::MidiModel::PatchChangePtr patch,
bool
);
@@ -53,8 +56,6 @@ public:
virtual bool on_event(GdkEvent* ev);
- string model_name () const { return _model_name; }
- string custom_device_mode () const { return _custom_device_mode; }
ARDOUR::MidiModel::PatchChangePtr patch () const { return _patch; }
void initialize_popup_menus();
@@ -62,8 +63,7 @@ public:
void on_patch_menu_selected(const MIDI::Name::PatchPrimaryKey& key);
private:
- string _model_name;
- string _custom_device_mode;
+ ARDOUR::InstrumentInfo& _info;
ARDOUR::MidiModel::PatchChangePtr _patch;
Gtk::Menu _popup;
bool _popup_initialized;
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index b7462f7c9e..884fe5eb17 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -4730,6 +4730,8 @@ Editor::insert_patch_change (bool from_context)
const framepos_t p = get_preferred_edit_position (false, from_context);
+ cerr << "Got " << rs.size() << " regions to add patch change to\n";
+
/* XXX: bit of a hack; use the MIDNAM from the first selected region;
there may be more than one, but the PatchChangeDialog can only offer
one set of patch menus.
@@ -4737,7 +4739,7 @@ Editor::insert_patch_change (bool from_context)
MidiRegionView* first = dynamic_cast<MidiRegionView*> (rs.front ());
Evoral::PatchChange<Evoral::MusicalTime> empty (0, 0, 0, 0);
- PatchChangeDialog d (0, _session, empty, first->model_name(), first->custom_device_mode(), Gtk::Stock::ADD);
+ PatchChangeDialog d (0, _session, empty, first->instrument_info(), Gtk::Stock::ADD);
if (d.run() == RESPONSE_CANCEL) {
return;
@@ -4747,6 +4749,7 @@ Editor::insert_patch_change (bool from_context)
MidiRegionView* const mrv = dynamic_cast<MidiRegionView*> (*i);
if (mrv) {
if (p >= mrv->region()->first_frame() && p <= mrv->region()->last_frame()) {
+ cerr << "Adding patch change @ " << p << " to " << mrv->region()->name() << endl;
mrv->add_patch_change (p - mrv->region()->position(), d.patch ());
}
}
diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc
index ca9cd4af71..9e9e7efe86 100644
--- a/gtk2_ardour/midi_region_view.cc
+++ b/gtk2_ardour/midi_region_view.cc
@@ -283,11 +283,8 @@ MidiRegionView::init (Gdk::Color const & basic_color, bool wfd)
midi_view()->signal_channel_mode_changed().connect(
sigc::mem_fun(this, &MidiRegionView::midi_channel_mode_changed));
- RouteUI* route_ui = dynamic_cast<RouteUI*> (&trackview);
- if (route_ui) {
- route_ui->route()->instrument_info().Changed.connect (_instrument_changed_connection, invalidator (*this),
- boost::bind (&MidiRegionView::instrument_settings_changed, this), gui_context());
- }
+ instrument_info().Changed.connect (_instrument_changed_connection, invalidator (*this),
+ boost::bind (&MidiRegionView::instrument_settings_changed, this), gui_context());
trackview.editor().SnapChanged.connect(snap_changed_connection, invalidator(*this),
boost::bind (&MidiRegionView::snap_changed, this),
@@ -299,6 +296,13 @@ MidiRegionView::init (Gdk::Color const & basic_color, bool wfd)
SelectionCleared.connect (_selection_cleared_connection, invalidator (*this), boost::bind (&MidiRegionView::selection_cleared, this, _1), gui_context ());
}
+InstrumentInfo&
+MidiRegionView::instrument_info () const
+{
+ RouteUI* route_ui = dynamic_cast<RouteUI*> (&trackview);
+ return route_ui->route()->instrument_info();
+}
+
const boost::shared_ptr<ARDOUR::MidiRegion>
MidiRegionView::midi_region() const
{
@@ -1204,10 +1208,8 @@ MidiRegionView::display_patch_changes_on_channel (uint8_t channel, bool active_c
continue;
}
- // MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
- //string patch_name = mtv->get_patch_name ((*i)->bank(), (*i)->program(), channel);
-
- // add_canvas_patch_change (*i, patch_name, active_channel);
+ string patch_name = instrument_info().get_patch_name ((*i)->bank(), (*i)->program(), channel);
+ add_canvas_patch_change (*i, patch_name, active_channel);
}
}
@@ -1792,8 +1794,7 @@ MidiRegionView::add_canvas_patch_change (MidiModel::PatchChangePtr patch, const
displaytext,
height,
x, 1.0,
- _model_name,
- _custom_device_mode,
+ instrument_info(),
patch,
active_channel)
);
@@ -3709,7 +3710,7 @@ MidiRegionView::trim_front_ending ()
void
MidiRegionView::edit_patch_change (ArdourCanvas::CanvasPatchChange* pc)
{
- PatchChangeDialog d (&_source_relative_time_converter, trackview.session(), *pc->patch (), _model_name, _custom_device_mode, Gtk::Stock::APPLY);
+ PatchChangeDialog d (&_source_relative_time_converter, trackview.session(), *pc->patch (), instrument_info(), Gtk::Stock::APPLY);
if (d.run () != Gtk::RESPONSE_ACCEPT) {
return;
}
diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h
index 93cc1ee128..1b22029151 100644
--- a/gtk2_ardour/midi_region_view.h
+++ b/gtk2_ardour/midi_region_view.h
@@ -300,13 +300,7 @@ public:
void clear_selection (bool signal = true) { clear_selection_except (0, signal); }
- std::string model_name () const {
- return _model_name;
- }
-
- std::string custom_device_mode () const {
- return _custom_device_mode;
- }
+ ARDOUR::InstrumentInfo& instrument_info() const;
protected:
/** Allows derived types to specify their visibility requirements
@@ -381,12 +375,6 @@ private:
uint8_t _current_range_min;
uint8_t _current_range_max;
- /// MIDNAM information of the current track: Model name of MIDNAM file
- std::string _model_name;
-
- /// MIDNAM information of the current track: CustomDeviceMode
- std::string _custom_device_mode;
-
typedef std::list<ArdourCanvas::CanvasNoteEvent*> Events;
typedef std::vector< boost::shared_ptr<ArdourCanvas::CanvasPatchChange> > PatchChanges;
typedef std::vector< boost::shared_ptr<ArdourCanvas::CanvasSysEx> > SysExes;
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc
index 4678ea7c7b..df5d4b1b97 100644
--- a/gtk2_ardour/midi_time_axis.cc
+++ b/gtk2_ardour/midi_time_axis.cc
@@ -208,8 +208,12 @@ MidiTimeAxisView::set_route (boost::shared_ptr<Route> rt)
_model_selector.set_active_text (gui_property (X_("midnam-model-name")));
_custom_device_mode_selector.set_active_text (gui_property (X_("midnam-custom-device-mode")));
+ ARDOUR_UI::instance()->set_tip (_model_selector, _("external MIDI Device selector"));
+ ARDOUR_UI::instance()->set_tip (_custom_device_mode_selector, _("external MIDI Device Mode"));
+
midi_controls_hbox->pack_start(_channel_selector, true, false);
if (!patch_manager.all_models().empty()) {
+ _midi_controls_box.set_border_width (5);
_midi_controls_box.pack_start(_model_selector, true, false);
_midi_controls_box.pack_start(_custom_device_mode_selector, true, false);
}
diff --git a/gtk2_ardour/patch_change_dialog.cc b/gtk2_ardour/patch_change_dialog.cc
index 0ec12f93c2..4dd2a91d75 100644
--- a/gtk2_ardour/patch_change_dialog.cc
+++ b/gtk2_ardour/patch_change_dialog.cc
@@ -20,11 +20,17 @@
#include <gtkmm/stock.h>
#include <gtkmm/table.h>
+
#include <boost/algorithm/string.hpp>
+
#include "gtkmm2ext/utils.h"
+
#include "ardour/midi_patch_manager.h"
#include "ardour/beats_frames_converter.h"
+#include "ardour/instrument_info.h"
+
#include "patch_change_dialog.h"
+
#include "i18n.h"
using namespace std;
@@ -36,14 +42,12 @@ PatchChangeDialog::PatchChangeDialog (
const ARDOUR::BeatsFramesConverter* tc,
ARDOUR::Session* session,
Evoral::PatchChange<Evoral::MusicalTime> const & patch,
- string const & model_name,
- string const & custom_device_node,
+ ARDOUR::InstrumentInfo& info,
const Gtk::BuiltinStockID& ok
)
: ArdourDialog (_("Patch Change"), true)
, _time_converter (tc)
- , _model_name (model_name)
- , _custom_device_mode (custom_device_node)
+ , _info (info)
, _time (X_("patchchangetime"), true, "", true, false)
, _channel (*manage (new Adjustment (1, 1, 16, 1, 4)))
, _program (*manage (new Adjustment (1, 1, 128, 1, 16)))
@@ -139,12 +143,9 @@ PatchChangeDialog::patch () const
void
PatchChangeDialog::fill_bank_combo ()
{
- MIDI::Name::ChannelNameSet::PatchBanks const * banks = get_banks ();
- if (banks == 0) {
- return;
- }
+ boost::shared_ptr<MIDI::Name::ChannelNameSet> cns = _info.get_patches (_channel.get_value_as_int() - 1);
- for (MIDI::Name::ChannelNameSet::PatchBanks::const_iterator i = banks->begin(); i != banks->end(); ++i) {
+ for (MIDI::Name::ChannelNameSet::PatchBanks::const_iterator i = cns->patch_banks().begin(); i != cns->patch_banks().end(); ++i) {
string n = (*i)->name ();
boost::replace_all (n, "_", " ");
_bank_combo.append_text (n);
@@ -157,12 +158,10 @@ PatchChangeDialog::set_active_bank_combo ()
{
_current_patch_bank.reset ();
- MIDI::Name::ChannelNameSet::PatchBanks const * banks = get_banks ();
- if (banks == 0) {
- return;
- }
+ boost::shared_ptr<MIDI::Name::ChannelNameSet> cns = _info.get_patches (_channel.get_value_as_int() - 1);
+
+ for (MIDI::Name::ChannelNameSet::PatchBanks::const_iterator i = cns->patch_banks().begin(); i != cns->patch_banks().end(); ++i) {
- for (MIDI::Name::ChannelNameSet::PatchBanks::const_iterator i = banks->begin(); i != banks->end(); ++i) {
string n = (*i)->name ();
boost::replace_all (n, "_", " ");
@@ -193,12 +192,9 @@ PatchChangeDialog::bank_combo_changed ()
_current_patch_bank.reset ();
- MIDI::Name::ChannelNameSet::PatchBanks const * banks = get_banks ();
- if (banks == 0) {
- return;
- }
+ boost::shared_ptr<MIDI::Name::ChannelNameSet> cns = _info.get_patches (_channel.get_value_as_int() - 1);
- for (MIDI::Name::ChannelNameSet::PatchBanks::const_iterator i = banks->begin(); i != banks->end(); ++i) {
+ for (MIDI::Name::ChannelNameSet::PatchBanks::const_iterator i = cns->patch_banks().begin(); i != cns->patch_banks().end(); ++i) {
string n = (*i)->name ();
boost::replace_all (n, "_", " ");
if (n == _bank_combo.get_active_text()) {
@@ -327,17 +323,3 @@ PatchChangeDialog::bank_changed ()
set_active_patch_combo ();
}
-MIDI::Name::ChannelNameSet::PatchBanks const *
-PatchChangeDialog::get_banks ()
-{
- MIDI::Name::MidiPatchManager& mpm = MIDI::Name::MidiPatchManager::instance ();
- boost::shared_ptr<MIDI::Name::ChannelNameSet> channel_name_set = mpm.find_channel_name_set (
- _model_name, _custom_device_mode, _channel.get_value_as_int() - 1
- );
-
- if (!channel_name_set) {
- return 0;
- }
-
- return &channel_name_set->patch_banks ();
-}
diff --git a/gtk2_ardour/patch_change_dialog.h b/gtk2_ardour/patch_change_dialog.h
index 0691260126..1a0b63e51f 100644
--- a/gtk2_ardour/patch_change_dialog.h
+++ b/gtk2_ardour/patch_change_dialog.h
@@ -28,6 +28,7 @@
namespace ARDOUR {
class BeatsFramesConverter;
class Session;
+ class InstrumentInfo;
}
namespace MIDI {
@@ -43,8 +44,7 @@ public:
const ARDOUR::BeatsFramesConverter *,
ARDOUR::Session *,
Evoral::PatchChange<Evoral::MusicalTime> const &,
- std::string const &,
- std::string const &,
+ ARDOUR::InstrumentInfo&,
const Gtk::BuiltinStockID &
);
@@ -61,11 +61,8 @@ private:
void bank_changed ();
void program_changed ();
- MIDI::Name::ChannelNameSet::PatchBanks const * get_banks ();
-
const ARDOUR::BeatsFramesConverter* _time_converter;
- std::string _model_name;
- std::string _custom_device_mode;
+ ARDOUR::InstrumentInfo& _info;
AudioClock _time;
Gtk::SpinButton _channel;
Gtk::SpinButton _program;
diff --git a/libs/ardour/ardour/instrument_info.h b/libs/ardour/ardour/instrument_info.h
index d4c9bf4f46..f83b2c0632 100644
--- a/libs/ardour/ardour/instrument_info.h
+++ b/libs/ardour/ardour/instrument_info.h
@@ -24,6 +24,8 @@
#include "pbd/signals.h"
+#include "midi++/midnam_patch.h"
+
#include <boost/weak_ptr.hpp>
namespace ARDOUR {
@@ -41,13 +43,22 @@ class InstrumentInfo {
std::string get_patch_name (uint16_t bank, uint8_t program, uint8_t channel) const;
std::string get_instrument_name () const;
+ boost::shared_ptr<MIDI::Name::ChannelNameSet> get_patches (uint8_t channel);
+
PBD::Signal0<void> Changed;
+ static const MIDI::Name::PatchBank::PatchNameList& general_midi_patches();
+
private:
std::string external_instrument_model;
std::string external_instrument_mode;
boost::weak_ptr<ARDOUR::Processor> internal_instrument;
+
+ boost::shared_ptr<MIDI::Name::ChannelNameSet> plugin_programs_to_channel_name_set (boost::shared_ptr<Processor> p);
+ std::string get_plugin_patch_name (boost::shared_ptr<ARDOUR::Processor>, uint16_t bank, uint8_t program, uint8_t channel) const;
+
+ static MIDI::Name::PatchBank::PatchNameList _gm_patches;
};
} /* namespace ARDOUR */
diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h
index cfdf0e8121..f33fb9d1e5 100644
--- a/libs/ardour/ardour/plugin.h
+++ b/libs/ardour/ardour/plugin.h
@@ -166,16 +166,17 @@ class Plugin : public PBD::StatefulDestructible, public Latent
void monitoring_changed ();
struct PresetRecord {
- PresetRecord () : user (true) {}
- PresetRecord (const std::string& u, const std::string& l, bool s = true) : uri (u), label (l), user (s) {}
-
- bool operator!= (PresetRecord const & a) const {
- return uri != a.uri || label != a.label;
- }
-
- std::string uri;
- std::string label;
- bool user;
+ PresetRecord () : number (-1), user (true) {}
+ PresetRecord (const std::string& u, const std::string& l, int n = -1, bool s = true) : uri (u), label (l), number (n), user (s) {}
+
+ bool operator!= (PresetRecord const & a) const {
+ return number != a.number || uri != a.uri || label != a.label;
+ }
+
+ std::string uri;
+ std::string label;
+ int number; // if <0, invalid
+ bool user;
};
PresetRecord save_preset (std::string);
@@ -188,6 +189,15 @@ class Plugin : public PBD::StatefulDestructible, public Latent
std::vector<PresetRecord> get_presets ();
+ /* This is hard to return a correct value for because most plugin APIs
+ do not specify plugin behaviour. However, if you want to force
+ the display of plugin built-in preset names rather than MIDI program
+ numbers, return true. If you want a generic description, return
+ false.
+ */
+ virtual bool presets_are_MIDI_programs() const { return true; }
+ virtual bool current_preset_uses_general_midi() const { return true; }
+
/** @return Last preset to be requested; the settings may have
* been changed since; find out with parameter_changed_since_last_preset.
*/
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 5a828513e3..d1248d8b03 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -603,6 +603,8 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
boost::weak_ptr<Processor> _processor_after_last_custom_meter;
/** true if the last custom meter position was at the end of the processor list */
bool _last_custom_meter_was_at_end;
+
+ void reset_instrument_info ();
};
} // namespace ARDOUR
diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc
index 9151e76bec..52e329bb87 100644
--- a/libs/ardour/audio_unit.cc
+++ b/libs/ardour/audio_unit.cc
@@ -2107,7 +2107,7 @@ AUPlugin::find_presets ()
for (FactoryPresetMap::iterator i = factory_preset_map.begin(); i != factory_preset_map.end(); ++i) {
/* XXX: dubious */
string const uri = string_compose ("%1", _presets.size ());
- _presets.insert (make_pair (uri, Plugin::PresetRecord (uri, i->first)));
+ _presets.insert (make_pair (uri, Plugin::PresetRecord (uri, i->first, i->second)));
}
#endif
diff --git a/libs/ardour/instrument_info.cc b/libs/ardour/instrument_info.cc
index 21e4bd1cd9..c83f7ae321 100644
--- a/libs/ardour/instrument_info.cc
+++ b/libs/ardour/instrument_info.cc
@@ -16,6 +16,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <algorithm>
+
#include "pbd/compose.h"
#include "midi++/midnam_patch.h"
@@ -23,13 +25,17 @@
#include "ardour/instrument_info.h"
#include "ardour/midi_patch_manager.h"
#include "ardour/processor.h"
+#include "ardour/plugin.h"
#include "ardour/rc_configuration.h"
#include "i18n.h"
using namespace ARDOUR;
+using namespace MIDI::Name;
using std::string;
+MIDI::Name::PatchBank::PatchNameList InstrumentInfo::_gm_patches;
+
InstrumentInfo::InstrumentInfo ()
: external_instrument_model (_("Unknown"))
{
@@ -79,7 +85,7 @@ InstrumentInfo::get_patch_name (uint16_t bank, uint8_t program, uint8_t channel)
boost::shared_ptr<Processor> p = internal_instrument.lock();
if (p) {
- return "some plugin program";
+ return get_plugin_patch_name (p, bank, program, channel);
}
MIDI::Name::PatchPrimaryKey patch_key (bank, program);
@@ -95,6 +101,103 @@ InstrumentInfo::get_patch_name (uint16_t bank, uint8_t program, uint8_t channel)
#define MIDI_BP_ZERO ((Config->get_first_midi_bank_is_zero())?0:1)
- return string_compose ("%1 %2",program + MIDI_BP_ZERO , bank + MIDI_BP_ZERO);
+ return string_compose ("prg %1 bnk %2",program + MIDI_BP_ZERO , bank + MIDI_BP_ZERO);
}
}
+
+boost::shared_ptr<MIDI::Name::ChannelNameSet>
+InstrumentInfo::get_patches (uint8_t channel)
+{
+ boost::shared_ptr<Processor> p = internal_instrument.lock();
+
+ if (p) {
+ return plugin_programs_to_channel_name_set (p);
+ }
+
+ return MidiPatchManager::instance().find_channel_name_set (external_instrument_model,
+ external_instrument_mode,
+ channel);
+
+}
+
+boost::shared_ptr<MIDI::Name::ChannelNameSet>
+InstrumentInfo::plugin_programs_to_channel_name_set (boost::shared_ptr<Processor> p)
+{
+ PatchBank::PatchNameList patch_list;
+
+ boost::shared_ptr<PluginInsert> insert = boost::dynamic_pointer_cast<PluginInsert> (p);
+
+ if (!insert) {
+ return boost::shared_ptr<ChannelNameSet>();
+ }
+
+ boost::shared_ptr<Plugin> pp = insert->plugin();
+
+ if (pp->current_preset_uses_general_midi()) {
+
+ patch_list = InstrumentInfo::general_midi_patches ();
+
+ } else if (pp->presets_are_MIDI_programs()) {
+
+ std::vector<Plugin::PresetRecord> presets = pp->get_presets ();
+ std::vector<Plugin::PresetRecord>::iterator i;
+ int n;
+
+ /* XXX note the assumption that plugin presets start their numbering at
+ * zero
+ */
+
+ for (n = 0, i = presets.begin(); i != presets.end(); ++i, ++n) {
+ if ((*i).number >= 0) {
+ patch_list.push_back (boost::shared_ptr<Patch> (new Patch (string_compose ("%1", n), (*i).label)));
+ } else {
+ patch_list.push_back (boost::shared_ptr<Patch> (new Patch (string_compose ("%1", n),
+ string_compose ("program %1", n))));
+ }
+ }
+ } else {
+ for (int n = 0; n < 127; ++n) {
+ patch_list.push_back (boost::shared_ptr<Patch> (new Patch (string_compose ("%1", n),
+ string_compose ("program %1", n))));
+ }
+ }
+
+ boost::shared_ptr<PatchBank> pb (new PatchBank (p->name()));
+ pb->set_patch_name_list (patch_list);
+
+ ChannelNameSet::PatchBanks patch_banks;
+ patch_banks.push_back (pb);
+
+ boost::shared_ptr<MIDI::Name::ChannelNameSet> cns (new ChannelNameSet);
+ cns->set_patch_banks (patch_banks);
+
+ return cns;
+}
+
+const MIDI::Name::PatchBank::PatchNameList&
+InstrumentInfo::general_midi_patches()
+{
+ if (_gm_patches.empty()) {
+ for (int n = 0; n < 128; n++) {
+ _gm_patches.push_back (boost::shared_ptr<Patch> (new Patch (string_compose ("%1", n), general_midi_program_names[n])));
+ }
+ }
+
+ return _gm_patches;
+}
+
+string
+InstrumentInfo::get_plugin_patch_name (boost::shared_ptr<Processor> p, uint16_t bank, uint8_t program, uint8_t channel) const
+{
+ boost::shared_ptr<PluginInsert> insert = boost::dynamic_pointer_cast<PluginInsert> (p);
+
+ if (insert) {
+ boost::shared_ptr<Plugin> pp = insert->plugin();
+
+ if (pp->current_preset_uses_general_midi()) {
+ return MIDI::Name::general_midi_program_names[std::min((uint8_t) 127,program)];
+ }
+ }
+
+ return string_compose (_("preset %1 (bank %2)"), (int) program, (int) bank);
+}
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index bd916458dd..318524d8ed 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -1014,11 +1014,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, boost::shared_ptr<
_output->set_user_latency (0);
}
- boost::shared_ptr<Processor> instr = the_instrument();
- if (instr) {
- _instrument_info.set_internal_instrument (instr);
- }
-
+ reset_instrument_info ();
processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
set_processor_positions ();
@@ -1167,11 +1163,7 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
_output->set_user_latency (0);
}
- boost::shared_ptr<Processor> instr = the_instrument();
- if (instr) {
- _instrument_info.set_internal_instrument (instr);
- }
-
+ reset_instrument_info ();
processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
set_processor_positions ();
@@ -1378,7 +1370,7 @@ Route::clear_processors (Placement p)
processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
set_processor_positions ();
- _instrument_info.set_internal_instrument (boost::shared_ptr<Processor>());
+ reset_instrument_info ();
if (!already_deleting) {
_session.clear_deletion_in_progress();
@@ -1478,11 +1470,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
}
}
- boost::shared_ptr<Processor> instr = the_instrument();
- if (instr) {
- _instrument_info.set_internal_instrument (instr);
- }
-
+ reset_instrument_info ();
processor->drop_references ();
processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
set_processor_positions ();
@@ -1579,12 +1567,20 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams*
(*i)->drop_references ();
}
+ reset_instrument_info ();
processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
set_processor_positions ();
return 0;
}
+void
+Route::reset_instrument_info ()
+{
+ boost::shared_ptr<Processor> instr = the_instrument();
+ _instrument_info.set_internal_instrument (instr);
+}
+
/** Caller must hold process lock */
int
Route::configure_processors (ProcessorStreams* err)
@@ -2543,6 +2539,7 @@ Route::set_processor_state (const XMLNode& node)
}
}
+ reset_instrument_info ();
processors_changed (RouteProcessorChange ());
set_processor_positions ();
}
@@ -4067,9 +4064,11 @@ Route::the_instrument () const
{
Glib::RWLock::WriterLock lm (_processor_lock);
for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
- if ((*i)->input_streams().n_midi() > 0 &&
- (*i)->output_streams().n_audio() > 0) {
- return (*i);
+ if (boost::dynamic_pointer_cast<PluginInsert>(*i)) {
+ if ((*i)->input_streams().n_midi() > 0 &&
+ (*i)->output_streams().n_audio() > 0) {
+ return (*i);
+ }
}
}
return boost::shared_ptr<Processor>();
diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc
index 1afc496b16..84186fd672 100644
--- a/libs/ardour/vst_plugin.cc
+++ b/libs/ardour/vst_plugin.cc
@@ -598,7 +598,7 @@ VSTPlugin::find_presets ()
int const vst_version = _plugin->dispatcher (_plugin, effGetVstVersion, 0, 0, NULL, 0);
for (int i = 0; i < _plugin->numPrograms; ++i) {
- PresetRecord r (string_compose (X_("VST:%1:%2"), unique_id (), i), "", false);
+ PresetRecord r (string_compose (X_("VST:%1:%2"), unique_id (), i), "", -1, false);
if (vst_version >= 2) {
char buf[256];
@@ -628,7 +628,7 @@ VSTPlugin::find_presets ()
assert (uri);
assert (label);
- PresetRecord r (uri->value(), label->value(), true);
+ PresetRecord r (uri->value(), label->value(), -1, true);
_presets.insert (make_pair (r.uri, r));
}
}
diff --git a/libs/midi++2/midi++/midnam_patch.h b/libs/midi++2/midi++/midnam_patch.h
index cbf64299ea..276b402086 100644
--- a/libs/midi++2/midi++/midnam_patch.h
+++ b/libs/midi++2/midi++/midnam_patch.h
@@ -200,6 +200,8 @@ public:
XMLNode& get_state (void);
int set_state (const XMLTree&, const XMLNode&);
+ void set_patch_banks (const PatchBanks&);
+
private:
std::string _name;
AvailableForChannels _available_for_channels;
@@ -352,6 +354,8 @@ private:
MasterDeviceNames::Models _all_models;
};
+extern const char* general_midi_program_names[128]; /* 0 .. 127 */
+
}
}
diff --git a/libs/midi++2/midnam_patch.cc b/libs/midi++2/midnam_patch.cc
index 66d3219310..1ad5cf9dc5 100644
--- a/libs/midi++2/midnam_patch.cc
+++ b/libs/midi++2/midnam_patch.cc
@@ -262,6 +262,28 @@ PatchBank::set_patch_name_list (const PatchNameList& pnl)
return 0;
}
+void
+ChannelNameSet::set_patch_banks (const ChannelNameSet::PatchBanks& pb)
+{
+ _patch_banks = pb;
+
+ _patch_map.clear ();
+ _patch_list.clear ();
+ _patch_list_name = "";
+ _available_for_channels.clear ();
+
+ for (PatchBanks::const_iterator pbi = _patch_banks.begin(); pbi != _patch_banks.end(); ++pbi) {
+ for (PatchBank::PatchNameList::const_iterator pni = (*pbi)->patch_name_list().begin(); pni != (*pbi)->patch_name_list().end(); ++pni) {
+ _patch_map[(*pni)->patch_primary_key()] = (*pni);
+ _patch_list.push_back ((*pni)->patch_primary_key());
+ }
+ }
+
+ for (uint8_t n = 0; n < 16; ++n) {
+ _available_for_channels.insert (n);
+ }
+}
+
XMLNode&
ChannelNameSet::get_state (void)
{
@@ -526,6 +548,136 @@ MIDINameDocument::get_state(void)
return nothing;
}
+const char* general_midi_program_names[128] = {
+ "Acoustic Grand Piano",
+ "Bright Acoustic Piano",
+ "Electric Grand Piano",
+ "Honky-tonk Piano",
+ "Rhodes Piano",
+ "Chorused Piano",
+ "Harpsichord",
+ "Clavinet",
+ "Celesta",
+ "Glockenspiel",
+ "Music Box",
+ "Vibraphone",
+ "Marimba",
+ "Xylophone",
+ "Tubular Bells",
+ "Dulcimer",
+ "Hammond Organ",
+ "Percussive Organ",
+ "Rock Organ",
+ "Church Organ",
+ "Reed Organ",
+ "Accordion",
+ "Harmonica",
+ "Tango Accordion",
+ "Acoustic Guitar (nylon)",
+ "Acoustic Guitar (steel)",
+ "Electric Guitar (jazz)",
+ "Electric Guitar (clean)",
+ "Electric Guitar (muted)",
+ "Overdriven Guitar",
+ "Distortion Guitar",
+ "Guitar Harmonics",
+ "Acoustic Bass",
+ "Electric Bass (finger)",
+ "Electric Bass (pick)",
+ "Fretless Bass",
+ "Slap Bass 1",
+ "Slap Bass 2",
+ "Synth Bass 1",
+ "Synth Bass 2",
+ "Violin",
+ "Viola",
+ "Cello",
+ "Contrabass",
+ "Tremolo Strings",
+ "Pizzicato Strings",
+ "Orchestral Harp",
+ "Timpani",
+ "String Ensemble 1",
+ "String Ensemble 2",
+ "SynthStrings 1",
+ "SynthStrings 2",
+ "Choir Aahs",
+ "Voice Oohs",
+ "Synth Voice",
+ "Orchestra Hit",
+ "Trumpet",
+ "Trombone",
+ "Tuba",
+ "Muted Trumpet",
+ "French Horn",
+ "Brass Section",
+ "Synth Brass 1",
+ "Synth Brass 2",
+ "Soprano Sax",
+ "Alto Sax",
+ "Tenor Sax",
+ "Baritone Sax",
+ "Oboe",
+ "English Horn",
+ "Bassoon",
+ "Clarinet",
+ "Piccolo",
+ "Flute",
+ "Recorder",
+ "Pan Flute",
+ "Bottle Blow",
+ "Shakuhachi",
+ "Whistle",
+ "Ocarina",
+ "Lead 1 (square)",
+ "Lead 2 (sawtooth)",
+ "Lead 3 (calliope lead)",
+ "Lead 4 (chiff lead)",
+ "Lead 5 (charang)",
+ "Lead 6 (voice)",
+ "Lead 7 (fifths)",
+ "Lead 8 (bass + lead)",
+ "Pad 1 (new age)",
+ "Pad 2 (warm)",
+ "Pad 3 (polysynth)",
+ "Pad 4 (choir)",
+ "Pad 5 (bowed)",
+ "Pad 6 (metallic)",
+ "Pad 7 (halo)",
+ "Pad 8 (sweep)",
+ "FX 1 (rain)",
+ "FX 2 (soundtrack)",
+ "FX 3 (crystal)",
+ "FX 4 (atmosphere)",
+ "FX 5 (brightness)",
+ "FX 6 (goblins)",
+ "FX 7 (echoes)",
+ "FX 8 (sci-fi)",
+ "Sitar",
+ "Banjo",
+ "Shamisen",
+ "Koto",
+ "Kalimba",
+ "Bagpipe",
+ "Fiddle",
+ "Shanai",
+ "Tinkle Bell",
+ "Agogo",
+ "Steel Drums",
+ "Woodblock",
+ "Taiko Drum",
+ "Melodic Tom",
+ "Synth Drum",
+ "Reverse Cymbal",
+ "Guitar Fret Noise",
+ "Breath Noise",
+ "Seashore",
+ "Bird Tweet",
+ "Telephone Ring",
+ "Helicopter",
+ "Applause",
+ "Gunshot",
+};
} //namespace Name