/*
- Copyright (C) 2006 Paul Davis
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
+ * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
+ * Copyright (C) 2007-2017 Paul Davis <paul@linuxaudiosystems.com>
+ * Copyright (C) 2007 Doug McLain <doug@nostar.net>
+ * Copyright (C) 2008-2009 Hans Baier <hansfbaier@googlemail.com>
+ * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
+ * Copyright (C) 2013-2014 Colin Fletcher <colin.m.fletcher@googlemail.com>
+ * Copyright (C) 2014-2017 Ben Loftis <ben@harrisonconsoles.com>
+ * Copyright (C) 2015-2016 Nick Mainsbridge <mainsbridge@gmail.com>
+ * Copyright (C) 2015-2016 Tim Mayberry <mojofunk@gmail.com>
+ * Copyright (C) 2016 Julien "_FrnchFrgg_" RIVAUD <frnchfrgg@free.fr>
+ *
+ * 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 <cstdlib>
#include <cmath>
#include "pbd/enumwriter.h"
#include "pbd/stateful_diff_command.h"
-#include "evoral/Parameter.hpp"
+#include "evoral/Parameter.h"
#include "ardour/amp.h"
#include "ardour/meter.h"
#include "ardour/event_type_map.h"
#include "ardour/pannable.h"
#include "ardour/panner.h"
+#include "ardour/plugin_insert.h"
#include "ardour/processor.h"
#include "ardour/profile.h"
#include "ardour/route_group.h"
#include "item_counts.h"
#include "keyboard.h"
#include "paste_context.h"
+#include "patch_change_widget.h"
#include "playlist_selector.h"
#include "point_selection.h"
#include "public_editor.h"
, plugins_submenu_item (0)
, route_group_menu (0)
, playlist_action_menu (0)
- , mode_menu (0)
- , color_mode_menu (0)
, gm (sess, true, 75, 14)
, _ignore_set_layer_display (false)
, pan_automation_item(NULL)
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (route_group_button, 2, 3, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
controls_table.attach (gm.get_gain_slider(), 3, 5, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 1, 0);
- }
- else if (!ARDOUR::Profile->get_trx()) {
+ } else {
controls_table.attach (route_group_button, 4, 5, 2, 3, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
controls_table.attach (gm.get_gain_slider(), 0, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 1, 0);
}
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (automation_button, 1, 2, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
- }
- else if (!ARDOUR::Profile->get_trx()) {
+ } else {
controls_table.attach (automation_button, 3, 4, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
}
if (is_track() && track()->mode() == ARDOUR::Normal) {
if (ARDOUR::Profile->get_mixbus()) {
controls_table.attach (playlist_button, 0, 1, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
- }
- else if (!ARDOUR::Profile->get_trx()) {
+ } else {
controls_table.attach (playlist_button, 2, 3, 2, 3, Gtk::SHRINK, Gtk::SHRINK);
}
}
}
delete playlist_action_menu;
- playlist_action_menu = 0;
+ delete automation_action_menu;
delete _view;
_view = 0;
} else {
/* show nothing */
+ delete alignment_menu;
}
-#ifdef XXX_OLD_DESTRUCTIVE_API_XXX
- Menu* mode_menu = manage (new Menu);
- MenuList& mode_items = mode_menu->items ();
- mode_menu->set_name ("ArdourContextMenu");
-
- RadioMenuItem::Group mode_group;
-
- int normal = 0;
- int tape = 0;
- int non_layered = 0;
-
- for (TrackSelection::const_iterator t = s.begin(); t != s.end(); ++t) {
- RouteTimeAxisView* r = dynamic_cast<RouteTimeAxisView*> (*t);
- if (!r || !r->is_track ()) {
- continue;
- }
-
- switch (r->track()->mode()) {
- case Normal:
- ++normal;
- break;
- case Destructive:
- ++tape;
- break;
- case NonLayered:
- ++non_layered;
- break;
- }
- }
-
- mode_items.push_back (RadioMenuElem (mode_group, _("Normal Mode")));
- i = dynamic_cast<RadioMenuItem*> (&mode_items.back ());
- i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Normal, true));
- i->set_active (normal != 0 && tape == 0 && non_layered == 0);
- i->set_inconsistent (normal != 0 && (tape != 0 || non_layered != 0));
-
- mode_items.push_back (RadioMenuElem (mode_group, _("Tape Mode")));
- i = dynamic_cast<RadioMenuItem*> (&mode_items.back ());
- i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Destructive, true));
- i->set_active (normal == 0 && tape != 0 && non_layered == 0);
- i->set_inconsistent (tape != 0 && (normal != 0 || non_layered != 0));
-
- mode_items.push_back (RadioMenuElem (mode_group, _("Non-Layered Mode")));
- i = dynamic_cast<RadioMenuItem*> (&mode_items.back ());
- i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::NonLayered, true));
- i->set_active (normal == 0 && tape == 0 && non_layered != 0);
- i->set_inconsistent (non_layered != 0 && (normal != 0 || tape != 0));
-
- items.push_back (MenuElem (_("Record Mode"), *mode_menu));
-#endif
-
items.push_back (SeparatorElem());
build_playlist_menu ();
items.back().set_sensitive (_editor.get_selection().tracks.size() <= 1);
}
+ if (!is_midi_track () && _route->the_instrument ()) {
+ /* MIDI Bus */
+ items.push_back (MenuElem (_("Patch Selector..."),
+ sigc::mem_fun(*this, &RouteUI::select_midi_patch)));
+ items.push_back (SeparatorElem());
+ }
+
route_group_menu->detach ();
WeakRouteList r;
items.push_back (MenuElem (_("Remove"), sigc::mem_fun(_editor, &PublicEditor::remove_tracks)));
}
-#ifdef XXX_OLD_DESTRUCTIVE_API_XXX
void
-RouteTimeAxisView::set_track_mode (TrackMode mode, bool apply_to_selection)
-{
- if (apply_to_selection) {
- _editor.get_selection().tracks.foreach_route_time_axis (boost::bind (&RouteTimeAxisView::set_track_mode, _1, mode, false));
- } else {
-
- bool needs_bounce = false;
-
- if (!track()->can_use_mode (mode, needs_bounce)) {
-
- if (!needs_bounce) {
- /* cannot be done */
- return;
- } else {
- cerr << "would bounce this one\n";
- return;
- }
- }
-
- track()->set_mode (mode);
- }
-}
-#endif
-
-void
-RouteTimeAxisView::show_timestretch (framepos_t start, framepos_t end, int layers, int layer)
+RouteTimeAxisView::show_timestretch (samplepos_t start, samplepos_t end, int layers, int layer)
{
TimeAxisView::show_timestretch (start, end, layers, layer);
void
RouteTimeAxisView::set_samples_per_pixel (double fpp)
{
- double speed = 1.0;
-
- if (track()) {
- speed = track()->speed();
- }
-
if (_view) {
- _view->set_samples_per_pixel (fpp * speed);
+ _view->set_samples_per_pixel (fpp);
}
- StripableTimeAxisView::set_samples_per_pixel (fpp * speed);
+ StripableTimeAxisView::set_samples_per_pixel (fpp);
}
void
}
prompter.get_result (name);
if (name.length()) {
- if (_session->playlists->by_name (name)) {
+ if (_session->playlists()->by_name (name)) {
MessageDialog msg (_("Given playlist name is not unique."));
msg.run ();
prompter.set_initial_text (Playlist::bump_name (name, *_session));
name = resolve_new_group_playlist_name(name,playlists_before_op);
}
- while (_session->playlists->by_name(name)) {
+ while (_session->playlists()->by_name(name)) {
name = Playlist::bump_name (name, *_session);
}
}
prompter.get_result (name);
if (name.length()) {
- if (_session->playlists->by_name (name)) {
+ if (_session->playlists()->by_name (name)) {
MessageDialog msg (_("Given playlist name is not unique."));
msg.run ();
prompter.set_initial_text (Playlist::bump_name (name, *_session));
if (copy) {
tr->use_copy_playlist ();
} else {
- tr->use_new_playlist ();
+ tr->use_default_new_playlist ();
}
tr->playlist()->set_name (name);
}
* @param results List to add things to.
*/
void
-RouteTimeAxisView::get_selectables (framepos_t start, framepos_t end, double top, double bot, list<Selectable*>& results, bool within)
+RouteTimeAxisView::get_selectables (samplepos_t start, samplepos_t end, double top, double bot, list<Selectable*>& results, bool within)
{
- double speed = 1.0;
-
- if (track() != 0) {
- speed = track()->speed();
- }
-
- framepos_t const start_adjusted = session_frame_to_track_frame(start, speed);
- framepos_t const end_adjusted = session_frame_to_track_frame(end, speed);
-
if ((_view && ((top < 0.0 && bot < 0.0))) || touched (top, bot)) {
- _view->get_selectables (start_adjusted, end_adjusted, top, bot, results, within);
+ _view->get_selectables (start, end, top, bot, results, within);
}
/* pick up visible automation tracks */
- StripableTimeAxisView::get_selectables (start_adjusted, end_adjusted, top, bot, results, within);
+ for (Children::iterator i = children.begin(); i != children.end(); ++i) {
+ if (!(*i)->hidden()) {
+ (*i)->get_selectables (start, end, top, bot, results, within);
+ }
+ }
}
void
}
boost::shared_ptr<Region>
-RouteTimeAxisView::find_next_region (framepos_t pos, RegionPoint point, int32_t dir)
+RouteTimeAxisView::find_next_region (samplepos_t pos, RegionPoint point, int32_t dir)
{
boost::shared_ptr<Playlist> pl = playlist ();
return boost::shared_ptr<Region> ();
}
-framepos_t
-RouteTimeAxisView::find_next_region_boundary (framepos_t pos, int32_t dir)
+samplepos_t
+RouteTimeAxisView::find_next_region_boundary (samplepos_t pos, int32_t dir)
{
boost::shared_ptr<Playlist> pl = playlist ();
playlist = tr->playlist();
TimeSelection time (selection);
- float const speed = tr->speed();
- if (speed != 1.0f) {
- for (TimeSelection::iterator i = time.begin(); i != time.end(); ++i) {
- (*i).start = session_frame_to_track_frame((*i).start, speed);
- (*i).end = session_frame_to_track_frame((*i).end, speed);
- }
- }
playlist->clear_changes ();
playlist->clear_owned_changes ();
playlist = tr->playlist();
TimeSelection time (selection.time);
- float const speed = tr->speed();
- if (speed != 1.0f) {
- for (TimeSelection::iterator i = time.begin(); i != time.end(); ++i) {
- (*i).start = session_frame_to_track_frame((*i).start, speed);
- (*i).end = session_frame_to_track_frame((*i).end, speed);
- }
- }
playlist->clear_changes ();
playlist->clear_owned_changes ();
}
bool
-RouteTimeAxisView::paste (framepos_t pos, const Selection& selection, PasteContext& ctx, const int32_t sub_num)
+RouteTimeAxisView::paste (samplepos_t pos, const Selection& selection, PasteContext& ctx, const int32_t sub_num)
{
if (!is_track()) {
return false;
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("paste to %1\n", pos));
- if (track()->speed() != 1.0f) {
- pos = session_frame_to_track_frame (pos, track()->speed());
- DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("modified paste to %1\n", pos));
- }
-
/* add multi-paste offset if applicable */
- std::pair<framepos_t, framepos_t> extent = (*p)->get_extent();
- const framecnt_t duration = extent.second - extent.first;
+ std::pair<samplepos_t, samplepos_t> extent = (*p)->get_extent();
+ const samplecnt_t duration = extent.second - extent.first;
pos += _editor.get_paste_offset(pos, ctx.count, duration);
pl->clear_changes ();
pl->clear_owned_changes ();
if (Config->get_edit_mode() == Ripple) {
- std::pair<framepos_t, framepos_t> extent = (*p)->get_extent_with_endspace();
- framecnt_t amount = extent.second - extent.first;
+ std::pair<samplepos_t, samplepos_t> extent = (*p)->get_extent_with_endspace();
+ samplecnt_t amount = extent.second - extent.first;
pl->ripple(pos, amount * ctx.times, boost::shared_ptr<Region>());
}
pl->paste (*p, pos, ctx.times, sub_num);
RadioMenuItem::Group playlist_group;
boost::shared_ptr<Track> tr = track ();
- vector<boost::shared_ptr<Playlist> > playlists_tr = _session->playlists->playlists_for_track (tr);
+ vector<boost::shared_ptr<Playlist> > playlists_tr = _session->playlists()->playlists_for_track (tr);
/* sort the playlists */
PlaylistSorter cmp;
return;
}
- track()->use_playlist (pl);
+ track()->use_playlist (track()->data_type(), pl);
RouteGroup* rg = route_group();
continue;
}
- boost::shared_ptr<Playlist> ipl = session()->playlists->by_name(playlist_name);
+ boost::shared_ptr<Playlist> ipl = session()->playlists()->by_name(playlist_name);
if (!ipl) {
// No playlist for this track for this take yet, make it
- track->use_new_playlist();
+ track->use_default_new_playlist();
track->playlist()->set_name(playlist_name);
} else {
- track->use_playlist(ipl);
+ track->use_playlist(track->data_type(), ipl);
}
}
}
boost::shared_ptr<AutomationLine> al;
if ((al = find_processor_automation_curve (processor, param)) != 0) {
+#warning NOT REACHED -- bug?
al->queue_reset ();
} else {
add_processor_automation_curve (processor, param);
items.clear ();
- std::set<Evoral::Parameter> has_visible_automation;
- AutomationTimeAxisView::what_has_visible_automation (processor, has_visible_automation);
-
for (std::set<Evoral::Parameter>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) {
ProcessorAutomationNode* pan;
_subplugin_menu_map[*i] = mitem;
- if (has_visible_automation.find((*i)) != has_visible_automation.end()) {
- mitem->set_active(true);
- }
-
if ((pan = find_processor_automation_node (processor, *i)) == 0) {
/* new item */
}
+ boost::shared_ptr<AutomationTimeAxisView> atav = automation_child (*i);
+ bool visible;
+ if (atav && atav->get_gui_property ("visible", visible)) {
+ mitem->set_active(true);
+ }
+
mitem->signal_toggled().connect (sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::processor_menu_item_toggled), rai, pan));
}
}
}
+void
+RouteTimeAxisView::reread_midnam ()
+{
+ boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_route->the_instrument ());
+ assert (pi);
+ bool rv = pi->plugin ()->read_midnam();
+
+ if (rv && patch_change_dialog ()) {
+ patch_change_dialog ()->refresh ();
+ }
+}
+
+void
+RouteTimeAxisView::drop_instrument_ref ()
+{
+ midnam_connection.drop_connections ();
+}
+
void
RouteTimeAxisView::processors_changed (RouteProcessorChange c)
{
+ if (_route) {
+ boost::shared_ptr<Processor> the_instrument (_route->the_instrument());
+ boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (the_instrument);
+ if (pi && pi->plugin ()->has_midnam ()) {
+ midnam_connection.drop_connections ();
+ the_instrument->DropReferences.connect (midnam_connection, invalidator (*this),
+ boost::bind (&RouteTimeAxisView::drop_instrument_ref, this),
+ gui_context());
+ pi->plugin()->UpdateMidnam.connect (midnam_connection, invalidator (*this),
+ boost::bind (&RouteTimeAxisView::reread_midnam, this),
+ gui_context());
+
+ reread_midnam ();
+ }
+ }
+
if (c.type == RouteProcessorChange::MeterPointChange) {
/* nothing to do if only the meter point has changed */
return;