summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Baier <hansfbaier@googlemail.com>2008-12-15 11:05:41 +0000
committerHans Baier <hansfbaier@googlemail.com>2008-12-15 11:05:41 +0000
commit5e7ae490c1616696a733287b62c08416726653ae (patch)
tree9d9d933e7c4afacbb8608cce17e7de779be0b0fe
parentbf7e792e3e499b665c20fc196e53cf05bb99e0c7 (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.h4
-rw-r--r--gtk2_ardour/canvas-program-change.cc18
-rw-r--r--gtk2_ardour/canvas-program-change.h7
-rw-r--r--gtk2_ardour/midi_region_view.cc100
-rw-r--r--gtk2_ardour/midi_region_view.h20
-rw-r--r--libs/ardour/ardour/midi_patch_manager.h34
-rw-r--r--libs/midi++2/midi++/midnam_patch.h35
-rw-r--r--libs/midi++2/midnam_patch.cc2
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;
}