Merge branch 'master' into mixer-snapshots

This commit is contained in:
Nikolaus Gullotta 2019-04-01 09:04:55 -05:00
commit cd16058019
13 changed files with 173 additions and 93 deletions

View file

@ -2302,12 +2302,15 @@ Editor::set_snap_mode (SnapMode mode)
void
Editor::set_edit_point_preference (EditPoint ep, bool force)
{
if (Profile->get_mixbus()) {
if (ep == EditAtSelectedMarker) {
ep = EditAtPlayhead;
}
}
bool changed = (_edit_point != ep);
_edit_point = ep;
if (Profile->get_mixbus())
if (ep == EditAtSelectedMarker)
ep = EditAtPlayhead;
string str = edit_point_strings[(int)ep];
if (str != edit_point_selector.get_text ()) {
@ -2327,7 +2330,7 @@ Editor::set_edit_point_preference (EditPoint ep, bool force)
action = "edit-at-playhead";
break;
case EditAtSelectedMarker:
action = "edit-at-marker";
action = "edit-at-selected-marker";
break;
case EditAtMouse:
action = "edit-at-mouse";

View file

@ -6216,6 +6216,7 @@ AutomationRangeDrag::AutomationRangeDrag (Editor* editor, AutomationTimeAxisView
: Drag (editor, atv->base_item ())
, _ranges (r)
, _y_origin (atv->y_position())
, _y_height (atv->effective_height()) // or atv->lines()->front()->height() ?!
, _nothing_to_drag (false)
{
DEBUG_TRACE (DEBUG::Drags, "New AutomationRangeDrag\n");
@ -6223,10 +6224,11 @@ AutomationRangeDrag::AutomationRangeDrag (Editor* editor, AutomationTimeAxisView
}
/** Make an AutomationRangeDrag for region gain lines or MIDI controller regions */
AutomationRangeDrag::AutomationRangeDrag (Editor* editor, RegionView* rv, list<AudioRange> const & r)
: Drag (editor, rv->get_canvas_group ())
AutomationRangeDrag::AutomationRangeDrag (Editor* editor, list<RegionView*> const & v, list<AudioRange> const & r, double y_origin, double y_height)
: Drag (editor, v.front()->get_canvas_group ())
, _ranges (r)
, _y_origin (rv->get_time_axis_view().y_position())
, _y_origin (y_origin)
, _y_height (y_height)
, _nothing_to_drag (false)
, _integral (false)
{
@ -6234,17 +6236,16 @@ AutomationRangeDrag::AutomationRangeDrag (Editor* editor, RegionView* rv, list<A
list<boost::shared_ptr<AutomationLine> > lines;
AudioRegionView* audio_view;
AutomationRegionView* automation_view;
if ((audio_view = dynamic_cast<AudioRegionView*>(rv))) {
lines.push_back (audio_view->get_gain_line ());
} else if ((automation_view = dynamic_cast<AutomationRegionView*>(rv))) {
lines.push_back (automation_view->line ());
_integral = true;
} else {
error << _("Automation range drag created for invalid region type") << endmsg;
for (list<RegionView*>::const_iterator i = v.begin(); i != v.end(); ++i) {
if (AudioRegionView* audio_view = dynamic_cast<AudioRegionView*>(*i)) {
lines.push_back (audio_view->get_gain_line ());
} else if (AutomationRegionView* automation_view = dynamic_cast<AutomationRegionView*>(*i)) {
lines.push_back (automation_view->line ());
_integral = true;
} else {
error << _("Automation range drag created for invalid region type") << endmsg;
}
}
setup (lines);
}
@ -6296,9 +6297,9 @@ AutomationRangeDrag::setup (list<boost::shared_ptr<AutomationLine> > const & lin
}
double
AutomationRangeDrag::y_fraction (boost::shared_ptr<AutomationLine> line, double global_y) const
AutomationRangeDrag::y_fraction (double global_y) const
{
return 1.0 - ((global_y - _y_origin) / line->height());
return 1.0 - ((global_y - _y_origin) / _y_height);
}
double
@ -6316,7 +6317,6 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
/* Get line states before we start changing things */
for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
i->state = &i->line->get_state ();
i->original_fraction = y_fraction (i->line, current_pointer_y());
}
if (_ranges.empty()) {
@ -6348,22 +6348,21 @@ AutomationRangeDrag::motion (GdkEvent*, bool first_move)
if (!_ranges.empty()) {
/* add guard points */
for (list<AudioRange>::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i) {
samplecnt_t const half = (i->start + i->end) / 2;
/* find the line that this audio range starts in */
list<Line>::iterator j = _lines.begin();
while (j != _lines.end() && (j->range.first > i->start || j->range.second < i->start)) {
++j;
}
for (list<Line>::iterator j = _lines.begin(); j != _lines.end(); ++j) {
if (j->range.first > i->start || j->range.second < i->start) {
continue;
}
if (j != _lines.end()) {
boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
/* j is the line that this audio range starts in; fade into it;
64 samples length plucked out of thin air.
*/
/* j is the line that this audio range starts in; fade into it;
* 64 samples length plucked out of thin air.
*/
samplepos_t a = i->start + 64;
if (a > half) {
@ -6384,18 +6383,17 @@ AutomationRangeDrag::motion (GdkEvent*, bool first_move)
}
/* same thing for the end */
for (list<Line>::iterator j = _lines.begin(); j != _lines.end(); ++j) {
j = _lines.begin();
while (j != _lines.end() && (j->range.first > i->end || j->range.second < i->end)) {
++j;
}
if (j->range.first > i->end || j->range.second < i->end) {
continue;
}
if (j != _lines.end()) {
boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
/* j is the line that this audio range starts in; fade out of it;
64 samples length plucked out of thin air.
*/
* 64 samples length plucked out of thin air.
*/
samplepos_t b = i->end - 64;
if (b < half) {
@ -6419,9 +6417,8 @@ AutomationRangeDrag::motion (GdkEvent*, bool first_move)
_nothing_to_drag = true;
/* Find all the points that should be dragged and put them in the relevant
points lists in the Line structs.
*/
* points lists in the Line structs.
*/
for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
uint32_t const N = i->line->npoints ();
@ -6447,12 +6444,12 @@ AutomationRangeDrag::motion (GdkEvent*, bool first_move)
}
for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
i->line->start_drag_multiple (i->points, y_fraction (i->line, current_pointer_y()), i->state);
i->line->start_drag_multiple (i->points, y_fraction (current_pointer_y()), i->state);
}
}
for (list<Line>::iterator l = _lines.begin(); l != _lines.end(); ++l) {
float const f = y_fraction (l->line, current_pointer_y());
float const f = y_fraction (current_pointer_y());
/* we are ignoring x position for this drag, so we can just pass in anything */
pair<float, float> result;
uint32_t ignored;

View file

@ -1244,7 +1244,7 @@ class AutomationRangeDrag : public Drag
{
public:
AutomationRangeDrag (Editor *, AutomationTimeAxisView *, std::list<ARDOUR::AudioRange> const &);
AutomationRangeDrag (Editor *, RegionView *, std::list<ARDOUR::AudioRange> const &);
AutomationRangeDrag (Editor *, std::list<RegionView*> const &, std::list<ARDOUR::AudioRange> const &, double y_origin, double y_height);
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
void motion (GdkEvent *, bool);
@ -1257,7 +1257,7 @@ public:
private:
void setup (std::list<boost::shared_ptr<AutomationLine> > const &);
double y_fraction (boost::shared_ptr<AutomationLine>, double global_y_position) const;
double y_fraction (double global_y_position) const;
double value (boost::shared_ptr<ARDOUR::AutomationList> list, double x) const;
std::list<ARDOUR::AudioRange> _ranges;
@ -1268,11 +1268,11 @@ private:
std::list<ControlPoint*> points; ///< points to drag on the line
std::pair<ARDOUR::samplepos_t, ARDOUR::samplepos_t> range; ///< the range of all points on the line, in session samples
XMLNode* state; ///< the XML state node before the drag
double original_fraction; ///< initial y-fraction before the drag
};
std::list<Line> _lines;
double _y_origin;
double _y_height;
bool _nothing_to_drag;
bool _integral;
};

View file

@ -37,6 +37,7 @@
#include "canvas/canvas.h"
#include "ardour/audioplaylist.h"
#include "ardour/audioregion.h"
#include "ardour/operations.h"
#include "ardour/playlist.h"
@ -1116,25 +1117,90 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
break;
case SelectionItem:
{
if (dynamic_cast<AudioRegionView*>(clicked_regionview) ||
dynamic_cast<AutomationRegionView*>(clicked_regionview)) {
_drags->set (new AutomationRangeDrag (this, clicked_regionview, selection->time),
event, _cursors->up_down);
} else {
double const y = event->button.y;
pair<TimeAxisView*, int> tvp = trackview_by_y_position (y, false);
if (tvp.first) {
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (tvp.first);
if (atv) {
/* smart "join" mode: drag automation */
_drags->set (new AutomationRangeDrag (this, atv, selection->time), event, _cursors->up_down);
{
if (selection->time.empty ()) {
/* nothing to do */
return true;
}
pair<TimeAxisView*, int> tvp = trackview_by_y_position (event->button.y, false);
if (!tvp.first) {
/* clicked outside of a track */
return true;
}
/* handle automation lanes first */
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (tvp.first);
if (atv) {
/* smart "join" mode: drag automation */
_drags->set (new AutomationRangeDrag (this, atv, selection->time), event, _cursors->up_down);
return true;
}
if (dynamic_cast<AutomationRegionView*>(clicked_regionview)) {
/* MIDI CC or similar -- TODO handle multiple? */
list<RegionView*> rvl;
rvl.push_back (clicked_regionview);
_drags->set (new AutomationRangeDrag (this, rvl, selection->time,
clicked_regionview->get_time_axis_view().y_position(),
clicked_regionview->get_time_axis_view().current_height()),
event, _cursors->up_down);
return true;
}
/* shift+drag: only apply to clicked_regionview (if any) */
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::TertiaryModifier)) {
if (dynamic_cast<AudioRegionView*>(clicked_regionview) == 0) {
return true;
}
list<RegionView*> rvl;
rvl.push_back (clicked_regionview);
// TODO: handle layer_display() == Stacked
_drags->set (new AutomationRangeDrag (this, rvl, selection->time,
clicked_regionview->get_time_axis_view().y_position(),
clicked_regionview->get_time_axis_view().current_height()),
event, _cursors->up_down);
return true;
}
/* collect all audio regions-views in the given range selection */
list<RegionView*> rvl;
TrackViewList ts = selection->tracks.filter_to_unique_playlists ();
for (TrackViewList::iterator i = ts.begin(); i != ts.end(); ++i) {
RouteTimeAxisView* tatv;
boost::shared_ptr<Playlist> playlist;
if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) == 0) {
continue;
}
if ((playlist = (*i)->playlist()) == 0) {
continue;
}
if (boost::dynamic_pointer_cast<AudioPlaylist> (playlist) == 0) {
continue;
}
for (list<AudioRange>::const_iterator j = selection->time.begin(); j != selection->time.end(); ++j) {
boost::shared_ptr<RegionList> rl = playlist->regions_touched (j->start, j->end);
for (RegionList::iterator ir = rl->begin(); ir != rl->end(); ++ir) {
RegionView* rv;
if ((rv = tatv->view()->find_view (*ir)) != 0) {
rvl.push_back (rv);
}
}
}
}
/* region-gain drag */
if (!rvl.empty ()) {
double y_pos = tvp.first->y_position();
double height = tvp.first->current_height();
StreamView* cv = tvp.first->view ();
if (cv->layer_display() == Stacked && cv->layers() > 1) {
height /= cv->layers();
double yy = event->button.y - _trackview_group->canvas_origin().y;
y_pos += floor ((yy - y_pos) / height) * height;
}
_drags->set (new AutomationRangeDrag (this, rvl, selection->time, y_pos, height),
event, _cursors->up_down);
}
return true;
break;
}
return true;
break;
}
case AutomationLineItem:
_drags->set (new LineDrag (this, item), event);
@ -2235,7 +2301,6 @@ Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event)
*/
if (Keyboard::modifier_state_contains (event->state, Keyboard::PrimaryModifier)) {
TimeAxisView* tv = &rv.get_time_axis_view();
samplepos_t where = get_preferred_edit_position();

View file

@ -69,10 +69,9 @@ PluginSelector::PluginSelector (PluginManager& mgr)
_plugin_menu = 0;
in_row_change = false;
//anytime the list changes ( Status, Tags, or scanned plugins ) we need to rebuild redirect-box plugin selector menu
manager.PluginListChanged.connect (plugin_list_changed_connection, invalidator (*this), boost::bind (&PluginSelector::build_plugin_menu, this), gui_context());
manager.PluginStatusChanged.connect (plugin_list_changed_connection, invalidator (*this), boost::bind (&PluginSelector::build_plugin_menu, this), gui_context());
//these are used to update the info of specific entries, while they are being edited
manager.PluginStatusChanged.connect (plugin_list_changed_connection, invalidator (*this), boost::bind (&PluginSelector::plugin_status_changed, this, _1, _2, _3), gui_context());
manager.PluginTagChanged.connect(plugin_list_changed_connection, invalidator (*this), boost::bind (&PluginSelector::tags_changed, this, _1, _2, _3), gui_context());
@ -788,10 +787,6 @@ PluginSelector::run ()
manager.save_statuses();
}
if ( _need_tag_save || _need_status_save || _need_menu_rebuild ) {
manager.PluginListChanged(); //emit signal
}
return (int) r;
}
@ -810,7 +805,6 @@ PluginSelector::tag_reset_button_clicked ()
manager.reset_tags (pi);
display_selection_changed ();
_need_tag_save = true;
_need_menu_rebuild = true;
}
}
@ -833,7 +827,6 @@ PluginSelector::tag_entry_changed ()
manager.set_tags (pi->type, pi->unique_id, tag_entry->get_text(), pi->name, PluginManager::FromGui);
_need_tag_save = true;
_need_menu_rebuild = true;
}
}
@ -888,7 +881,6 @@ PluginSelector::on_show ()
_need_tag_save = false;
_need_status_save = false;
_need_menu_rebuild = false;
}
struct PluginMenuCompareByCreator {
@ -1172,7 +1164,6 @@ PluginSelector::favorite_changed (const std::string& path)
manager.set_status (pi->type, pi->unique_id, status);
_need_status_save = true;
_need_menu_rebuild = true;
}
in_row_change = false;
}
@ -1205,7 +1196,6 @@ PluginSelector::hidden_changed (const std::string& path)
manager.set_status (pi->type, pi->unique_id, status);
_need_status_save = true;
_need_menu_rebuild = true;
}
in_row_change = false;
}

View file

@ -186,7 +186,6 @@ private:
bool _need_tag_save;
bool _need_status_save;
bool _need_menu_rebuild;
bool _inhibit_refill;
};

View file

@ -1985,6 +1985,9 @@ ProcessorBox::object_drop (DnDVBox<ProcessorEntry>* source, ProcessorEntry* posi
if (boost::dynamic_pointer_cast<UnknownProcessor> ((*i)->processor())) {
continue;
}
if (boost::dynamic_pointer_cast<PortInsert> ((*i)->processor())) {
continue;
}
procs.push_back ((*i)->processor ());
}
}

View file

@ -1329,10 +1329,10 @@ class ControlSurfacesOptions : public OptionEditorMiniPage
{
_store = ListStore::create (_model);
_view.set_model (_store);
_view.append_column (_("Control Surface Protocol"), _model.name);
_view.get_column(0)->set_resizable (true);
_view.get_column(0)->set_expand (true);
_view.append_column_editable (_("Enable"), _model.enabled);
_view.append_column (_("Control Surface Protocol"), _model.name);
_view.get_column(1)->set_resizable (true);
_view.get_column(1)->set_expand (true);
Gtk::HBox* edit_box = manage (new Gtk::HBox);
edit_box->set_spacing(3);

View file

@ -25,8 +25,6 @@
#include "pbd/i18n.h"
using namespace std;
using namespace Gtk;
using namespace ARDOUR;
TransformDialog::Model::Model()
@ -99,7 +97,7 @@ TransformDialog::TransformDialog()
Gtk::HBox* add_hbox = Gtk::manage(new Gtk::HBox);
_add_button.add(
*manage(new Gtk::Image(Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON)));
*Gtk::manage(new Gtk::Image(Gtk::Stock::ADD, Gtk::ICON_SIZE_BUTTON)));
add_hbox->pack_start(_add_button, false, false);
_add_button.signal_clicked().connect(
sigc::mem_fun(*this, &TransformDialog::add_clicked));
@ -109,7 +107,7 @@ TransformDialog::TransformDialog()
get_vbox()->pack_start(_operations_box, false, false);
get_vbox()->pack_start(*add_hbox, false, false);
add_button(Stock::CANCEL, Gtk::RESPONSE_CANCEL);
add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
add_button(_("Transform"), Gtk::RESPONSE_OK);
show_all();
@ -229,15 +227,17 @@ TransformDialog::ValueChooser::source_changed()
}
double
TransformDialog::ValueChooser::get_value () const
TransformDialog::ValueChooser::get_value() const
{
return value_spinner.get_value() + ((target_property == MidiModel::NoteDiffCommand::Channel) ? -1. : 0.);
const bool is_channel = target_property == MidiModel::NoteDiffCommand::Channel;
return value_spinner.get_value() + (is_channel ? -1.0 : 0.0);
}
double
TransformDialog::ValueChooser::get_max () const
TransformDialog::ValueChooser::get_max() const
{
return max_spinner.get_value() + ((target_property == MidiModel::NoteDiffCommand::Channel) ? -1. : 0.);
const bool is_channel = target_property == MidiModel::NoteDiffCommand::Channel;
return max_spinner.get_value() + (is_channel ? -1.0 : 0.0);
}
void
@ -311,7 +311,7 @@ TransformDialog::OperationChooser::OperationChooser(const Model& model)
pack_start(remove_button, false, false);
remove_button.add(
*manage(new Gtk::Image(Gtk::Stock::REMOVE, Gtk::ICON_SIZE_BUTTON)));
*Gtk::manage(new Gtk::Image(Gtk::Stock::REMOVE, Gtk::ICON_SIZE_BUTTON)));
remove_button.signal_clicked().connect(
sigc::mem_fun(*this, &TransformDialog::OperationChooser::remove_clicked));

View file

@ -106,7 +106,7 @@ public:
};
std::vector<std::string> get_all_tags (enum TagFilter) const;
/** plugins were added to or removed from one of the PluginInfoLists, OR the user has made changes to the status/tags */
/** plugins were added to or removed from one of the PluginInfoLists */
PBD::Signal0<void> PluginListChanged;
/** A single plugin's Hidden/Favorite status changed */

View file

@ -576,6 +576,21 @@ IO::set_state (const XMLNode& node, int version)
if (create_ports (node, version)) {
return -1;
}
if (_sendish && _direction == Output) {
/* ignore <Port name="..."> from XML for sends, but use the names
* ::ensure_ports_locked() creates port using ::build_legal_port_name()
* This is needed to properly restore connections when creating
* external sends from templates because the IO name changes.
*/
PortSet::iterator i = _ports.begin();
XMLNodeConstIterator x = node.children().begin();
for (; i != _ports.end(), x != node.children().end(); ++i, ++x) {
if ((*x)->name() == "Port") {
(*x)->remove_property (X_("name"));
(*x)->set_property (X_("name"), i->name());
}
}
}
// after create_ports, updates names
if (node.get_property ("pretty-name", name)) {

View file

@ -1536,7 +1536,7 @@ PluginManager::save_tags ()
XMLNode* root = new XMLNode (X_("PluginTags"));
for (PluginTagList::iterator i = ptags.begin(); i != ptags.end(); ++i) {
if ( (*i).tagtype == FromFactoryFile || (*i).tagtype == FromUserFile ) {
if ((*i).tagtype == FromFactoryFile || (*i).tagtype == FromUserFile) {
/* user file should contain only plugins that are (a) newly user-tagged or (b) previously unknown */
continue;
}
@ -1545,7 +1545,7 @@ PluginManager::save_tags ()
node->set_property (X_("id"), (*i).unique_id);
node->set_property (X_("tags"), (*i).tags);
node->set_property (X_("name"), (*i).name);
if ( (*i).tagtype >= FromUserFile ) {
if ((*i).tagtype >= FromUserFile) {
node->set_property (X_("user-set"), "1");
}
root->add_child_nocopy (*node);
@ -1593,25 +1593,25 @@ PluginManager::load_tags ()
user_set = false;
}
strip_whitespace_edges (tags);
set_tags (type, id, tags, name, user_set ? FromUserFile : FromFactoryFile );
set_tags (type, id, tags, name, user_set ? FromUserFile : FromFactoryFile);
}
}
}
void
PluginManager::set_tags (PluginType t, string id, string tag, std::string name, TagType ttype )
PluginManager::set_tags (PluginType t, string id, string tag, std::string name, TagType ttype)
{
string sanitized = sanitize_tag (tag);
PluginTag ps (to_generic_vst (t), id, sanitized, name, ttype );
PluginTag ps (to_generic_vst (t), id, sanitized, name, ttype);
PluginTagList::const_iterator i = find (ptags.begin(), ptags.end(), ps);
if (i == ptags.end()) {
ptags.insert (ps);
} else if ( (uint32_t) ttype >= (uint32_t) (*i).tagtype ) { // only overwrite if we are more important than the existing. Gui > UserFile > FactoryFile > Plugin
} else if ((uint32_t) ttype >= (uint32_t) (*i).tagtype) { // only overwrite if we are more important than the existing. Gui > UserFile > FactoryFile > Plugin
ptags.erase (ps);
ptags.insert (ps);
}
if ( ttype == FromGui ) {
if (ttype == FromGui) {
PluginTagChanged (t, id, sanitized); /* EMIT SIGNAL */
}
}

View file

@ -3439,6 +3439,14 @@ Session::new_route_from_template (uint32_t how_many, PresentationInfo::order_t i
(*i)->remove_property (X_("name"));
(*i)->set_property ("bitslot", bitslot);
(*i)->set_property ("name", name);
XMLNodeList io_kids = (*i)->children ();
for (XMLNodeList::iterator j = io_kids.begin(); j != io_kids.end(); ++j) {
if ((*j)->name() != X_("IO")) {
continue;
}
(*j)->remove_property (X_("name"));
(*j)->set_property ("name", name);
}
}
else if (type && type->value() == X_("intreturn")) {
(*i)->remove_property (X_("bitslot"));