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
This commit is contained in:
Paul Davis 2012-06-11 22:59:35 +00:00
parent c816917411
commit d97312d438
17 changed files with 389 additions and 128 deletions

View File

@ -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);
{
/* 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;
} 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;
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;

View File

@ -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;

View File

@ -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 ());
}
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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 ();
}

View File

@ -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;

View File

@ -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 */

View File

@ -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.
*/

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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>();

View File

@ -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));
}
}

View File

@ -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 */
}
}

View File

@ -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