Only show user-presets in favorite sidebar
[ardour.git] / gtk2_ardour / ardour_ui_dependents.cc
1 /*
2     Copyright (C) 2000 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 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #endif
23
24 /* this file exists solely to break compilation dependencies that
25    would connect changes to the mixer or editor objects.
26 */
27
28 #include <cstdio>
29
30 #include "pbd/error.h"
31
32 #include "ardour/session.h"
33
34 #include "gtkmm2ext/bindings.h"
35
36 #include "actions.h"
37 #include "ardour_ui.h"
38 #include "public_editor.h"
39 #include "meterbridge.h"
40 #include "luainstance.h"
41 #include "luawindow.h"
42 #include "mixer_ui.h"
43 #include "keyboard.h"
44 #include "keyeditor.h"
45 #include "splash.h"
46 #include "rc_option_editor.h"
47 #include "route_params_ui.h"
48 #include "time_info_box.h"
49 #include "opts.h"
50 #include "utils.h"
51
52 #include "pbd/i18n.h"
53
54 using namespace Gtk;
55 using namespace PBD;
56
57 namespace ARDOUR {
58         class Session;
59         class Route;
60 }
61
62 using namespace ARDOUR;
63 using namespace Gtkmm2ext;
64
65 void
66 ARDOUR_UI::we_have_dependents ()
67 {
68         /* other windows and related key-event-handling contexts have already
69          * called Bindings::get_bindings() to setup their list of keybindings.
70          * Do that here for the global bindings.
71          */
72
73         if ((global_bindings = Bindings::get_bindings (X_("Global"))) == 0) {
74                 error << _("Global keybindings are missing") << endmsg;
75         }
76
77         install_actions ();
78         /* The monitor section relies on at least 1 action defined by us. Since that
79          * action now exists, give it a chance to use it.
80          */
81         mixer->monitor_section().use_others_actions ();
82
83         /* Create "static" actions that apply to all ProcessorBoxes
84          */
85         ProcessorBox::register_actions ();
86
87         /* Global, editor, mixer, processor box actions are defined now. Link
88            them with any bindings, so that GTK does not get a chance to define
89            the GTK accel map entries first when we ask the GtkUIManager to
90            create menus/widgets.
91
92            If GTK adds the actions to its accel map before we do, we lose our
93            freedom to use any keys. More precisely, we can use any keys, but
94            ones that GTK considers illegal as accelerators will not show up in
95            menus.
96
97            There are other dynamic actions that can be created by a monitor
98            section, by step entry dialogs. These need to be handled
99            separately. They don't tend to use GTK-illegal bindings and more
100            importantly they don't have menus showing the bindings, so it is
101            less of an issue.
102         */
103
104         Gtkmm2ext::Bindings::associate_all ();
105
106         editor->setup_tooltips ();
107         editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks));
108
109         /* catch up on tabbable state, in the right order to leave the editor
110          * selected by default
111          */
112
113         tabbable_state_change (*rc_option_editor);
114         tabbable_state_change (*mixer);
115         tabbable_state_change (*editor);
116
117         /* all actions are defined */
118
119         ActionManager::load_menus (ARDOUR_COMMAND_LINE::menus_file);
120
121         /* catch up on parameters */
122
123         boost::function<void (std::string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
124         Config->map_parameters (pc);
125
126         UIConfiguration::instance().reset_dpi ();
127 }
128
129 void
130 ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
131 {
132         DisplaySuspender ds;
133         BootMessage (_("Setup Editor"));
134         editor->set_session (s);
135         BootMessage (_("Setup Mixer"));
136         mixer->set_session (s);
137         meterbridge->set_session (s);
138         luawindow->set_session (s);
139
140         /* its safe to do this now */
141
142         BootMessage (_("Reload Session History"));
143         s->restore_history ("");
144 }
145
146 /** The main editor window has been closed */
147 gint
148 ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
149 {
150 #ifdef __APPLE__
151         /* just hide the window, and return - the top menu stays up */
152         editor->hide ();
153         return TRUE;
154 #else
155         /* time to get out of here */
156         finish();
157         return TRUE;
158 #endif
159 }
160
161 GtkNotebook*
162 ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
163                                  GtkWidget* w,
164                                  gint x,
165                                  gint y,
166                                  gpointer)
167 {
168         using namespace std;
169         Gtk::Notebook* nb = 0;
170         Gtk::Window* win = 0;
171         ArdourWidgets::Tabbable* tabbable = 0;
172
173
174         if (w == GTK_WIDGET(editor->contents().gobj())) {
175                 tabbable = editor;
176         } else if (w == GTK_WIDGET(mixer->contents().gobj())) {
177                 tabbable = mixer;
178         } else if (w == GTK_WIDGET(rc_option_editor->contents().gobj())) {
179                 tabbable = rc_option_editor;
180         } else {
181                 return 0;
182         }
183
184         nb = tabbable->tab_root_drop ();
185         win = tabbable->own_window ();
186
187         if (nb) {
188                 win->move (x, y);
189                 win->show_all ();
190                 win->present ();
191                 return nb->gobj();
192         }
193
194         return 0; /* what was that? */
195 }
196
197 bool
198 ARDOUR_UI::idle_ask_about_quit ()
199 {
200         if (_session && _session->dirty()) {
201                 finish ();
202         } else {
203                 /* no session or session not dirty, but still ask anyway */
204
205                 Gtk::MessageDialog msg (string_compose (_("Quit %1?"), PROGRAM_NAME),
206                                         false, /* no markup */
207                                         Gtk::MESSAGE_INFO,
208                                         Gtk::BUTTONS_YES_NO,
209                                         true); /* modal */
210                 msg.set_default_response (Gtk::RESPONSE_YES);
211
212                 if (msg.run() == Gtk::RESPONSE_YES) {
213                         finish ();
214                 }
215         }
216
217         /* not reached but keep the compiler happy */
218
219         return false;
220 }
221
222 bool
223 ARDOUR_UI::main_window_delete_event (GdkEventAny* ev)
224 {
225         /* quit the application as soon as we go idle. If we call this here,
226          * the window manager/desktop can think we're taking too longer to
227          * handle the "delete" event
228          */
229
230         Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_ask_about_quit));
231
232         return true;
233 }
234
235 static GtkNotebook*
236 tab_window_root_drop (GtkNotebook* src,
237                       GtkWidget* w,
238                       gint x,
239                       gint y,
240                       gpointer user_data)
241 {
242         return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data);
243 }
244
245 int
246 ARDOUR_UI::setup_windows ()
247 {
248         /* actions do not need to be defined when we load keybindings. They
249          * will be lazily discovered. But bindings do need to exist when we
250          * create windows/tabs with their own binding sets.
251          */
252
253         keyboard->setup_keybindings ();
254
255         _tabs.set_show_border(false);
256         _tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch));
257         _tabs.signal_page_added().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_added));
258         _tabs.signal_page_removed().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_removed));
259
260         rc_option_editor = new RCOptionEditor;
261         rc_option_editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
262
263         if (create_editor ()) {
264                 error << _("UI: cannot setup editor") << endmsg;
265                 return -1;
266         }
267
268         if (create_mixer ()) {
269                 error << _("UI: cannot setup mixer") << endmsg;
270                 return -1;
271         }
272
273         if (create_meterbridge ()) {
274                 error << _("UI: cannot setup meterbridge") << endmsg;
275                 return -1;
276         }
277
278         if (create_luawindow ()) {
279                 error << _("UI: cannot setup luawindow") << endmsg;
280                 return -1;
281         }
282
283         time_info_box = new TimeInfoBox ("ToolbarTimeInfo", false);
284         /* all other dialogs are created conditionally */
285
286         we_have_dependents ();
287
288         /* order of addition affects order seen in initial window display */
289
290         rc_option_editor->add_to_notebook (_tabs, _("Preferences"));
291         mixer->add_to_notebook (_tabs, _("Mixer"));
292         editor->add_to_notebook (_tabs, _("Editor"));
293
294         top_packer.pack_start (menu_bar_base, false, false);
295
296         main_vpacker.pack_start (top_packer, false, false);
297
298         ArdourWidgets::ArdourDropShadow *spacer = manage (new (ArdourWidgets::ArdourDropShadow));
299         spacer->set_size_request( -1, 4 );
300         spacer->show();
301
302         /* now add the transport sample to the top of main window */
303
304         main_vpacker.pack_start ( *spacer, false, false);
305         main_vpacker.pack_start (transport_frame, false, false);
306         main_vpacker.pack_start (_tabs, true, true);
307
308         LuaInstance::instance()->ActionChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_action_script_btn));
309
310         for (int i = 0; i < MAX_LUA_ACTION_SCRIPTS; ++i) {
311                 std::string const a = string_compose (X_("script-action-%1"), i + 1);
312                 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
313                 assert (act);
314                 action_script_call_btn[i].set_text (string_compose ("%1", i+1));
315                 action_script_call_btn[i].set_related_action (act);
316                 action_script_call_btn[i].signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::bind_lua_action_script), i), false);
317                 if (act->get_sensitive ()) {
318                         action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() & ~Gtkmm2ext::Insensitive));
319                 } else {
320                         action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() | Gtkmm2ext::Insensitive));
321                 }
322                 const int row = i % 2;
323                 const int col = i / 2;
324                 action_script_table.attach (action_script_call_btn[i], col, col + 1, row, row + 1, EXPAND, EXPAND, 1, 0);
325                 action_script_call_btn[i].set_no_show_all ();
326         }
327         action_script_table.show ();
328
329         setup_transport();
330         build_menu_bar ();
331         setup_tooltips ();
332
333         _main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
334
335         /* pack the main vpacker into the main window and show everything
336          */
337
338         _main_window.add (main_vpacker);
339         transport_frame.show_all ();
340
341         const XMLNode* mnode = main_window_settings ();
342
343         if (mnode) {
344                 XMLProperty const * prop;
345                 gint x = -1;
346                 gint y = -1;
347                 gint w = -1;
348                 gint h = -1;
349
350                 if ((prop = mnode->property (X_("x"))) != 0) {
351                         x = atoi (prop->value());
352                 }
353
354                 if ((prop = mnode->property (X_("y"))) != 0) {
355                         y = atoi (prop->value());
356                 }
357
358                 if ((prop = mnode->property (X_("w"))) != 0) {
359                         w = atoi (prop->value());
360                 }
361
362                 if ((prop = mnode->property (X_("h"))) != 0) {
363                         h = atoi (prop->value());
364                 }
365
366                 if (x >= 0 && y >= 0 && w >= 0 && h >= 0) {
367                         _main_window.set_position (Gtk::WIN_POS_NONE);
368                 }
369
370                 if (x >= 0 && y >= 0) {
371                         _main_window.move (x, y);
372                 }
373
374                 if (w > 0 && h > 0) {
375                         _main_window.set_default_size (w, h);
376                 }
377
378                 std::string current_tab;
379
380                 if ((prop = mnode->property (X_("current-tab"))) != 0) {
381                         current_tab = prop->value();
382                 } else {
383                         current_tab = "editor";
384                 }
385                 if (mixer && current_tab == "mixer") {
386                         _tabs.set_current_page (_tabs.page_num (mixer->contents()));
387                 } else if (rc_option_editor && current_tab == "preferences") {
388                         _tabs.set_current_page (_tabs.page_num (rc_option_editor->contents()));
389                 } else if (editor) {
390                         _tabs.set_current_page (_tabs.page_num (editor->contents()));
391                 }
392         }
393
394         setup_toplevel_window (_main_window, "", this);
395         _main_window.show_all ();
396
397         _tabs.set_show_tabs (false);
398
399         /* It would be nice if Gtkmm had wrapped this rather than just
400          * deprecating the old set_window_creation_hook() method, but oh well...
401          */
402         g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this);
403
404         return 0;
405 }
406
407 bool
408 ARDOUR_UI::bind_lua_action_script (GdkEventButton*ev, int i)
409 {
410         if (ev->button != 3) {
411                 return false;
412         }
413         LuaInstance *li = LuaInstance::instance();
414         if (Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::TertiaryModifier)) {
415                 li->remove_lua_action (i);
416         } else {
417                 li->interactive_add (LuaScriptInfo::EditorAction, i);
418         }
419         return true;
420 }
421
422 void
423 ARDOUR_UI::update_action_script_btn (int i, const std::string& n)
424 {
425         if (LuaInstance::instance()->lua_action_has_icon (i)) {
426                 uintptr_t ii = i;
427                 action_script_call_btn[i].set_icon (&LuaInstance::render_action_icon, (void*)ii);
428         } else {
429                 action_script_call_btn[i].set_icon (0, 0);
430         }
431
432         std::string const a = string_compose (X_("script-action-%1"), i + 1);
433         Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
434         assert (act);
435         if (n.empty ()) {
436                 act->set_label (string_compose (_("Unset #%1"), i + 1));
437                 act->set_tooltip (_("No action bound\nRight-click to assign"));
438                 act->set_sensitive (false);
439         } else {
440                 act->set_label (n);
441                 act->set_tooltip (string_compose (_("%1\n\nClick to run\nRight-click to re-assign\nShift+right-click to unassign"), n));
442                 act->set_sensitive (true);
443         }
444         KeyEditor::UpdateBindings ();
445 }