* 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:
parent
c5659dda6e
commit
33852a0728
@ -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 ()
|
||||
{
|
||||
|
@ -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"));
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user