2 Copyright (C) 2000 Paul Davis
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.
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.
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.
21 #include "gtk2ardour-config.h"
24 /* this file exists solely to break compilation dependencies that
25 would connect changes to the mixer or editor objects.
30 #include "pbd/error.h"
32 #include "ardour/session.h"
34 #include "gtkmm2ext/bindings.h"
37 #include "ardour_ui.h"
38 #include "public_editor.h"
39 #include "meterbridge.h"
40 #include "luainstance.h"
41 #include "luawindow.h"
44 #include "keyeditor.h"
46 #include "rc_option_editor.h"
47 #include "route_params_ui.h"
48 #include "time_info_box.h"
62 using namespace ARDOUR;
63 using namespace Gtkmm2ext;
66 ARDOUR_UI::we_have_dependents ()
70 /* other windows and related key-event-handling contexts have already
71 * called Bindings::get_bindings() to setup their list of keybindings.
72 * Do that here for the global bindings.
75 if ((global_bindings = Bindings::get_bindings (X_("Global"))) == 0) {
76 error << _("Global keybindings are missing") << endmsg;
79 ProcessorBox::register_actions ();
81 /* Global, editor, mixer, processor box actions are defined now. Link
82 them with any bindings, so that GTK does not get a chance to define
83 the GTK accel map entries first when we ask the GtkUIManager to
86 If GTK adds the actions to its accel map before we do, we lose our
87 freedom to use any keys. More precisely, we can use any keys, but
88 ones that GTK considers illegal as accelerators will not show up in
91 There are other dynamic actions that can be created by a monitor
92 section, by step entry dialogs. These need to be handled
93 separately. They don't tend to use GTK-illegal bindings and more
94 importantly they don't have menus showing the bindings, so it is
98 Gtkmm2ext::Bindings::associate_all ();
100 editor->setup_tooltips ();
101 editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks));
103 /* catch up on tabbable state, in the right order to leave the editor
104 * selected by default
107 tabbable_state_change (*rc_option_editor);
108 tabbable_state_change (*mixer);
109 tabbable_state_change (*editor);
111 /* all actions are defined */
113 ActionManager::load_menus (ARDOUR_COMMAND_LINE::menus_file);
115 /* catch up on parameters */
117 boost::function<void (std::string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
118 Config->map_parameters (pc);
120 UIConfiguration::instance().reset_dpi ();
124 ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
127 BootMessage (_("Setup Editor"));
128 editor->set_session (s);
129 BootMessage (_("Setup Mixer"));
130 mixer->set_session (s);
131 meterbridge->set_session (s);
132 luawindow->set_session (s);
134 /* its safe to do this now */
136 BootMessage (_("Reload Session History"));
137 s->restore_history ("");
140 /** The main editor window has been closed */
142 ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
145 /* just hide the window, and return - the top menu stays up */
149 /* time to get out of here */
156 ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
163 Gtk::Notebook* nb = 0;
164 Gtk::Window* win = 0;
165 ArdourWidgets::Tabbable* tabbable = 0;
168 if (w == GTK_WIDGET(editor->contents().gobj())) {
170 } else if (w == GTK_WIDGET(mixer->contents().gobj())) {
172 } else if (w == GTK_WIDGET(rc_option_editor->contents().gobj())) {
173 tabbable = rc_option_editor;
178 nb = tabbable->tab_root_drop ();
179 win = tabbable->own_window ();
188 return 0; /* what was that? */
192 ARDOUR_UI::idle_ask_about_quit ()
194 if (_session && _session->dirty()) {
197 /* no session or session not dirty, but still ask anyway */
199 Gtk::MessageDialog msg (string_compose (_("Quit %1?"), PROGRAM_NAME),
200 false, /* no markup */
204 msg.set_default_response (Gtk::RESPONSE_YES);
206 if (msg.run() == Gtk::RESPONSE_YES) {
211 /* not reached but keep the compiler happy */
217 ARDOUR_UI::main_window_delete_event (GdkEventAny* ev)
219 /* quit the application as soon as we go idle. If we call this here,
220 * the window manager/desktop can think we're taking too longer to
221 * handle the "delete" event
224 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_ask_about_quit));
230 tab_window_root_drop (GtkNotebook* src,
236 return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data);
240 ARDOUR_UI::setup_windows ()
242 /* actions do not need to be defined when we load keybindings. They
243 * will be lazily discovered. But bindings do need to exist when we
244 * create windows/tabs with their own binding sets.
247 keyboard->setup_keybindings ();
249 _tabs.set_show_border(false);
250 _tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch));
251 _tabs.signal_page_added().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_added));
252 _tabs.signal_page_removed().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_removed));
254 rc_option_editor = new RCOptionEditor;
255 rc_option_editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
257 if (create_editor ()) {
258 error << _("UI: cannot setup editor") << endmsg;
262 if (create_mixer ()) {
263 error << _("UI: cannot setup mixer") << endmsg;
267 if (create_meterbridge ()) {
268 error << _("UI: cannot setup meterbridge") << endmsg;
272 if (create_luawindow ()) {
273 error << _("UI: cannot setup luawindow") << endmsg;
277 /* order of addition affects order seen in initial window display */
279 rc_option_editor->add_to_notebook (_tabs, _("Preferences"));
280 mixer->add_to_notebook (_tabs, _("Mixer"));
281 editor->add_to_notebook (_tabs, _("Editor"));
283 time_info_box = new TimeInfoBox ("ToolbarTimeInfo", false);
284 /* all other dialogs are created conditionally */
286 we_have_dependents ();
288 top_packer.pack_start (menu_bar_base, false, false);
290 main_vpacker.pack_start (top_packer, false, false);
292 ArdourWidgets::ArdourDropShadow *spacer = manage (new (ArdourWidgets::ArdourDropShadow));
293 spacer->set_size_request( -1, 4 );
296 /* now add the transport sample to the top of main window */
298 main_vpacker.pack_start ( *spacer, false, false);
299 main_vpacker.pack_start (transport_frame, false, false);
300 main_vpacker.pack_start (_tabs, true, true);
302 LuaInstance::instance()->ActionChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_action_script_btn));
304 for (int i = 0; i < MAX_LUA_ACTION_SCRIPTS; ++i) {
305 std::string const a = string_compose (X_("script-action-%1"), i + 1);
306 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
308 action_script_call_btn[i].set_text (string_compose ("%1", i+1));
309 action_script_call_btn[i].set_related_action (act);
310 action_script_call_btn[i].signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::bind_lua_action_script), i), false);
311 if (act->get_sensitive ()) {
312 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() & ~Gtkmm2ext::Insensitive));
314 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() | Gtkmm2ext::Insensitive));
316 const int row = i % 2;
317 const int col = i / 2;
318 action_script_table.attach (action_script_call_btn[i], col, col + 1, row, row + 1, EXPAND, EXPAND, 1, 0);
319 action_script_call_btn[i].set_no_show_all ();
321 action_script_table.show ();
327 _main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
329 /* pack the main vpacker into the main window and show everything
332 _main_window.add (main_vpacker);
333 transport_frame.show_all ();
335 const XMLNode* mnode = main_window_settings ();
338 XMLProperty const * prop;
344 if ((prop = mnode->property (X_("x"))) != 0) {
345 x = atoi (prop->value());
348 if ((prop = mnode->property (X_("y"))) != 0) {
349 y = atoi (prop->value());
352 if ((prop = mnode->property (X_("w"))) != 0) {
353 w = atoi (prop->value());
356 if ((prop = mnode->property (X_("h"))) != 0) {
357 h = atoi (prop->value());
360 if (x >= 0 && y >= 0 && w >= 0 && h >= 0) {
361 _main_window.set_position (Gtk::WIN_POS_NONE);
364 if (x >= 0 && y >= 0) {
365 _main_window.move (x, y);
368 if (w > 0 && h > 0) {
369 _main_window.set_default_size (w, h);
372 std::string current_tab;
374 if ((prop = mnode->property (X_("current-tab"))) != 0) {
375 current_tab = prop->value();
377 current_tab = "editor";
379 if (mixer && current_tab == "mixer") {
380 _tabs.set_current_page (_tabs.page_num (mixer->contents()));
381 } else if (rc_option_editor && current_tab == "preferences") {
382 _tabs.set_current_page (_tabs.page_num (rc_option_editor->contents()));
384 _tabs.set_current_page (_tabs.page_num (editor->contents()));
388 setup_toplevel_window (_main_window, "", this);
389 _main_window.show_all ();
391 _tabs.set_show_tabs (false);
393 /* It would be nice if Gtkmm had wrapped this rather than just
394 * deprecating the old set_window_creation_hook() method, but oh well...
396 g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this);
402 ARDOUR_UI::bind_lua_action_script (GdkEventButton*ev, int i)
404 if (ev->button != 3) {
407 LuaInstance *li = LuaInstance::instance();
408 if (Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::TertiaryModifier)) {
409 li->remove_lua_action (i);
411 li->interactive_add (LuaScriptInfo::EditorAction, i);
417 ARDOUR_UI::update_action_script_btn (int i, const std::string& n)
419 if (LuaInstance::instance()->lua_action_has_icon (i)) {
421 action_script_call_btn[i].set_icon (&LuaInstance::render_action_icon, (void*)ii);
423 action_script_call_btn[i].set_icon (0, 0);
426 std::string const a = string_compose (X_("script-action-%1"), i + 1);
427 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
430 act->set_label (string_compose (_("Unset #%1"), i + 1));
431 act->set_tooltip (_("No action bound\nRight-click to assign"));
432 act->set_sensitive (false);
435 act->set_tooltip (string_compose (_("%1\n\nClick to run\nRight-click to re-assign\nShift+right-click to unassign"), n));
436 act->set_sensitive (true);
438 KeyEditor::UpdateBindings ();