diff options
author | Hans Baier <hansfbaier@googlemail.com> | 2008-12-15 11:05:41 +0000 |
---|---|---|
committer | Hans Baier <hansfbaier@googlemail.com> | 2008-12-15 11:05:41 +0000 |
commit | 5e7ae490c1616696a733287b62c08416726653ae (patch) | |
tree | 9d9d933e7c4afacbb8608cce17e7de779be0b0fe | |
parent | bf7e792e3e499b665c20fc196e53cf05bb99e0c7 (diff) |
* first working prototype of changing program changes by scroll wheel (still some automation points issues)
git-svn-id: svn://localhost/ardour2/branches/3.0@4324 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | gtk2_ardour/canvas-flag.h | 4 | ||||
-rw-r--r-- | gtk2_ardour/canvas-program-change.cc | 18 | ||||
-rw-r--r-- | gtk2_ardour/canvas-program-change.h | 7 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.cc | 100 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.h | 20 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_patch_manager.h | 34 | ||||
-rw-r--r-- | libs/midi++2/midi++/midnam_patch.h | 35 | ||||
-rw-r--r-- | libs/midi++2/midnam_patch.cc | 2 |
8 files changed, 185 insertions, 35 deletions
diff --git a/gtk2_ardour/canvas-flag.h b/gtk2_ardour/canvas-flag.h index 0f45667614..57a78ef992 100644 --- a/gtk2_ardour/canvas-flag.h +++ b/gtk2_ardour/canvas-flag.h @@ -46,15 +46,15 @@ public: void set_text(string& a_text); protected: - CanvasFlagText* _text; + CanvasFlagText* _text; double _height; guint _outline_color_rgba; guint _fill_color_rgba; + MidiRegionView& _region; private: void delete_allocated_objects(); - MidiRegionView& _region; SimpleLine* _line; CanvasFlagRect* _rect; }; diff --git a/gtk2_ardour/canvas-program-change.cc b/gtk2_ardour/canvas-program-change.cc index 2e6473ef66..8c24ce95e3 100644 --- a/gtk2_ardour/canvas-program-change.cc +++ b/gtk2_ardour/canvas-program-change.cc @@ -1,6 +1,7 @@ #include "canvas-program-change.h" #include <iostream> #include "ardour_ui.h" +#include "midi_region_view.h" using namespace Gnome::Canvas; using namespace std; @@ -32,14 +33,13 @@ CanvasProgramChange::~CanvasProgramChange() bool CanvasProgramChange::on_event(GdkEvent* ev) { - cerr << "CanvasProgramChange::on_event(GdkEvent* ev) type " << ev->type << endl; switch (ev->type) { case GDK_SCROLL: if (ev->scroll.direction == GDK_SCROLL_UP) { - previous_patch(); + _region.previous_program(*this); return true; } else if (ev->scroll.direction == GDK_SCROLL_DOWN) { - next_patch(); + _region.next_program(*this); return true; } default: @@ -48,15 +48,3 @@ CanvasProgramChange::on_event(GdkEvent* ev) return false; } - -void -CanvasProgramChange::previous_patch() -{ - cerr << "decreasing program" << endl; -} - -void -CanvasProgramChange::next_patch() -{ - cerr << "increasing program" << endl; -} diff --git a/gtk2_ardour/canvas-program-change.h b/gtk2_ardour/canvas-program-change.h index 929c302b7c..2620359036 100644 --- a/gtk2_ardour/canvas-program-change.h +++ b/gtk2_ardour/canvas-program-change.h @@ -28,16 +28,13 @@ public: void set_event_time(nframes_t new_time) { _event_time = new_time; }; uint8_t program() const { return _program; } - void set_program(uint8_t new_time) { _program = new_time; }; + void set_program(uint8_t new_program) { _program = new_program; }; uint8_t channel() const { return _channel; } - void set_channel(uint8_t new_time) { _channel = new_time; }; + void set_channel(uint8_t new_channel) { _channel = new_channel; }; private: - void previous_patch(); - void next_patch(); - nframes_t _event_time; uint8_t _program; uint8_t _channel; diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index ed4176bbfb..c81edd4e7b 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -631,7 +631,7 @@ MidiRegionView::find_and_insert_program_change_flags() for (AutomationList::const_iterator event = control->second->list()->begin(); event != control->second->list()->end(); ++event) { double event_time = (*event)->when; - double program_number = (*event)->value; + double program_number = floor((*event)->value + 0.5); //cerr << " got program change on channel " << int(channel) << " time: " << event_time << " number: " << program_number << endl; @@ -640,17 +640,17 @@ MidiRegionView::find_and_insert_program_change_flags() boost::shared_ptr<Evoral::Control> msb_control = _model->control(bank_select_msb); uint8_t msb = 0; if (msb_control != 0) { - msb = uint8_t(msb_control->get_float(true, event_time)); + msb = uint8_t(floor(msb_control->get_float(true, event_time) + 0.5)); } Evoral::Parameter bank_select_lsb(MidiCCAutomation, channel, MIDI_CTL_LSB_BANK); boost::shared_ptr<Evoral::Control> lsb_control = _model->control(bank_select_lsb); uint8_t lsb = 0; if (lsb_control != 0) { - lsb = uint8_t(lsb_control->get_float(true, event_time)); + lsb = uint8_t(floor(lsb_control->get_float(true, event_time) + 0.5)); } - cerr << " got msb " << int(msb) << " and lsb " << int(lsb) << " thread_id: " << pthread_self() << endl; + //cerr << " got msb " << int(msb) << " and lsb " << int(lsb) << " thread_id: " << pthread_self() << endl; MIDI::Name::PatchPrimaryKey patch_key(msb, lsb, program_number); @@ -665,7 +665,7 @@ MidiRegionView::find_and_insert_program_change_flags() ControlEvent program_change(nframes_t(event_time), uint8_t(program_number), channel); if (patch != 0) { - cerr << " got patch with name " << patch->name() << " number " << patch->number() << endl; + //cerr << " got patch with name " << patch->name() << " number " << patch->number() << endl; add_pgm_change(program_change, patch->name()); } else { char buf[4]; @@ -1013,22 +1013,106 @@ MidiRegionView::add_pgm_change(ControlEvent& program, string displaytext) _pgm_changes.push_back(pgm_change); } +void +MidiRegionView::get_patch_key_at(double time, uint8_t channel, MIDI::Name::PatchPrimaryKey& key) +{ + + cerr << "getting patch key at " << time << " for channel " << channel << endl; + Evoral::Parameter bank_select_msb(MidiCCAutomation, channel, MIDI_CTL_MSB_BANK); + boost::shared_ptr<Evoral::Control> msb_control = _model->control(bank_select_msb); + float msb = -1.0; + if (msb_control != 0) { + msb = int(msb_control->get_float(true, time)); + cerr << "got msb " << msb; + } + + Evoral::Parameter bank_select_lsb(MidiCCAutomation, channel, MIDI_CTL_LSB_BANK); + boost::shared_ptr<Evoral::Control> lsb_control = _model->control(bank_select_lsb); + float lsb = -1.0; + if (lsb_control != 0) { + lsb = lsb_control->get_float(true, time); + cerr << " got lsb " << lsb; + } + + Evoral::Parameter program_change(MidiPgmChangeAutomation, channel, 0); + boost::shared_ptr<Evoral::Control> program_control = _model->control(program_change); + float program_number = -1.0; + if (program_control != 0) { + program_number = program_control->get_float(true, time); + cerr << " got program " << program_number << endl; + } + + key.msb = (int) floor(msb + 0.5); + key.lsb = (int) floor(lsb + 0.5); + key.program_number = (int) floor(program_number + 0.5); + assert(key.is_sane()); +} + + void -MidiRegionView::alter_program_change(ControlEvent& old_program, ControlEvent& new_program) +MidiRegionView::alter_program_change(ControlEvent& old_program, const MIDI::Name::PatchPrimaryKey& new_patch) { + // TODO: Get the real event here and alter them at the original times + Evoral::Parameter bank_select_msb(MidiCCAutomation, old_program.channel, MIDI_CTL_MSB_BANK); + boost::shared_ptr<Evoral::Control> msb_control = _model->control(bank_select_msb); + if (msb_control != 0) { + msb_control->set_float(float(new_patch.msb), true, old_program.time); + } + + // TODO: Get the real event here and alter them at the original times + Evoral::Parameter bank_select_lsb(MidiCCAutomation, old_program.channel, MIDI_CTL_LSB_BANK); + boost::shared_ptr<Evoral::Control> lsb_control = _model->control(bank_select_lsb); + if (lsb_control != 0) { + lsb_control->set_float(float(new_patch.lsb), true, old_program.time); + } + + Evoral::Parameter program_change(MidiPgmChangeAutomation, old_program.channel, 0); + boost::shared_ptr<Evoral::Control> program_control = _model->control(program_change); + + assert(program_control != 0); + program_control->set_float(float(new_patch.program_number), true, old_program.time); + + redisplay_model(); } void -MidiRegionView::previous_program(boost::shared_ptr<CanvasProgramChange> program) +MidiRegionView::previous_program(CanvasProgramChange& program) { + MIDI::Name::PatchPrimaryKey key; + get_patch_key_at(program.event_time(), program.channel(), key); + + boost::shared_ptr<MIDI::Name::Patch> patch = + MIDI::Name::MidiPatchManager::instance().previous_patch( + _model_name, + _custom_device_mode, + program.channel(), + key + ); + ControlEvent program_change_event(program.event_time(), program.program(), program.channel()); + if (patch) { + alter_program_change(program_change_event, patch->patch_primary_key()); + } } void -MidiRegionView::next_program(boost::shared_ptr<CanvasProgramChange> program) +MidiRegionView::next_program(CanvasProgramChange& program) { + MIDI::Name::PatchPrimaryKey key; + get_patch_key_at(program.event_time(), program.channel(), key); + boost::shared_ptr<MIDI::Name::Patch> patch = + MIDI::Name::MidiPatchManager::instance().next_patch( + _model_name, + _custom_device_mode, + program.channel(), + key + ); + ControlEvent program_change_event(program.event_time(), program.program(), program.channel()); + if (patch) { + alter_program_change(program_change_event, patch->patch_primary_key()); + } } void diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 1789437d83..ca4a43f962 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -44,6 +44,12 @@ namespace ARDOUR { class MidiModel; }; +namespace MIDI { + namespace Name { + struct PatchPrimaryKey; + }; +}; + class MidiTimeAxisView; class GhostRegion; class AutomationTimeAxisView; @@ -94,12 +100,20 @@ class MidiRegionView : public RegionView ControlEvent(nframes_t a_time, uint8_t a_value, uint8_t a_channel) : time(a_time), value(a_value), channel(a_channel) {} + + ControlEvent& operator=(const ControlEvent& other) { + time = other.time; + value = other.value; + channel = other.channel; + return *this; + } }; void add_pgm_change(ControlEvent& program, string displaytext); - void alter_program_change(ControlEvent& old_program, ControlEvent& new_program); - void previous_program(boost::shared_ptr<ArdourCanvas::CanvasProgramChange> program); - void next_program(boost::shared_ptr<ArdourCanvas::CanvasProgramChange> program); + void get_patch_key_at(double time, uint8_t channel, MIDI::Name::PatchPrimaryKey& key); + void alter_program_change(ControlEvent& old_program, const MIDI::Name::PatchPrimaryKey& new_patch); + void previous_program(ArdourCanvas::CanvasProgramChange& program); + void next_program(ArdourCanvas::CanvasProgramChange& program); void find_and_insert_program_change_flags(); void begin_write(); diff --git a/libs/ardour/ardour/midi_patch_manager.h b/libs/ardour/ardour/midi_patch_manager.h index 1642b1a22b..f617d82998 100644 --- a/libs/ardour/ardour/midi_patch_manager.h +++ b/libs/ardour/ardour/midi_patch_manager.h @@ -80,6 +80,40 @@ public: } } + boost::shared_ptr<Patch> previous_patch( + string model, + string custom_device_mode, + uint8_t channel, + PatchPrimaryKey patch_key) { + + boost::shared_ptr<MIDI::Name::MasterDeviceNames> master_device = master_device_by_model(model); + + if (master_device != 0 && custom_device_mode != "") { + return master_device-> + channel_name_set_by_device_mode_and_channel(custom_device_mode, channel)-> + previous_patch(patch_key); + } else { + return boost::shared_ptr<Patch>(); + } + } + + boost::shared_ptr<Patch> next_patch( + string model, + string custom_device_mode, + uint8_t channel, + PatchPrimaryKey patch_key) { + + boost::shared_ptr<MIDI::Name::MasterDeviceNames> master_device = master_device_by_model(model); + + if (master_device != 0 && custom_device_mode != "") { + return master_device-> + channel_name_set_by_device_mode_and_channel(custom_device_mode, channel)-> + next_patch(patch_key); + } else { + return boost::shared_ptr<Patch>(); + } + } + std::list<string> custom_device_mode_names_by_model(std::string model_name) { if (model_name != "") { return master_device_by_model(model_name)->custom_device_mode_names(); diff --git a/libs/midi++2/midi++/midnam_patch.h b/libs/midi++2/midi++/midnam_patch.h index 1fa73a56b6..24838294ec 100644 --- a/libs/midi++2/midi++/midnam_patch.h +++ b/libs/midi++2/midi++/midnam_patch.h @@ -133,12 +133,15 @@ private: PatchNameList _patch_name_list; }; +#include <iostream> + class ChannelNameSet : public PBD::Stateful { public: typedef std::set<uint8_t> AvailableForChannels; typedef std::list<boost::shared_ptr<PatchBank> > PatchBanks; typedef std::map<PatchPrimaryKey, boost::shared_ptr<Patch> > PatchMap; + typedef std::list<PatchPrimaryKey> PatchList; ChannelNameSet() {}; virtual ~ChannelNameSet() {}; @@ -158,12 +161,39 @@ public: boost::shared_ptr<Patch> previous_patch(PatchPrimaryKey& key) { assert(key.is_sane()); - return (*(--_patch_map.find(key))).second; + std::cerr << "finding patch with " << key.msb << "/" << key.lsb << "/" <<key.program_number << std::endl; + for (PatchList::const_iterator i = _patch_list.begin(); + i != _patch_list.end(); + ++i) { + if ((*i) == key) { + if (i != _patch_list.begin()) { + std::cerr << "got it!" << std::endl; + --i; + return _patch_map[*i]; + } + } + } + + return boost::shared_ptr<Patch>(); } boost::shared_ptr<Patch> next_patch(PatchPrimaryKey& key) { assert(key.is_sane()); - return (*(++_patch_map.find(key))).second; + std::cerr << "finding patch with " << key.msb << "/" << key.lsb << "/" <<key.program_number << std::endl; + for (PatchList::const_iterator i = _patch_list.begin(); + i != _patch_list.end(); + ++i) { + if ((*i) == key) { + if (++i != _patch_list.end()) { + std::cerr << "got it!" << std::endl; + return _patch_map[*i]; + } else { + --i; + } + } + } + + return boost::shared_ptr<Patch>(); } XMLNode& get_state (void); @@ -174,6 +204,7 @@ private: AvailableForChannels _available_for_channels; PatchBanks _patch_banks; PatchMap _patch_map; + PatchList _patch_list; }; class Note : public PBD::Stateful diff --git a/libs/midi++2/midnam_patch.cc b/libs/midi++2/midnam_patch.cc index 555e19fc63..acbf9208a8 100644 --- a/libs/midi++2/midnam_patch.cc +++ b/libs/midi++2/midnam_patch.cc @@ -79,6 +79,7 @@ Patch::set_state (const XMLNode& node) } //cerr << "deserialized Patch: name: " << _name << _id.msb << " lsb: " << _id.lsb << " program " << _id.program_number << endl; + // TODO: handle that more gracefully assert(_id.is_sane()); return 0; @@ -230,6 +231,7 @@ ChannelNameSet::set_state (const XMLNode& node) patch != patches.end(); ++patch) { _patch_map[(*patch)->patch_primary_key()] = *patch; + _patch_list.push_back((*patch)->patch_primary_key()); } // cerr << "after PatchBank pushback" << endl; } |