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 ()
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.
73 if ((global_bindings = Bindings::get_bindings (X_("Global"))) == 0) {
74 error << _("Global keybindings are missing") << endmsg;
78 ProcessorBox::register_actions ();
80 /* Global, editor, mixer, processor box actions are defined now. Link
81 them with any bindings, so that GTK does not get a chance to define
82 the GTK accel map entries first when we ask the GtkUIManager to
85 If GTK adds the actions to its accel map before we do, we lose our
86 freedom to use any keys. More precisely, we can use any keys, but
87 ones that GTK considers illegal as accelerators will not show up in
90 There are other dynamic actions that can be created by a monitor
91 section, by step entry dialogs. These need to be handled
92 separately. They don't tend to use GTK-illegal bindings and more
93 importantly they don't have menus showing the bindings, so it is
97 Gtkmm2ext::Bindings::associate_all ();
99 editor->setup_tooltips ();
100 editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks));
102 /* catch up on tabbable state, in the right order to leave the editor
103 * selected by default
106 tabbable_state_change (*rc_option_editor);
107 tabbable_state_change (*mixer);
108 tabbable_state_change (*editor);
110 /* all actions are defined */
112 ActionManager::load_menus (ARDOUR_COMMAND_LINE::menus_file);
114 /* catch up on parameters */
116 boost::function<void (std::string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
117 Config->map_parameters (pc);
119 UIConfiguration::instance().reset_dpi ();
123 ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
126 BootMessage (_("Setup Editor"));
127 editor->set_session (s);
128 BootMessage (_("Setup Mixer"));
129 mixer->set_session (s);
130 meterbridge->set_session (s);
131 luawindow->set_session (s);
133 /* its safe to do this now */
135 BootMessage (_("Reload Session History"));
136 s->restore_history ("");
139 /** The main editor window has been closed */
141 ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
144 /* just hide the window, and return - the top menu stays up */
148 /* time to get out of here */
155 ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
162 Gtk::Notebook* nb = 0;
163 Gtk::Window* win = 0;
164 ArdourWidgets::Tabbable* tabbable = 0;
167 if (w == GTK_WIDGET(editor->contents().gobj())) {
169 } else if (w == GTK_WIDGET(mixer->contents().gobj())) {
171 } else if (w == GTK_WIDGET(rc_option_editor->contents().gobj())) {
172 tabbable = rc_option_editor;
177 nb = tabbable->tab_root_drop ();
178 win = tabbable->own_window ();
187 return 0; /* what was that? */
191 ARDOUR_UI::idle_ask_about_quit ()
193 if (_session && _session->dirty()) {
196 /* no session or session not dirty, but still ask anyway */
198 Gtk::MessageDialog msg (string_compose (_("Quit %1?"), PROGRAM_NAME),
199 false, /* no markup */
203 msg.set_default_response (Gtk::RESPONSE_YES);
205 if (msg.run() == Gtk::RESPONSE_YES) {
210 /* not reached but keep the compiler happy */
216 ARDOUR_UI::main_window_delete_event (GdkEventAny* ev)
218 /* quit the application as soon as we go idle. If we call this here,
219 * the window manager/desktop can think we're taking too longer to
220 * handle the "delete" event
223 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_ask_about_quit));
229 tab_window_root_drop (GtkNotebook* src,
235 return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data);
239 ARDOUR_UI::setup_windows ()
241 /* actions do not need to be defined when we load keybindings. They
242 * will be lazily discovered. But bindings do need to exist when we
243 * create windows/tabs with their own binding sets.
246 keyboard->setup_keybindings ();
248 _tabs.set_show_border(false);
249 _tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch));
250 _tabs.signal_page_added().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_added));
251 _tabs.signal_page_removed().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_removed));
253 rc_option_editor = new RCOptionEditor;
254 rc_option_editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
256 if (create_editor ()) {
257 error << _("UI: cannot setup editor") << endmsg;
261 if (create_mixer ()) {
262 error << _("UI: cannot setup mixer") << endmsg;
266 if (create_meterbridge ()) {
267 error << _("UI: cannot setup meterbridge") << endmsg;
271 if (create_luawindow ()) {
272 error << _("UI: cannot setup luawindow") << endmsg;
276 time_info_box = new TimeInfoBox ("ToolbarTimeInfo", false);
277 /* all other dialogs are created conditionally */
279 we_have_dependents ();
281 /* order of addition affects order seen in initial window display */
283 rc_option_editor->add_to_notebook (_tabs, _("Preferences"));
284 mixer->add_to_notebook (_tabs, _("Mixer"));
285 editor->add_to_notebook (_tabs, _("Editor"));
287 top_packer.pack_start (menu_bar_base, false, false);
289 main_vpacker.pack_start (top_packer, false, false);
291 ArdourWidgets::ArdourDropShadow *spacer = manage (new (ArdourWidgets::ArdourDropShadow));
292 spacer->set_size_request( -1, 4 );
295 /* now add the transport sample to the top of main window */
297 main_vpacker.pack_start ( *spacer, false, false);
298 main_vpacker.pack_start (transport_frame, false, false);
299 main_vpacker.pack_start (_tabs, true, true);
301 LuaInstance::instance()->ActionChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_action_script_btn));
303 for (int i = 0; i < MAX_LUA_ACTION_SCRIPTS; ++i) {
304 std::string const a = string_compose (X_("script-action-%1"), i + 1);
305 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
307 action_script_call_btn[i].set_text (string_compose ("%1", i+1));
308 action_script_call_btn[i].set_related_action (act);
309 action_script_call_btn[i].signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::bind_lua_action_script), i), false);
310 if (act->get_sensitive ()) {
311 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() & ~Gtkmm2ext::Insensitive));
313 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() | Gtkmm2ext::Insensitive));
315 const int row = i % 2;
316 const int col = i / 2;
317 action_script_table.attach (action_script_call_btn[i], col, col + 1, row, row + 1, EXPAND, EXPAND, 1, 0);
318 action_script_call_btn[i].set_no_show_all ();
320 action_script_table.show ();
326 _main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
328 /* pack the main vpacker into the main window and show everything
331 _main_window.add (main_vpacker);
332 transport_frame.show_all ();
334 const XMLNode* mnode = main_window_settings ();
337 XMLProperty const * prop;
343 if ((prop = mnode->property (X_("x"))) != 0) {
344 x = atoi (prop->value());
347 if ((prop = mnode->property (X_("y"))) != 0) {
348 y = atoi (prop->value());
351 if ((prop = mnode->property (X_("w"))) != 0) {
352 w = atoi (prop->value());
355 if ((prop = mnode->property (X_("h"))) != 0) {
356 h = atoi (prop->value());
359 if (x >= 0 && y >= 0 && w >= 0 && h >= 0) {
360 _main_window.set_position (Gtk::WIN_POS_NONE);
363 if (x >= 0 && y >= 0) {
364 _main_window.move (x, y);
367 if (w > 0 && h > 0) {
368 _main_window.set_default_size (w, h);
371 std::string current_tab;
373 if ((prop = mnode->property (X_("current-tab"))) != 0) {
374 current_tab = prop->value();
376 current_tab = "editor";
378 if (mixer && current_tab == "mixer") {
379 _tabs.set_current_page (_tabs.page_num (mixer->contents()));
380 } else if (rc_option_editor && current_tab == "preferences") {
381 _tabs.set_current_page (_tabs.page_num (rc_option_editor->contents()));
383 _tabs.set_current_page (_tabs.page_num (editor->contents()));
387 setup_toplevel_window (_main_window, "", this);
388 _main_window.show_all ();
390 _tabs.set_show_tabs (false);
392 /* It would be nice if Gtkmm had wrapped this rather than just
393 * deprecating the old set_window_creation_hook() method, but oh well...
395 g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this);
401 ARDOUR_UI::bind_lua_action_script (GdkEventButton*ev, int i)
403 if (ev->button != 3) {
406 LuaInstance *li = LuaInstance::instance();
407 if (Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::TertiaryModifier)) {
408 li->remove_lua_action (i);
410 li->interactive_add (LuaScriptInfo::EditorAction, i);
416 ARDOUR_UI::update_action_script_btn (int i, const std::string& n)
418 if (LuaInstance::instance()->lua_action_has_icon (i)) {
420 action_script_call_btn[i].set_icon (&LuaInstance::render_action_icon, (void*)ii);
422 action_script_call_btn[i].set_icon (0, 0);
425 std::string const a = string_compose (X_("script-action-%1"), i + 1);
426 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
429 act->set_label (string_compose (_("Unset #%1"), i + 1));
430 act->set_tooltip (_("No action bound\nRight-click to assign"));
431 act->set_sensitive (false);
434 act->set_tooltip (string_compose (_("%1\n\nClick to run\nRight-click to re-assign\nShift+right-click to unassign"), n));
435 act->set_sensitive (true);
437 KeyEditor::UpdateBindings ();