1 /*
2  * Copyright (C) 2005-2007 Taybin Rutkin <taybin@taybin.com>
3  * Copyright (C) 2005-2018 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2006 Nick Mainsbridge <mainsbridge@gmail.com>
5  * Copyright (C) 2007-2009 David Robillard <d@drobilla.net>
6  * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
7  * Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
8  * Copyright (C) 2014-2018 Ben Loftis <ben@harrisonconsoles.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24 
25 #ifndef __ardour_mixer_ui_h__
26 #define __ardour_mixer_ui_h__
27 
28 #include <list>
29 
30 #include <gtkmm/box.h>
31 #include <gtkmm/scrolledwindow.h>
32 #include <gtkmm/eventbox.h>
33 #include <gtkmm/label.h>
34 #include <gtkmm/comboboxtext.h>
35 #include <gtkmm/button.h>
36 #include <gtkmm/frame.h>
37 #include <gtkmm/menu.h>
38 #include <gtkmm/treeview.h>
39 #include <gtkmm/treestore.h>
40 #include <gtkmm/liststore.h>
41 
42 #include "pbd/stateful.h"
43 #include "pbd/signals.h"
44 
45 #include "ardour/ardour.h"
46 #include "ardour/types.h"
47 #include "ardour/session_handle.h"
48 #include "ardour/plugin.h"
49 #include "ardour/plugin_manager.h"
50 
51 #include <gtkmm2ext/bindings.h>
52 #include "gtkmm2ext/dndtreeview.h"
53 #include "gtkmm2ext/treeutils.h"
54 
55 #include "widgets/pane.h"
56 #include "widgets/tabbable.h"
57 
58 #include "axis_provider.h"
59 #include "enums.h"
60 #include "monitor_section.h"
61 #include "route_processor_selection.h"
62 
63 namespace ARDOUR {
64 	class Route;
65 	class RouteGroup;
66 	class VCA;
67 };
68 
69 class AxisView;
70 class FoldbackStrip;
71 class MixerStrip;
72 class PluginSelector;
73 class MixerGroupTabs;
74 class MonitorSection;
75 class VCAMasterStrip;
76 
77 class PluginTreeStore : public Gtk::TreeStore
78 {
79 public:
create(const Gtk::TreeModelColumnRecord & columns)80 	static Glib::RefPtr<PluginTreeStore> create(const Gtk::TreeModelColumnRecord& columns) {
81 		return Glib::RefPtr<PluginTreeStore> (new PluginTreeStore (columns));
82 	}
83 
84 protected:
PluginTreeStore(const Gtk::TreeModelColumnRecord & columns)85 	PluginTreeStore (const Gtk::TreeModelColumnRecord& columns) : Gtk::TreeStore (columns) {}
row_draggable_vfunc(const Gtk::TreeModel::Path &)86 	virtual bool row_draggable_vfunc (const Gtk::TreeModel::Path&) const { return true; }
87 	virtual bool row_drop_possible_vfunc (const Gtk::TreeModel::Path&, const Gtk::SelectionData&) const;
88 };
89 
90 class Mixer_UI : public ArdourWidgets::Tabbable, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr, public AxisViewProvider
91 {
92 public:
93 	static Mixer_UI* instance();
94 	~Mixer_UI();
95 
96 	Gtk::Window* use_own_window (bool and_fill_it);
97 	void show_window ();
98 
99 	void set_session (ARDOUR::Session *);
100 
101 	PluginSelector* plugin_selector();
102 
103 	void  set_strip_width (Width, bool save = false);
get_strip_width()104 	Width get_strip_width () const { return _strip_width; }
105 
106 	XMLNode& get_state ();
107 	int set_state (const XMLNode&, int /* version */);
108 
109 	void save_plugin_order_file ();
110 
111 	void show_strip (MixerStrip *);
112 	void hide_strip (MixerStrip *);
113 
114 	void maximise_mixer_space();
115 	void restore_mixer_space();
116 
monitor_section()117 	MonitorSection& monitor_section() { return _monitor_section; }
118 
119 	void deselect_all_strip_processors();
120 	void delete_processors();
121 	void select_none ();
122 
123 	void select_next_strip ();
124 	void select_prev_strip ();
125 
126 	void do_vca_assign (boost::shared_ptr<ARDOUR::VCA>);
127 	void do_vca_unassign (boost::shared_ptr<ARDOUR::VCA>);
128 	void show_spill (boost::shared_ptr<ARDOUR::Stripable>);
129 	bool showing_spill_for (boost::shared_ptr<ARDOUR::Stripable>) const;
130 	void fan_out (boost::weak_ptr<ARDOUR::Route>, bool to_busses, bool group);
131 
132 	sigc::signal1<void,boost::shared_ptr<ARDOUR::Stripable> > show_spill_change;
133 
selection()134 	RouteProcessorSelection& selection() { return _selection; }
135 
136 	void show_editor_window () const;
137 
138 	void register_actions ();
139 
140 	void load_bindings ();
141 	Gtkmm2ext::Bindings*  bindings;
142 
143 	void toggle_mixer_list ();
144 	void showhide_mixer_list (bool yn);
145 
146 	void toggle_monitor_section ();
147 	void showhide_monitor_section (bool);
148 
149 	void toggle_foldback_strip ();
150 	void showhide_foldback_strip (bool);
151 
152 	void toggle_vcas ();
153 	void showhide_vcas (bool on);
154 
155 #ifdef MIXBUS
156 	void toggle_mixbuses ();
157 	void showhide_mixbusses (bool on);
158 #endif
159 
160 	bool screenshot (std::string const&);
161 
162 	void toggle_monitor_action (ARDOUR::MonitorChoice monitor_choice, bool group_override = false, bool all = false);
163 
164 protected:
165 	void set_axis_targets_for_operation ();
166 	ARDOUR::AutomationControlSet selected_gaincontrols ();
167 
168 private:
169 	Mixer_UI ();
170 	static Mixer_UI*     _instance;
171 	Gtk::VBox            _content;
172 	Gtk::HBox             global_hpacker;
173 	Gtk::VBox             global_vpacker;
174 	Gtk::ScrolledWindow   scroller;
175 	Gtk::EventBox         scroller_base;
176 	Gtk::HBox             scroller_hpacker;
177 	Gtk::VBox             mixer_scroller_vpacker;
178 	Gtk::VBox             list_vpacker;
179 	Gtk::Label            group_display_button_label;
180 	Gtk::ScrolledWindow   track_display_scroller;
181 	Gtk::ScrolledWindow   group_display_scroller;
182 	Gtk::ScrolledWindow   favorite_plugins_scroller;
183 	Gtk::VBox             group_display_vbox;
184 	Gtk::Frame            track_display_frame;
185 	Gtk::Frame            group_display_frame;
186 	Gtk::Frame            favorite_plugins_frame;
187 	Gtk::VBox             favorite_plugins_vbox;
188 	Gtk::HBox             favorite_plugins_search_hbox;
189 	Gtk::ComboBoxText     favorite_plugins_mode_combo;
190 	Gtk::Entry            plugin_search_entry;
191 	Gtk::Button           plugin_search_clear_button;
192 	ArdourWidgets::VPane  rhs_pane1;
193 	ArdourWidgets::VPane  rhs_pane2;
194 	ArdourWidgets::HPane  inner_pane;
195 	Gtk::VBox             strip_group_box;
196 	Gtk::HBox             strip_packer;
197 	Gtk::ScrolledWindow   vca_scroller;
198 	Gtk::HBox             vca_hpacker;
199 	Gtk::VBox             vca_vpacker;
200 	Gtk::EventBox         vca_label_bar;
201 	Gtk::Label            vca_label;
202 	Gtk::EventBox         vca_scroller_base;
203 	Gtk::HBox             out_packer;
204 	ArdourWidgets::HPane  list_hpane;
205 
206 	MixerGroupTabs* _group_tabs;
207 
208 	bool on_scroll_event (GdkEventScroll*);
209 	bool on_vca_scroll_event (GdkEventScroll*);
210 
211 	std::list<MixerStrip *> strips;
212 
213 	void scroller_drag_data_received (const Glib::RefPtr<Gdk::DragContext>&, int, int, const Gtk::SelectionData&, guint, guint);
214 	bool strip_scroller_button_event (GdkEventButton*);
215 	bool masters_scroller_button_release (GdkEventButton*);
216 	void scroll_left ();
217 	void scroll_right ();
218 	void vca_scroll_left ();
219 	void vca_scroll_right ();
220 	void toggle_midi_input_active (bool flip_others);
221 
222 	void move_vca_into_view (boost::shared_ptr<ARDOUR::Stripable>);
223 	void move_stripable_into_view (boost::shared_ptr<ARDOUR::Stripable>);
224 
225 	void add_stripables (ARDOUR::StripableList&);
226 
227 	void add_routes (ARDOUR::RouteList&);
228 	void remove_strip (MixerStrip *);
229 	void remove_foldback (FoldbackStrip *);
230 	void add_masters (ARDOUR::VCAList&);
231 	void remove_master (VCAMasterStrip*);
232 	void new_masters_created ();
233 
234 	MixerStrip* strip_by_route (boost::shared_ptr<ARDOUR::Route>) const;
235 	MixerStrip* strip_by_stripable (boost::shared_ptr<ARDOUR::Stripable>) const;
236 
237 	AxisView* axis_view_by_stripable (boost::shared_ptr<ARDOUR::Stripable>) const;
238 	AxisView* axis_view_by_control (boost::shared_ptr<ARDOUR::AutomationControl>) const;
239 
240 	gint start_updating ();
241 	gint stop_updating ();
242 
243 	void session_going_away ();
244 
245 	sigc::connection fast_screen_update_connection;
246 	void fast_update_strips ();
247 
248 	void track_name_changed (MixerStrip *);
249 
250 	void redisplay_track_list ();
251 	void spill_redisplay (boost::shared_ptr<ARDOUR::Stripable>);
252 	bool no_track_list_redisplay;
253 	bool track_display_button_press (GdkEventButton*);
254 	void strip_width_changed ();
255 
256 	void track_list_delete (const Gtk::TreeModel::Path&);
257 	void track_list_reorder (const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, int* new_order);
258 
259 	void plugin_row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column);
260 	bool plugin_row_button_press (GdkEventButton*);
261 	void popup_note_context_menu (GdkEventButton*);
262 	void plugin_drop (const Glib::RefPtr<Gdk::DragContext>&, const Gtk::SelectionData& data);
263 	bool plugin_drag_motion (Glib::RefPtr<Gdk::DragContext> const&, int, int, guint);
264 
265 	enum ProcessorPosition {
266 		AddTop,
267 		AddPreFader,
268 		AddPostFader,
269 		AddBottom
270 	};
271 
272 	void add_selected_processor (ProcessorPosition);
273 	void add_favorite_processor (ARDOUR::PluginPresetPtr, ProcessorPosition);
274 	void remove_selected_from_favorites ();
275 	void delete_selected_preset ();
276 	ARDOUR::PluginPresetPtr selected_plugin ();
277 
278 	void initial_track_display ();
279 
280 	void set_all_strips_visibility (bool yn);
281 	void set_all_audio_midi_visibility (int, bool);
282 	void track_visibility_changed (std::string const & path);
283 	void update_track_visibility ();
284 
285 	void hide_all_routes ();
286 	void show_all_routes ();
287 	void show_all_audiobus ();
288 	void hide_all_audiobus ();
289 	void show_all_audiotracks();
290 	void hide_all_audiotracks ();
291 	void show_all_miditracks();
292 	void hide_all_miditracks ();
293 
294 	bool in_group_row_change;
295 
296 	void group_selected (gint row, gint col, GdkEvent *ev);
297 	void group_unselected (gint row, gint col, GdkEvent *ev);
298 	void group_display_active_clicked();
299 	void new_route_group ();
300 	void remove_selected_route_group ();
301 	void activate_all_route_groups ();
302 	void disable_all_route_groups ();
303 	void add_route_group (ARDOUR::RouteGroup *);
304 	void route_groups_changed ();
305 	void route_group_name_edit (const std::string&, const std::string&);
306 	void route_group_row_change (const Gtk::TreeModel::Path& path,const Gtk::TreeModel::iterator& iter);
307 	void route_group_row_deleted (Gtk::TreeModel::Path const &);
308 
309 	Gtk::Menu *track_menu;
310 	void track_column_click (gint);
311 	void build_track_menu ();
312 
313 	MonitorSection   _monitor_section;
314 	PluginSelector *_plugin_selector;
315 	FoldbackStrip * foldback_strip;
316 	bool _show_foldback_strip;
317 
318 	void stripable_property_changed (const PBD::PropertyChange& what_changed, boost::weak_ptr<ARDOUR::Stripable> ws);
319 	void route_group_property_changed (ARDOUR::RouteGroup *, const PBD::PropertyChange &);
320 
321 	/* various treeviews */
322 
323 	struct StripableDisplayModelColumns : public Gtk::TreeModel::ColumnRecord {
StripableDisplayModelColumnsStripableDisplayModelColumns324 		StripableDisplayModelColumns () {
325 			add (text);
326 			add (visible);
327 			add (stripable);
328 			add (strip);
329 		}
330 		Gtk::TreeModelColumn<bool>         visible;
331 		Gtk::TreeModelColumn<std::string>  text;
332 		Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Stripable> > stripable;
333 		Gtk::TreeModelColumn<AxisView*>    strip;
334 	};
335 
336 	struct GroupDisplayModelColumns : public Gtk::TreeModel::ColumnRecord {
GroupDisplayModelColumnsGroupDisplayModelColumns337 		GroupDisplayModelColumns() {
338 			add (visible);
339 			add (text);
340 			add (group);
341 		}
342 		Gtk::TreeModelColumn<bool>            visible;
343 		Gtk::TreeModelColumn<std::string>         text;
344 		Gtk::TreeModelColumn<ARDOUR::RouteGroup*> group;
345 	};
346 
347 	struct PluginsDisplayModelColumns : public Gtk::TreeModel::ColumnRecord {
PluginsDisplayModelColumnsPluginsDisplayModelColumns348 		PluginsDisplayModelColumns() {
349 			add (name);
350 			add (plugin);
351 		}
352 		Gtk::TreeModelColumn<std::string> name;
353 		Gtk::TreeModelColumn<ARDOUR::PluginPresetPtr> plugin;
354 	};
355 
356 	ARDOUR::PluginInfoList plugin_list;
357 
358 	std::list<std::string>      favorite_ui_order;
359 	std::map<std::string, bool> favorite_ui_state;
360 
361 	StripableDisplayModelColumns stripable_columns;
362 	GroupDisplayModelColumns     group_columns;
363 	PluginsDisplayModelColumns   favorite_plugins_columns;
364 
365 	Gtk::TreeView track_display;
366 	Gtk::TreeView group_display;
367 	Gtkmm2ext::DnDTreeView<ARDOUR::PluginPresetPtr> favorite_plugins_display;
368 
369 	Glib::RefPtr<Gtk::ListStore> track_model;
370 	Glib::RefPtr<Gtk::ListStore> group_model;
371 	Glib::RefPtr<PluginTreeStore> favorite_plugins_model;
372 
373 	bool group_display_button_press (GdkEventButton*);
374 	void group_display_selection_changed ();
375 
376 	bool strip_button_release_event (GdkEventButton*, MixerStrip*);
377 	bool vca_button_release_event (GdkEventButton*, VCAMasterStrip*);
378 
379 	Width _strip_width;
380 	double _spill_scroll_position;
381 
382 	void presentation_info_changed (PBD::PropertyChange const &);
383 	void sync_treeview_from_presentation_info (PBD::PropertyChange const &);
384 	void sync_presentation_info_from_treeview ();
385 
386 	bool ignore_track_reorder;
387 	bool ignore_plugin_refill;
388 	bool ignore_plugin_reorder;
389 
390 	void parameter_changed (std::string const &);
391 	void set_route_group_activation (ARDOUR::RouteGroup *, bool);
392 
393 	void setup_track_display ();
394 	void new_track_or_bus ();
395 
396 	static const int32_t default_width = 478;
397 	static const int32_t default_height = 765;
398 
399 	/** true if we are rebuilding the route group list, or clearing
400 	 * it during a session teardown.
401 	 */
402 	bool _in_group_rebuild_or_clear;
403 	bool _route_deletion_in_progress;
404 
405 	void update_title ();
406 	MixerStrip* strip_by_x (int x);
407 
408 	friend class MixerGroupTabs;
409 
410 	void monitor_section_going_away ();
411 	void monitor_section_attached ();
412 	void monitor_section_detached ();
413 
414 	enum PluginListMode {
415 		PLM_Favorite,
416 		PLM_Recent,
417 		PLM_TopHits
418 	};
419 
420 	void refiller (ARDOUR::PluginInfoList& result, const ARDOUR::PluginInfoList& plugs);
421 	void refill_favorite_plugins ();
422 	void maybe_refill_favorite_plugins (PluginListMode);
423 	void store_current_favorite_order();
424 	enum PluginListMode plugin_list_mode () const;
425 	void plugin_list_mode_changed ();
426 	void plugin_search_entry_changed ();
427 	void plugin_search_clear_button_clicked ();
428 	void favorite_plugins_deleted (const Gtk::TreeModel::Path&);
429 	void sync_treeview_from_favorite_order ();
430 	void sync_treeview_favorite_ui_state (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator&);
431 	void save_favorite_ui_state (const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path);
432 
433 	/// true if we are in fullscreen mode
434 	bool _maximised;
435 
436 	bool _strip_selection_change_without_scroll;
437 
438 	mutable boost::weak_ptr<ARDOUR::Stripable> spilled_strip;
439 
440 	void escape ();
441 
442 	RouteProcessorSelection _selection;
443 	AxisViewSelection _axis_targets;
444 
445 	void spill_nothing ();
446 	PBD::ScopedConnection _spill_gone_connection;
447 
448 	void vca_assign (boost::shared_ptr<ARDOUR::VCA>);
449 	void vca_unassign (boost::shared_ptr<ARDOUR::VCA>);
450 
451 	template<class T> void control_action (boost::shared_ptr<T> (ARDOUR::Stripable::*get_control)() const);
452 	void solo_action ();
453 	void mute_action ();
454 	void rec_enable_action ();
455 	void step_gain_up_action ();
456 	void step_gain_down_action ();
457 	void unity_gain_action ();
458 
459 	void copy_processors ();
460 	void cut_processors ();
461 	void paste_processors ();
462 	void select_all_processors ();
463 	void toggle_processors ();
464 	void ab_plugins ();
465 };
466 
467 #endif /* __ardour_mixer_ui_h__ */
468