* Fixed crash on closing MIDI automation tracks, because ARDOUR::Parameter::operator< violated strict weak ordering,
which is necessary for std::set to work correctly * few small style guide corrections git-svn-id: svn://localhost/ardour2/branches/3.0@3363 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
8ab37dd700
commit
0c25b2aa8e
@ -1619,8 +1619,9 @@ void
|
||||
RouteTimeAxisView::automation_track_hidden (Parameter param)
|
||||
{
|
||||
RouteAutomationNode* ran = automation_track(param);
|
||||
if (!ran)
|
||||
if (!ran) {
|
||||
return;
|
||||
}
|
||||
|
||||
_show_automation.erase(param);
|
||||
ran->track->get_state_node()->add_property (X_("shown"), X_("no"));
|
||||
|
@ -141,13 +141,15 @@ template<typename T>
|
||||
bool
|
||||
MidiRingBufferBase<T>::full_peek(size_t size, T* dst)
|
||||
{
|
||||
if (read_space() < size)
|
||||
if (read_space() < size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t read_size = peek(size, dst);
|
||||
|
||||
if (read_size < size)
|
||||
if (read_size < size) {
|
||||
peek(size - read_size, dst + read_size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -181,13 +183,15 @@ template<typename T>
|
||||
bool
|
||||
MidiRingBufferBase<T>::full_read(size_t size, T* dst)
|
||||
{
|
||||
if (read_space() < size)
|
||||
if (read_space() < size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t read_size = read(size, dst);
|
||||
|
||||
if (read_size < size)
|
||||
if (read_size < size) {
|
||||
read(size - read_size, dst + read_size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -292,11 +296,14 @@ inline bool
|
||||
MidiRingBuffer::read(double* time, size_t* size, Byte* buf)
|
||||
{
|
||||
bool success = MidiRingBufferBase<Byte>::full_read(sizeof(double), (Byte*)time);
|
||||
if (success)
|
||||
|
||||
if (success) {
|
||||
success = MidiRingBufferBase<Byte>::full_read(sizeof(size_t), (Byte*)size);
|
||||
if (success)
|
||||
}
|
||||
if (success) {
|
||||
success = MidiRingBufferBase<Byte>::full_read(*size, buf);
|
||||
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -308,8 +315,9 @@ inline bool
|
||||
MidiRingBuffer::read_prefix(double* time, size_t* size)
|
||||
{
|
||||
bool success = MidiRingBufferBase<Byte>::full_read(sizeof(double), (Byte*)time);
|
||||
if (success)
|
||||
if (success) {
|
||||
success = MidiRingBufferBase<Byte>::full_read(sizeof(size_t), (Byte*)size);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
@ -338,8 +346,9 @@ MidiRingBuffer::write(double time, size_t size, const Byte* buf)
|
||||
// Don't write event if it doesn't match channel filter
|
||||
if (is_channel_event(buf[0]) && get_channel_mode() == FilterChannels) {
|
||||
Byte channel = buf[0] & 0x0F;
|
||||
if ( !(get_channel_mask() & (1L << channel)) )
|
||||
if ( !(get_channel_mask() & (1L << channel)) ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (write_space() < (sizeof(double) + sizeof(size_t) + size)) {
|
||||
@ -388,8 +397,9 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
|
||||
|
||||
full_peek(sizeof(double), (Byte*)&ev_time);
|
||||
|
||||
if (ev_time > end)
|
||||
if (ev_time > end) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool success = MidiRingBufferBase<Byte>::full_read(sizeof(double), (Byte*)&ev_time);
|
||||
if (success) {
|
||||
|
@ -58,17 +58,61 @@ public:
|
||||
inline uint32_t id() const { return _id; }
|
||||
inline uint8_t channel() const { return _channel; }
|
||||
|
||||
/**
|
||||
* Equivalence operator
|
||||
* It is obvious from the definition that this operator
|
||||
* is transitive, as required by stict weak ordering
|
||||
* (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);
|
||||
}
|
||||
|
||||
/** Arbitrary but fixed ordering (for use in e.g. std::map) */
|
||||
/** Strict weak ordering
|
||||
* (see: http://www.sgi.com/tech/stl/StrictWeakOrdering.html)
|
||||
* This is necessary so that std::set works):
|
||||
* Sort Parameters first according to type then to id and lastly to channel.
|
||||
*
|
||||
* Proof:
|
||||
* <ol>
|
||||
* <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 assuming the contrary,
|
||||
* that f(x, z) does not hold.
|
||||
* That would imply exactly one of the following:
|
||||
* <ol>
|
||||
* <li> x == z which contradicts the assumption f(x, y) and f(y, x)
|
||||
* because of antisymmetry.
|
||||
* </li>
|
||||
* <li> f(z, x) is true. That would imply that one of the ivars (we call it i)
|
||||
* of x is greater than the same ivar in z while all "previous" ivars
|
||||
* are equal. That would imply that also in y all those "previous"
|
||||
* ivars are equal and because if x.i > z.i it is impossible
|
||||
* that there is an y that satisfies x.i < y.i < z.i at the same
|
||||
* time which contradicts the assumption.
|
||||
* </li>
|
||||
* </ol>
|
||||
* </li>
|
||||
* </ol>
|
||||
*/
|
||||
|
||||
inline bool operator<(const Parameter& id) const {
|
||||
#ifndef NDEBUG
|
||||
if (_type == NullAutomation)
|
||||
PBD::warning << "Uninitialized Parameter compared." << endmsg;
|
||||
#endif
|
||||
return (_channel < id._channel || _type < id._type || _id < id._id);
|
||||
if (_type < id._type) {
|
||||
return true;
|
||||
} else if (_type == id._type && _id < id._id) {
|
||||
return true;
|
||||
} else if (_id == id._id && _channel < id._channel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline operator bool() const { return (_type != 0); }
|
||||
|
Loading…
Reference in New Issue
Block a user