* Added Menu to add a Program change parameter lane

* made adding automation lanes add them for every active channel on the track
* Evoral::Parameter.hpp: Strict weak ordering again: make the proof a bit easier to read
                         Make the implementation conform to the proof
                         order Parameters according to type, then channel, then id


git-svn-id: svn://localhost/ardour2/branches/3.0@4421 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Hans Baier 2009-01-21 08:32:23 +00:00
parent c5659dda6e
commit 33852a0728
3 changed files with 56 additions and 43 deletions

View File

@ -304,13 +304,15 @@ MidiTimeAxisView::build_automation_action_menu ()
automation_items.push_back (SeparatorElem());
automation_items.push_back (MenuElem (_("Controller..."),
mem_fun(*this, &MidiTimeAxisView::add_cc_track)));
automation_items.push_back (MenuElem (_("Program Change"),
sigc::bind(mem_fun(*this, &MidiTimeAxisView::add_parameter_track),
Evoral::Parameter(MidiPgmChangeAutomation))));
automation_items.push_back (MenuElem (_("Bender"),
sigc::bind(mem_fun(*this, &MidiTimeAxisView::add_parameter_track),
Evoral::Parameter(MidiPitchBenderAutomation))));
automation_items.push_back (MenuElem (_("Pressure"),
sigc::bind(mem_fun(*this, &MidiTimeAxisView::add_parameter_track),
Evoral::Parameter(MidiChannelPressureAutomation))));
}
Gtk::Menu*
@ -467,49 +469,57 @@ MidiTimeAxisView::add_cc_track()
void
MidiTimeAxisView::add_parameter_track(const Evoral::Parameter& param)
{
create_automation_child(param, true);
if ( param.type() != MidiCCAutomation &&
param.type() != MidiPgmChangeAutomation &&
param.type() != MidiPitchBenderAutomation &&
param.type() != MidiChannelPressureAutomation
) {
error << "MidiTimeAxisView: unknown automation child "
<< ARDOUR::EventTypeMap::instance().to_symbol(param) << endmsg;
return;
}
// create the parameter lane for each selected channel
uint16_t selected_channels = _channel_selector.get_selected_channels();
for (uint8_t i = 0; i < 16; i++) {
if (selected_channels & (0x0001 << i)) {
Evoral::Parameter param_with_channel(param.type(), i, param.id());
create_automation_child(param_with_channel, true);
}
}
}
void
MidiTimeAxisView::create_automation_child (const Evoral::Parameter& param, bool show)
{
if ( param.type() == MidiCCAutomation ||
param.type() == MidiPgmChangeAutomation ||
param.type() == MidiPitchBenderAutomation ||
param.type() == MidiChannelPressureAutomation
) {
/* These controllers are region "automation", so we do not create
* an AutomationList/Line for the track */
/* These controllers are region "automation", so we do not create
* an AutomationList/Line for the track */
AutomationTracks::iterator existing = _automation_tracks.find(param);
if (existing != _automation_tracks.end())
return;
AutomationTracks::iterator existing = _automation_tracks.find(param);
if (existing != _automation_tracks.end())
return;
boost::shared_ptr<AutomationControl> c
= boost::dynamic_pointer_cast<AutomationControl>(_route->data().control(param));
boost::shared_ptr<AutomationControl> c
= boost::dynamic_pointer_cast<AutomationControl>(_route->data().control(param));
if (!c) {
c = boost::dynamic_pointer_cast<AutomationControl>(_route->control_factory(param));
_route->add_control(c);
}
boost::shared_ptr<AutomationTimeAxisView> track(new AutomationTimeAxisView (_session,
_route, boost::shared_ptr<ARDOUR::Automatable>(), c,
_editor,
*this,
true,
parent_canvas,
_route->describe_parameter(param)));
add_automation_child(param, track, show);
} else {
error << "MidiTimeAxisView: unknown automation child "
<< ARDOUR::EventTypeMap::instance().to_symbol(param) << endmsg;
if (!c) {
c = boost::dynamic_pointer_cast<AutomationControl>(_route->control_factory(param));
_route->add_control(c);
}
boost::shared_ptr<AutomationTimeAxisView> track(new AutomationTimeAxisView (_session,
_route, boost::shared_ptr<ARDOUR::Automatable>(), c,
_editor,
*this,
true,
parent_canvas,
_route->describe_parameter(param)));
add_automation_child(param, track, show);
}
void
MidiTimeAxisView::route_active_changed ()
{

View File

@ -1665,7 +1665,8 @@ RouteTimeAxisView::automation_track_hidden (Evoral::Parameter param)
if (!ran) {
return;
}
// if Evoral::Parameter::operator< doesn't obey strict weak ordering, we may crash here....
_show_automation.erase(param);
ran->track->get_state_node()->add_property (X_("shown"), X_("no"));

View File

@ -47,8 +47,8 @@ public:
virtual ~Parameter() {}
inline uint32_t type() const { return _type; }
inline uint32_t id() const { return _id; }
inline uint8_t channel() const { return _channel; }
inline uint32_t id() const { return _id; }
/** Equivalence operator
* It is obvious from the definition that this operator
@ -56,7 +56,7 @@ public:
* (see: http://www.sgi.com/tech/stl/StrictWeakOrdering.html)
*/
inline bool operator==(const Parameter& id) const {
return (_type == id._type && _id == id._id && _channel == id._channel);
return (_type == id._type && _channel == id._channel && _id == id._id );
}
/** Strict weak ordering
@ -68,9 +68,11 @@ public:
* <li>Irreflexivity: f(x, x) is false because of the irreflexivity of \c < in each branch.</li>
* <li>Antisymmetry: given x != y, f(x, y) implies !f(y, x) because of the same
* property of \c < in each branch and the symmetry of operator==. </li>
* <li>Transitivity: let f(x, y) and f(y, z) be true.
* We prove by contradiction, assuming the contrary (f(x, z) is false).
* That would imply exactly one of the following:
* <li>Transitivity: let f(x, y) and f(y, z) => f(x, z) be true.
* We prove by contradiction, assuming the contrary:
* f(x, y) and f(x, z) hold => !f(x, z)
*
* That implies one of the following:
* <ol>
* <li> x == z which contradicts the assumption f(x, y) and f(y, x)
* because of antisymmetry.
@ -87,12 +89,12 @@ public:
* </li>
* </ol>
*/
inline bool operator<(const Parameter& id) const {
if (_type < id._type) {
inline bool operator<(const Parameter& other) const {
if (_type < other._type) {
return true;
} else if (_type == id._type && _id < id._id) {
} else if (_type == other._type && _channel < other._channel) {
return true;
} else if (_id == id._id && _channel < id._channel) {
} else if (_type == other._type && _channel == other._channel && _id < other._id ) {
return true;
}