Paul Davis
54597bd803
This also requires a change in the type of reference held by a MidiAutomationListBinder. Both the MidiSource and MidiModel have a reference to each other, and it is important that we avoid circular references to avoid problems with object destruction. We had been accomplishing this by having the Model hold a weak_ptr<MidiSource>. However, the lifetime of a MidiSource and its MidiModel are coincident and there's really no need to use a smart ptr at all. A normal reference is just fine. However, due to constructors that accept a serialized state, we cannot use an actual reference (we cannot set the constructor in the initializer list), so we use a bare ptr instead. This forces a similar change in MidiAutomationListBinder, which also maintains a reference to the Source. However, the only purpose of this object is to ensure that if the Source is destroyed, relevant commands will be removed from the undo/redo history, and so all that matters here is that the binder connects to the Destroyed signal of the source, and arranges for its own destruction when received. Note that the previous construction of the binder, actually holding a shared_ptr<MidiSource> would appear have prevented the Destroyed signal from ever being emitted (from ~Destructible), and so this may also be a bug fix that allows MidiSources to actually be deleted (the memory object, not the file).
100 lines
3.2 KiB
C++
100 lines
3.2 KiB
C++
/*
|
|
* Copyright (C) 2010-2012 Carl Hetherington <carl@carlh.net>
|
|
* Copyright (C) 2010-2014 David Robillard <d@drobilla.net>
|
|
* Copyright (C) 2010-2017 Paul Davis <paul@linuxaudiosystems.com>
|
|
* Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "ardour/midi_automation_list_binder.h"
|
|
#include "ardour/midi_region.h"
|
|
|
|
#include "midi++/midnam_patch.h"
|
|
|
|
#include "midi_automation_line.h"
|
|
#include "midi_time_axis.h"
|
|
|
|
#include "pbd/i18n.h"
|
|
|
|
using namespace std;
|
|
|
|
MidiAutomationLine::MidiAutomationLine (
|
|
const std::string& name,
|
|
TimeAxisView& tav,
|
|
ArdourCanvas::Item& parent,
|
|
boost::shared_ptr<ARDOUR::AutomationList> list,
|
|
boost::shared_ptr<ARDOUR::MidiRegion> region,
|
|
Evoral::Parameter parameter)
|
|
: AutomationLine (name, tav, parent, list, parameter)
|
|
, _region (region)
|
|
, _parameter (parameter)
|
|
{
|
|
|
|
}
|
|
|
|
MementoCommandBinder<ARDOUR::AutomationList>*
|
|
MidiAutomationLine::memento_command_binder ()
|
|
{
|
|
/* some weirdness here since _region->midi_source() returns a
|
|
* shared_ptr<> but the binder accepts a reference.
|
|
*/
|
|
|
|
return new ARDOUR::MidiAutomationListBinder (*(_region->midi_source().get()), _parameter);
|
|
}
|
|
|
|
Temporal::timepos_t
|
|
MidiAutomationLine::get_origin() const
|
|
{
|
|
/* Events in the automation list are relative to the start of the
|
|
source, not the start of the region, so we need to use the
|
|
position-of-the-start-of-the-source, rather than just the
|
|
position-of-the-region.
|
|
*/
|
|
return _region->source_position();
|
|
}
|
|
|
|
string
|
|
MidiAutomationLine::get_verbose_cursor_string (double fraction) const
|
|
{
|
|
using namespace MIDI::Name;
|
|
|
|
if (_parameter.type() != ARDOUR::MidiCCAutomation) {
|
|
return AutomationLine::get_verbose_cursor_string(fraction);
|
|
}
|
|
|
|
MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(trackview.get_parent());
|
|
if (!mtv) {
|
|
return AutomationLine::get_verbose_cursor_string(fraction);
|
|
}
|
|
|
|
const uint8_t channel = mtv->get_preferred_midi_channel();
|
|
boost::shared_ptr<const ValueNameList> value_names = mtv->route()->instrument_info().value_name_list_by_control (channel, _parameter.id());
|
|
|
|
if (!value_names) {
|
|
return AutomationLine::get_verbose_cursor_string(fraction);
|
|
}
|
|
|
|
const uint16_t cc_value = floor(std::max(std::min(fraction * 127.0, 127.0), 0.0));
|
|
|
|
boost::shared_ptr<const Value> value = value_names->max_value_below(cc_value);
|
|
if (!value) {
|
|
return AutomationLine::get_verbose_cursor_string(fraction);
|
|
}
|
|
|
|
return value->name();
|
|
}
|
|
|