[ardour-dev] Automation Write and Touch Bug Fixes

Christopher K. George ckg at yalesda.org
Wed May 5 07:29:53 PDT 2004


I have found and fixed two small bugs in the automation code.  I have never
submitted bug fixes before, so tips on how to do it better next time are welcome.

NOTE: My understanding is that the bugs I fixed affect all kinds of
automation.  I, however, only tested the validity of the fixes with gain
automation.

Automation Write Bug

I found that when writing automation, suddenly moving the gain slider from a
lower gain to maximum gain resulted in the new high gain position point being
moved along rather than written and a new point created.  When recording
automation, only automation points that are very close together should be
connected with a non-horizontal line.  The bug resulted in automation points
that were far apart being connected by a horizontal line when what the user
really intended was for the gain to change suddenly and then continue at the
new gain level.

Automation Touch Bug

I found that while in touch mode, clicking on the slider, moving it, and then
releasing the mouse button correctly modified the automation line, however,
when a second touch was begun, all the date between the end of the previous
touch and the start of the new one were deleted.

The Fix

***In /libs/ardour/io.cc I changed the following function:

void
IO::set_gain (gain_t val, void *src)
{
	_desired_gain = val;
	gain_changed (src);
                                                                             
                                              
	if (_session.transport_stopped() && src != this && gain_automation_recording()) {
		// CKG: Was using add instead of rt_add.
		_gain_automation_curve.rt_add (_session.transport_frame(), val);
	}
}

***In /libs/ardour/ardour/automation_event.h I added the following variable to
the protected section of the AutomationList class:

bool _new_touch;

NOTE: This variable needs to be initialized to false in the constructors for
AutomationLiest.

***In /libs/ardour/automation_event.cc I changed the following functions:

void
AutomationList::start_touch ()
{
	_touching = true;
	_new_touch = true;
}
                                                                             
                                               
void
AutomationList::stop_touch ()
{
	_touching = false;
	_new_touch = false;
}

void
AutomationList::rt_add (double when, double value)
{
	/* this is for automation recording */
															     
	if ((_state & Touch) && !_touching) {
		return;
	}
															     
	{
		LockMonitor lm (lock, __LINE__, __FILE__);
															     
		iterator where;
		TimeComparator cmp;
		ControlEvent cp (when, 0.0);
		bool done = false;
															     
		if (last_rt_insertion_point != events.end()) {
															     
			/* we have a previous insertion point, so we should delete
			   everything between it and the position where we are going
			   to insert this point.
			*/
															     
			iterator after = last_rt_insertion_point;
															     
			if (++after != events.end()) {
				iterator far = after;
															     
				while (far != events.end()) {
					if ((*far)->when > when) {
						break;
					}
					++far;
				}
															     
				if(_new_touch) {
					where = far;
					last_rt_insertion_point = where;
															     
					if((*where)->when == when) {
						(*where)->value = value;
						done = true;
					}
				} else {
					where = events.erase (after, far);
				}
															     
			} else {
															     
				where = after;
															     
			}
															     
			iterator previous = last_rt_insertion_point;
			--previous;
															     
			if (last_rt_insertion_point != events.begin() &&
(*last_rt_insertion_point)->value == value && (*previous)->value == value) {
				(*last_rt_insertion_point)->when = when;
				done = true;
															     
			}
															     
		} else {
															     
			where = lower_bound (events.begin(), events.end(), &cp, cmp);
															     
		}
															     
		if (!done) {
			last_rt_insertion_point = events.insert (where, point_factory (when, value));
		}
															     
		_new_touch = false;
															     
		max_x = max (when, max_x);
		min_x = min (when, min_x);
															     
		mark_dirty ();
	}
	maybe_signal_changed ();
}




More information about the Ardour-Dev mailing list