2 * Copyright (C) 2005-2019 Paul Davis <paul@linuxaudiosystems.com>
3 * Copyright (C) 2005 Taybin Rutkin <taybin@taybin.com>
4 * Copyright (C) 2006-2015 Tim Mayberry <mojofunk@gmail.com>
5 * Copyright (C) 2007-2011 David Robillard <d@drobilla.net>
6 * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
7 * Copyright (C) 2013-2018 Robin Gareus <robin@gareus.org>
8 * Copyright (C) 2016-2018 Ben Loftis <ben@harrisonconsoles.com>
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.
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.
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.
26 #include "gtk2ardour-config.h"
29 /* this file exists solely to break compilation dependencies that
30 would connect changes to the mixer or editor objects.
35 #include "pbd/error.h"
38 #include "ardour/session.h"
40 #include "gtkmm2ext/bindings.h"
43 #include "ardour_ui.h"
44 #include "public_editor.h"
45 #include "meterbridge.h"
46 #include "luainstance.h"
47 #include "luawindow.h"
50 #include "keyeditor.h"
52 #include "rc_option_editor.h"
53 #include "route_params_ui.h"
54 #include "time_info_box.h"
55 #include "step_entry.h"
68 using namespace ARDOUR;
69 using namespace Gtkmm2ext;
72 ARDOUR_UI::we_have_dependents ()
74 install_dependent_actions ();
76 /* The monitor section relies on at least 1 action defined by us. Since that
77 * action now exists, give it a chance to use it.
79 mixer->monitor_section().use_others_actions ();
81 /* Create "static" actions that apply to all ProcessorBoxes
83 ProcessorBox::register_actions ();
84 StepEntry::setup_actions_and_bindings ();
86 /* Global, editor, mixer, processor box actions are defined now. Link
87 them with any bindings, so that GTK does not get a chance to define
88 the GTK accel map entries first when we ask the GtkUIManager to
91 If GTK adds the actions to its accel map before we do, we lose our
92 freedom to use any keys. More precisely, we can use any keys, but
93 ones that GTK considers illegal as accelerators will not show up in
96 There are other dynamic actions that can be created by a monitor
97 section, by step entry dialogs. These need to be handled
98 separately. They don't tend to use GTK-illegal bindings and more
99 importantly they don't have menus showing the bindings, so it is
103 Gtkmm2ext::Bindings::associate_all ();
105 editor->setup_tooltips ();
106 editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks));
108 /* catch up on tabbable state, in the right order to leave the editor
109 * selected by default
112 tabbable_state_change (*rc_option_editor);
113 tabbable_state_change (*mixer);
114 tabbable_state_change (*editor);
116 /* all actions are defined */
118 ActionManager::load_menus (ARDOUR_COMMAND_LINE::menus_file);
120 /* catch up on parameters */
122 boost::function<void (std::string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
123 Config->map_parameters (pc);
125 UIConfiguration::instance().reset_dpi ();
129 ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
132 BootMessage (_("Setup Editor"));
133 editor->set_session (s);
134 BootMessage (_("Setup Mixer"));
135 mixer->set_session (s);
136 meterbridge->set_session (s);
137 luawindow->set_session (s);
139 /* its safe to do this now */
141 BootMessage (_("Reload Session History"));
142 s->restore_history ("");
145 /** The main editor window has been closed */
147 ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
150 /* just hide the window, and return - the top menu stays up */
154 /* time to get out of here */
161 ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
168 Gtk::Notebook* nb = 0;
169 Gtk::Window* win = 0;
170 ArdourWidgets::Tabbable* tabbable = 0;
173 if (w == GTK_WIDGET(editor->contents().gobj())) {
175 } else if (w == GTK_WIDGET(mixer->contents().gobj())) {
177 } else if (w == GTK_WIDGET(rc_option_editor->contents().gobj())) {
178 tabbable = rc_option_editor;
183 nb = tabbable->tab_root_drop ();
184 win = tabbable->own_window ();
193 return 0; /* what was that? */
197 ARDOUR_UI::idle_ask_about_quit ()
199 if (_session && _session->dirty()) {
202 /* no session or session not dirty, but still ask anyway */
204 Gtk::MessageDialog msg (string_compose (_("Quit %1?"), PROGRAM_NAME),
205 false, /* no markup */
209 msg.set_default_response (Gtk::RESPONSE_YES);
211 if (msg.run() == Gtk::RESPONSE_YES) {
216 /* not reached but keep the compiler happy */
222 ARDOUR_UI::main_window_delete_event (GdkEventAny* ev)
224 /* quit the application as soon as we go idle. If we call this here,
225 * the window manager/desktop can think we're taking too longer to
226 * handle the "delete" event
229 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_ask_about_quit));
235 tab_window_root_drop (GtkNotebook* src,
241 return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data);
245 ARDOUR_UI::setup_windows ()
247 _tabs.set_show_border(false);
248 _tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch));
249 _tabs.signal_page_added().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_added));
250 _tabs.signal_page_removed().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_removed));
252 rc_option_editor = new RCOptionEditor;
253 rc_option_editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
255 if (create_editor ()) {
256 error << _("UI: cannot setup editor") << endmsg;
260 if (create_mixer ()) {
261 error << _("UI: cannot setup mixer") << endmsg;
265 if (create_meterbridge ()) {
266 error << _("UI: cannot setup meterbridge") << endmsg;
270 if (create_luawindow ()) {
271 error << _("UI: cannot setup luawindow") << endmsg;
275 time_info_box = new TimeInfoBox ("ToolbarTimeInfo", false);
276 /* all other dialogs are created conditionally */
278 we_have_dependents ();
280 /* order of addition affects order seen in initial window display */
282 rc_option_editor->add_to_notebook (_tabs, _("Preferences"));
283 mixer->add_to_notebook (_tabs, _("Mixer"));
284 editor->add_to_notebook (_tabs, _("Editor"));
286 top_packer.pack_start (menu_bar_base, false, false);
288 main_vpacker.pack_start (top_packer, false, false);
290 ArdourWidgets::ArdourDropShadow *spacer = manage (new (ArdourWidgets::ArdourDropShadow));
291 spacer->set_size_request( -1, 4 );
294 /* now add the transport sample to the top of main window */
296 main_vpacker.pack_start ( *spacer, false, false);
297 main_vpacker.pack_start (transport_frame, false, false);
298 main_vpacker.pack_start (_tabs, true, true);
300 LuaInstance::instance()->ActionChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_action_script_btn));
302 for (int i = 0; i < MAX_LUA_ACTION_SCRIPTS; ++i) {
303 std::string const a = string_compose (X_("script-action-%1"), i + 1);
304 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
306 action_script_call_btn[i].set_text (string_compose ("%1", i+1));
307 action_script_call_btn[i].set_related_action (act);
308 action_script_call_btn[i].signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::bind_lua_action_script), i), false);
309 if (act->get_sensitive ()) {
310 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() & ~Gtkmm2ext::Insensitive));
312 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() | Gtkmm2ext::Insensitive));
314 const int row = i % 2;
315 const int col = i / 2;
316 action_script_table.attach (action_script_call_btn[i], col, col + 1, row, row + 1, EXPAND, EXPAND, 1, 0);
317 action_script_call_btn[i].set_no_show_all ();
319 action_script_table.show ();
325 _main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
327 /* pack the main vpacker into the main window and show everything
330 _main_window.add (main_vpacker);
331 transport_frame.show_all ();
333 const XMLNode* mnode = main_window_settings ();
336 XMLProperty const * prop;
342 if ((prop = mnode->property (X_("x"))) != 0) {
343 x = atoi (prop->value());
346 if ((prop = mnode->property (X_("y"))) != 0) {
347 y = atoi (prop->value());
350 if ((prop = mnode->property (X_("w"))) != 0) {
351 w = atoi (prop->value());
354 if ((prop = mnode->property (X_("h"))) != 0) {
355 h = atoi (prop->value());
358 if (x >= 0 && y >= 0 && w >= 0 && h >= 0) {
359 _main_window.set_position (Gtk::WIN_POS_NONE);
362 if (x >= 0 && y >= 0) {
363 _main_window.move (x, y);
366 if (w > 0 && h > 0) {
367 _main_window.set_default_size (w, h);
370 std::string current_tab;
372 if ((prop = mnode->property (X_("current-tab"))) != 0) {
373 current_tab = prop->value();
375 current_tab = "editor";
377 if (mixer && current_tab == "mixer") {
378 _tabs.set_current_page (_tabs.page_num (mixer->contents()));
379 } else if (rc_option_editor && current_tab == "preferences") {
380 _tabs.set_current_page (_tabs.page_num (rc_option_editor->contents()));
382 _tabs.set_current_page (_tabs.page_num (editor->contents()));
386 setup_toplevel_window (_main_window, "", this);
387 _main_window.show_all ();
389 _tabs.set_show_tabs (false);
391 /* It would be nice if Gtkmm had wrapped this rather than just
392 * deprecating the old set_window_creation_hook() method, but oh well...
394 g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this);
400 ARDOUR_UI::bind_lua_action_script (GdkEventButton*ev, int i)
402 if (ev->button != 3) {
405 LuaInstance *li = LuaInstance::instance();
406 if (Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::TertiaryModifier)) {
407 li->remove_lua_action (i);
409 li->interactive_add (LuaScriptInfo::EditorAction, i);
415 ARDOUR_UI::update_action_script_btn (int i, const std::string& n)
417 if (LuaInstance::instance()->lua_action_has_icon (i)) {
419 action_script_call_btn[i].set_icon (&LuaInstance::render_action_icon, (void*)ii);
421 action_script_call_btn[i].set_icon (0, 0);
424 std::string const a = string_compose (X_("script-action-%1"), i + 1);
425 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
428 act->set_label (string_compose (_("Unset #%1"), i + 1));
429 act->set_tooltip (_("No action bound\nRight-click to assign"));
430 act->set_sensitive (false);
433 act->set_tooltip (string_compose (_("%1\n\nClick to run\nRight-click to re-assign\nShift+right-click to unassign"), n));
434 act->set_sensitive (true);
436 KeyEditor::UpdateBindings ();