Prevent spinlock copy construction
[ardour.git] / gtk2_ardour / port_matrix.h
1 /*
2     Copyright (C) 2002-2009 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef __gtk_ardour_port_matrix_h__
21 #define __gtk_ardour_port_matrix_h__
22
23 #include <list>
24 #include <gtkmm/box.h>
25 #include <gtkmm/scrollbar.h>
26 #include <gtkmm/table.h>
27 #include <gtkmm/label.h>
28 #include <gtkmm/checkbutton.h>
29 #include <gtkmm/notebook.h>
30 #include <boost/shared_ptr.hpp>
31
32 #include "ardour/bundle.h"
33 #include "ardour/types.h"
34 #include "ardour/session_handle.h"
35
36 #include "port_group.h"
37 #include "port_matrix_types.h"
38
39 /** The `port matrix' UI.  This is a widget which lets the user alter
40  *  associations between one set of ports and another.  e.g. to connect
41  *  things together.
42  *
43  *  It is made up of a body, PortMatrixBody, which is rendered using cairo,
44  *  and some scrollbars and other stuff.  All of this is arranged inside the
45  *  Table that we inherit from.
46  */
47
48 namespace ARDOUR {
49         class Bundle;
50 }
51
52 namespace Gtk {
53         namespace Menu_Helpers {
54                 class MenuList;
55         }
56 }
57
58 class PortMatrixBody;
59
60 class PortMatrix : public Gtk::Table, public ARDOUR::SessionHandlePtr
61 {
62 public:
63         PortMatrix (Gtk::Window*, ARDOUR::Session *, ARDOUR::DataType);
64         ~PortMatrix ();
65
66         void set_type (ARDOUR::DataType);
67
68         ARDOUR::DataType type () const {
69                 return _type;
70         }
71
72         void disassociate_all ();
73         void setup_scrollbars ();
74         void popup_menu (ARDOUR::BundleChannel, ARDOUR::BundleChannel, uint32_t);
75
76         int min_height_divisor () const {
77                 return _min_height_divisor;
78         }
79         void set_min_height_divisor (int f) {
80                 _min_height_divisor = f;
81         }
82
83         enum Arrangement {
84                 TOP_TO_RIGHT,  ///< column labels on top, row labels to the right
85                 LEFT_TO_BOTTOM ///< row labels to the left, column labels on the bottom
86         };
87
88
89         /** @return Arrangement in use */
90         Arrangement arrangement () const {
91                 return _arrangement;
92         }
93
94         bool show_only_bundles () const {
95                 return _show_only_bundles;
96         }
97
98         PortGroupList const * columns () const;
99         boost::shared_ptr<const PortGroup> visible_columns () const;
100
101         /** @return index into the _ports array for the list which is displayed as columns */
102         int column_index () const {
103                 return _column_index;
104         }
105
106         PortGroupList const * rows () const;
107         boost::shared_ptr<const PortGroup> visible_rows () const;
108
109         /** @return index into the _ports array for the list which is displayed as rows */
110         int row_index () const {
111                 return _row_index;
112         }
113
114         PortGroupList const * ports (int d) const {
115                 return &_ports[d];
116         }
117
118         boost::shared_ptr<const PortGroup> visible_ports (int d) const;
119
120         void init ();
121         void setup ();
122         virtual void setup_ports (int) = 0;
123         void setup_all_ports ();
124
125         std::pair<uint32_t, uint32_t> max_size () const;
126
127         bool should_show (ARDOUR::DataType) const;
128         uint32_t count_of_our_type (ARDOUR::ChanCount) const;
129         uint32_t count_of_our_type_min_1 (ARDOUR::ChanCount) const;
130
131         PortMatrixNode::State get_association (PortMatrixNode) const;
132
133         void flip ();
134         bool key_press (GdkEventKey *);
135
136         /** @param c Channels; where c[0] is from _ports[0] and c[1] is from _ports[1].
137          *  @param s New state.
138          */
139         virtual void set_state (ARDOUR::BundleChannel c[2], bool s) = 0;
140
141         /** @param c Channels; where c[0] is from _ports[0] and c[1] is from _ports[1].
142          *  @return state
143          */
144         virtual PortMatrixNode::State get_state (ARDOUR::BundleChannel c[2]) const = 0;
145         virtual bool list_is_global (int) const = 0;
146
147         virtual bool can_add_channels (boost::shared_ptr<ARDOUR::Bundle>) const;
148         virtual void add_channel (boost::shared_ptr<ARDOUR::Bundle>, ARDOUR::DataType);
149         virtual bool can_remove_channels (boost::shared_ptr<ARDOUR::Bundle>) const;
150         virtual void remove_channel (ARDOUR::BundleChannel);
151         virtual void remove_all_channels (boost::weak_ptr<ARDOUR::Bundle>);
152         virtual bool can_rename_channels (boost::shared_ptr<ARDOUR::Bundle>) const {
153                 return false;
154         }
155         virtual void rename_channel (ARDOUR::BundleChannel) {}
156         virtual std::string disassociation_verb () const = 0;
157         virtual std::string channel_noun () const;
158
159         enum Result {
160                 Cancelled,
161                 Accepted
162         };
163
164         sigc::signal<void, Result> Finished;
165
166         static bool bundle_with_channels (boost::shared_ptr<ARDOUR::Bundle>);
167
168 protected:
169
170         /** We have two port group lists.  One will be presented on the rows of the matrix,
171             the other on the columns.  The PortMatrix chooses the arrangement based on which has
172             more ports in it.  Subclasses must fill these two lists with the port groups that they
173             wish to present.  The PortMatrix will arrange its layout such that signal flow is vaguely
174             from left to right as you go from list 0 to list 1.  Hence subclasses which deal with
175             inputs and outputs should put outputs in list 0 and inputs in list 1. */
176         PortGroupList _ports[2];
177
178 private:
179
180         void hscroll_changed ();
181         void vscroll_changed ();
182         void routes_changed ();
183         void reconnect_to_routes ();
184         void select_arrangement ();
185         bool can_add_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, ARDOUR::DataType) const;
186         void add_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, ARDOUR::DataType);
187         void remove_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
188         void rename_channel_proxy (boost::weak_ptr<ARDOUR::Bundle>, uint32_t);
189         void disassociate_all_on_channel (boost::weak_ptr<ARDOUR::Bundle>, uint32_t, int);
190         void disassociate_all_on_bundle (boost::weak_ptr<ARDOUR::Bundle>, int);
191         void setup_global_ports ();
192         void setup_global_ports_proxy ();
193         void toggle_show_only_bundles ();
194         bool on_scroll_event (GdkEventScroll *);
195         boost::shared_ptr<ARDOUR::IO> io_from_bundle (boost::shared_ptr<ARDOUR::Bundle>) const;
196         void setup_notebooks ();
197         void remove_notebook_pages (Gtk::Notebook &);
198         void notebook_page_selected (GtkNotebookPage *, guint);
199         void route_processors_changed (ARDOUR::RouteProcessorChange);
200         void body_dimensions_changed ();
201         void session_going_away ();
202         void add_remove_option (Gtk::Menu_Helpers::MenuList &, boost::weak_ptr<ARDOUR::Bundle>, int);
203         void add_disassociate_option (Gtk::Menu_Helpers::MenuList &, boost::weak_ptr<ARDOUR::Bundle>, int, int);
204         void port_connected_or_disconnected ();
205         void update_tab_highlighting ();
206         std::pair<int, int> check_flip () const;
207         bool can_flip () const;
208
209         Gtk::Window* _parent;
210
211         /** port type that we are working with, or NIL if we are working with all of them */
212         ARDOUR::DataType _type;
213         PBD::ScopedConnectionList _route_connections;
214         PBD::ScopedConnectionList _changed_connections;
215         PBD::ScopedConnectionList _bundle_changed_connections;
216
217         PortMatrixBody* _body;
218         Gtk::HScrollbar _hscroll;
219         Gtk::VScrollbar _vscroll;
220         Gtk::Notebook _vnotebook;
221         Gtk::Notebook _hnotebook;
222         Gtk::Label _vlabel;
223         Gtk::Label _hlabel;
224         Gtk::VBox _vbox;
225         Gtk::HBox _hbox;
226         Gtk::Label _hspacer;
227         Gtk::Label _vspacer;
228         Gtk::Menu* _menu;
229         Arrangement _arrangement;
230         int _row_index;
231         int _column_index;
232         int _min_height_divisor;
233         bool _show_only_bundles;
234         bool _inhibit_toggle_show_only_bundles;
235         bool _ignore_notebook_page_selected;
236 };
237
238 #endif