* added comments to midi_region_view.h

* implemented choosing patches with context menu on the program change flag
* added convenience method and a little refactoring in midi_patch_manager.h

Conflicts:

	.cproject
	build-tmp.sh


git-svn-id: svn://localhost/ardour2/branches/3.0@4338 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Hans Baier 2008-12-23 06:03:45 +00:00
parent e6c2f03ca1
commit e9a9fe30cf
6 changed files with 187 additions and 26 deletions

View File

@ -1,9 +1,12 @@
#include "canvas-program-change.h"
#include <iostream>
#include "ardour/midi_patch_manager.h"
#include "ardour_ui.h"
#include "midi_region_view.h"
#include "canvas-program-change.h"
using namespace Gnome::Canvas;
using namespace MIDI::Name;
using namespace std;
CanvasProgramChange::CanvasProgramChange(
@ -12,7 +15,13 @@ CanvasProgramChange::CanvasProgramChange(
string& text,
double height,
double x,
double y)
double y,
string& model_name,
string& custom_device_mode,
nframes_t event_time,
uint8_t channel,
uint8_t program
)
: CanvasFlag(
region,
parent,
@ -22,18 +31,80 @@ CanvasProgramChange::CanvasProgramChange(
x,
y
)
, _model_name(model_name)
, _custom_device_mode(custom_device_mode)
, _event_time(event_time)
, _channel(channel)
, _program(program)
{
set_text(text);
initialize_popup_menus();
}
CanvasProgramChange::~CanvasProgramChange()
{
}
void
CanvasProgramChange::initialize_popup_menus()
{
boost::shared_ptr<ChannelNameSet> channel_name_set =
MidiPatchManager::instance()
.find_channel_name_set(_model_name, _custom_device_mode, _channel);
if (!channel_name_set) {
return;
}
const ChannelNameSet::PatchBanks& patch_banks = channel_name_set->patch_banks();
// fill popup menu:
Gtk::Menu::MenuList& patch_bank_menus = _popup.items();
for (ChannelNameSet::PatchBanks::const_iterator bank = patch_banks.begin();
bank != patch_banks.end();
++bank) {
Gtk::Menu& patch_bank_menu = *manage(new Gtk::Menu());
const PatchBank::PatchNameList& patches = (*bank)->patch_name_list();
Gtk::Menu::MenuList& patch_menus = patch_bank_menu.items();
for (PatchBank::PatchNameList::const_iterator patch = patches.begin();
patch != patches.end();
++patch) {
patch_menus.push_back(
Gtk::Menu_Helpers::MenuElem(
(*patch)->name(),
sigc::bind(
sigc::mem_fun(*this, &CanvasProgramChange::on_patch_menu_selected),
(*patch)->patch_primary_key())) );
}
patch_bank_menus.push_back(
Gtk::Menu_Helpers::MenuElem(
(*bank)->name(),
patch_bank_menu) );
}
}
void
CanvasProgramChange::on_patch_menu_selected(const PatchPrimaryKey& key)
{
cerr << " got patch program number " << key.program_number << endl;
_region.program_selected(*this, key);
}
bool
CanvasProgramChange::on_event(GdkEvent* ev)
{
switch (ev->type) {
case GDK_BUTTON_PRESS:
if (ev->button.button == 3) {
_popup.popup(ev->button.button, ev->button.time);
return true;
}
break;
case GDK_SCROLL:
if (ev->scroll.direction == GDK_SCROLL_UP) {
_region.previous_program(*this);
@ -42,6 +113,8 @@ CanvasProgramChange::on_event(GdkEvent* ev)
_region.next_program(*this);
return true;
}
break;
default:
break;
}

View File

@ -5,6 +5,12 @@
class MidiRegionView;
namespace MIDI {
namespace Name {
struct PatchPrimaryKey;
}
}
namespace Gnome {
namespace Canvas {
@ -16,14 +22,25 @@ public:
Group& parent,
string& text,
double height,
double x = 0.0,
double y = 0.0
double x,
double y,
string& model_name,
string& custom_device_mode,
nframes_t event_time,
uint8_t channel,
uint8_t program
);
virtual ~CanvasProgramChange();
virtual bool on_event(GdkEvent* ev);
string model_name() const { return _model_name; }
void set_model_name(string model_name) { _model_name = model_name; }
string custom_device_mode() const { return _custom_device_mode; }
void set_custom_device_mode(string custom_device_mode) { _custom_device_mode = custom_device_mode; }
nframes_t event_time() const { return _event_time; }
void set_event_time(nframes_t new_time) { _event_time = new_time; };
@ -33,11 +50,17 @@ public:
uint8_t channel() const { return _channel; }
void set_channel(uint8_t new_channel) { _channel = new_channel; };
void initialize_popup_menus();
void on_patch_menu_selected(const MIDI::Name::PatchPrimaryKey& key);
private:
nframes_t _event_time;
uint8_t _program;
uint8_t _channel;
string _model_name;
string _custom_device_mode;
nframes_t _event_time;
uint8_t _channel;
uint8_t _program;
Gtk::Menu _popup;
};
} // namespace Canvas

View File

@ -1005,10 +1005,18 @@ MidiRegionView::add_pgm_change(ControlEvent& program, string displaytext)
double height = midi_stream_view()->contents_height();
boost::shared_ptr<CanvasProgramChange> pgm_change = boost::shared_ptr<CanvasProgramChange>(
new CanvasProgramChange(*this, *group, displaytext, height, x, 1.0));
pgm_change->set_event_time(program.time);
pgm_change->set_program(program.value);
pgm_change->set_channel(program.channel);
new CanvasProgramChange(
*this,
*group,
displaytext,
height,
x,
1.0,
_model_name,
_custom_device_mode,
program.time,
program.channel,
program.value));
_pgm_changes.push_back(pgm_change);
}
@ -1076,6 +1084,13 @@ MidiRegionView::alter_program_change(ControlEvent& old_program, const MIDI::Name
redisplay_model();
}
void
MidiRegionView::program_selected(CanvasProgramChange& program, const MIDI::Name::PatchPrimaryKey& new_patch)
{
ControlEvent program_change_event(program.event_time(), program.program(), program.channel());
alter_program_change(program_change_event, new_patch);
}
void
MidiRegionView::previous_program(CanvasProgramChange& program)
{

View File

@ -109,11 +109,50 @@ class MidiRegionView : public RegionView
}
};
/**
* Adds a new program change flag to the canvas
* @param program the MidiRegionView::ControlEvent to add
* @param the text to display in the flag
*/
void add_pgm_change(ControlEvent& program, string displaytext);
/**
* Looks up in the automation list in the specified time and channel and sets keys
* fields accordingly
* @param time the time of the program change event
* @param channel the MIDI channel of the event
* @key a reference to an instance of MIDI::Name::PatchPrimaryKey whose fields will
* will be set according to the result of the lookup
*/
void get_patch_key_at(double time, uint8_t channel, MIDI::Name::PatchPrimaryKey& key);
/**
* changes the automation list data of old_program to the new values which correspond to new_patch
* @param old_program identifies the program change event which is to be altered
* @param new_patch defines the new lsb, msb and program number which are to be set in the automation list data
*/
void alter_program_change(ControlEvent& old_program, const MIDI::Name::PatchPrimaryKey& new_patch);
/**
* alters a given program to the new given one (called on context menu select on CanvasProgramChange)
*/
void program_selected(
ArdourCanvas::CanvasProgramChange& program,
const MIDI::Name::PatchPrimaryKey& new_patch);
/**
* alters a given program to be its predecessor in the MIDNAM file
*/
void previous_program(ArdourCanvas::CanvasProgramChange& program);
/**
* alters a given program to be its successor in the MIDNAM file
*/
void next_program(ArdourCanvas::CanvasProgramChange& program);
/**
* displays all program changed events in the region as flags on the canvas
*/
void find_and_insert_program_change_flags();
void begin_write();

View File

@ -63,18 +63,31 @@ public:
boost::shared_ptr<MasterDeviceNames> master_device_by_model(std::string model_name)
{ return _master_devices_by_model[model_name]; }
boost::shared_ptr<ChannelNameSet> find_channel_name_set(
string model,
string custom_device_mode,
uint8_t channel) {
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);
} else {
return boost::shared_ptr<ChannelNameSet>();
}
}
boost::shared_ptr<Patch> find_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);
boost::shared_ptr<ChannelNameSet> channel_name_set = find_channel_name_set(model, custom_device_mode, channel);
if (master_device != 0 && custom_device_mode != "") {
return master_device->
channel_name_set_by_device_mode_and_channel(custom_device_mode, channel)->
find_patch(patch_key);
if (channel_name_set) {
return channel_name_set->find_patch(patch_key);
} else {
return boost::shared_ptr<Patch>();
}
@ -86,12 +99,10 @@ public:
uint8_t channel,
PatchPrimaryKey patch_key) {
boost::shared_ptr<MIDI::Name::MasterDeviceNames> master_device = master_device_by_model(model);
boost::shared_ptr<ChannelNameSet> channel_name_set = find_channel_name_set(model, custom_device_mode, channel);
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);
if (channel_name_set) {
return channel_name_set->previous_patch(patch_key);
} else {
return boost::shared_ptr<Patch>();
}
@ -103,12 +114,10 @@ public:
uint8_t channel,
PatchPrimaryKey patch_key) {
boost::shared_ptr<MIDI::Name::MasterDeviceNames> master_device = master_device_by_model(model);
boost::shared_ptr<ChannelNameSet> channel_name_set = find_channel_name_set(model, custom_device_mode, channel);
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);
if (channel_name_set) {
return channel_name_set->next_patch(patch_key);
} else {
return boost::shared_ptr<Patch>();
}

View File

@ -149,6 +149,8 @@ public:
const string& name() const { return _name; }
void set_name(const string a_name) { _name = a_name; }
const PatchBanks& patch_banks() const { return _patch_banks; }
bool available_for_channel(uint8_t channel) const {
return _available_for_channels.find(channel) != _available_for_channels.end();