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 /* 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.
81 mixer->monitor_section().use_others_actions ();
83 /* Create "static" actions that apply to all ProcessorBoxes
85 ProcessorBox::register_actions ();
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
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
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
104 Gtkmm2ext::Bindings::associate_all ();
106 editor->setup_tooltips ();
107 editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks));
109 /* catch up on tabbable state, in the right order to leave the editor
110 * selected by default
113 tabbable_state_change (*rc_option_editor);
114 tabbable_state_change (*mixer);
115 tabbable_state_change (*editor);
117 /* all actions are defined */
119 ActionManager::load_menus (ARDOUR_COMMAND_LINE::menus_file);
121 /* catch up on parameters */
123 boost::function<void (std::string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
124 Config->map_parameters (pc);
126 UIConfiguration::instance().reset_dpi ();
130 ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
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);
140 /* its safe to do this now */
142 BootMessage (_("Reload Session History"));
143 s->restore_history ("");
146 /** The main editor window has been closed */
148 ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
151 /* just hide the window, and return - the top menu stays up */
155 /* time to get out of here */
162 ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
169 Gtk::Notebook* nb = 0;
170 Gtk::Window* win = 0;
171 ArdourWidgets::Tabbable* tabbable = 0;
174 if (w == GTK_WIDGET(editor->contents().gobj())) {
176 } else if (w == GTK_WIDGET(mixer->contents().gobj())) {
178 } else if (w == GTK_WIDGET(rc_option_editor->contents().gobj())) {
179 tabbable = rc_option_editor;
184 nb = tabbable->tab_root_drop ();
185 win = tabbable->own_window ();
194 return 0; /* what was that? */
198 ARDOUR_UI::idle_ask_about_quit ()
200 if (_session && _session->dirty()) {
203 /* no session or session not dirty, but still ask anyway */
205 Gtk::MessageDialog msg (string_compose (_("Quit %1?"), PROGRAM_NAME),
206 false, /* no markup */
210 msg.set_default_response (Gtk::RESPONSE_YES);
212 if (msg.run() == Gtk::RESPONSE_YES) {
217 /* not reached but keep the compiler happy */
223 ARDOUR_UI::main_window_delete_event (GdkEventAny* ev)
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
230 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_ask_about_quit));
236 tab_window_root_drop (GtkNotebook* src,
242 return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data);
246 ARDOUR_UI::setup_windows ()
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.
253 keyboard->setup_keybindings ();
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));
260 rc_option_editor = new RCOptionEditor;
261 rc_option_editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
263 if (create_editor ()) {
264 error << _("UI: cannot setup editor") << endmsg;
268 if (create_mixer ()) {
269 error << _("UI: cannot setup mixer") << endmsg;
273 if (create_meterbridge ()) {
274 error << _("UI: cannot setup meterbridge") << endmsg;
278 if (create_luawindow ()) {
279 error << _("UI: cannot setup luawindow") << endmsg;
283 time_info_box = new TimeInfoBox ("ToolbarTimeInfo", false);
284 /* all other dialogs are created conditionally */
286 we_have_dependents ();
288 /* order of addition affects order seen in initial window display */
290 rc_option_editor->add_to_notebook (_tabs, _("Preferences"));
291 mixer->add_to_notebook (_tabs, _("Mixer"));
292 editor->add_to_notebook (_tabs, _("Editor"));
294 top_packer.pack_start (menu_bar_base, false, false);
296 main_vpacker.pack_start (top_packer, false, false);
298 ArdourWidgets::ArdourDropShadow *spacer = manage (new (ArdourWidgets::ArdourDropShadow));
299 spacer->set_size_request( -1, 4 );
302 /* now add the transport sample to the top of main window */
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);
308 LuaInstance::instance()->ActionChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_action_script_btn));
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());
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));
320 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() | Gtkmm2ext::Insensitive));
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 ();
327 action_script_table.show ();
333 _main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
335 /* pack the main vpacker into the main window and show everything
338 _main_window.add (main_vpacker);
339 transport_frame.show_all ();
341 const XMLNode* mnode = main_window_settings ();
344 XMLProperty const * prop;
350 if ((prop = mnode->property (X_("x"))) != 0) {
351 x = atoi (prop->value());
354 if ((prop = mnode->property (X_("y"))) != 0) {
355 y = atoi (prop->value());
358 if ((prop = mnode->property (X_("w"))) != 0) {
359 w = atoi (prop->value());
362 if ((prop = mnode->property (X_("h"))) != 0) {
363 h = atoi (prop->value());
366 if (x >= 0 && y >= 0 && w >= 0 && h >= 0) {
367 _main_window.set_position (Gtk::WIN_POS_NONE);
370 if (x >= 0 && y >= 0) {
371 _main_window.move (x, y);
374 if (w > 0 && h > 0) {
375 _main_window.set_default_size (w, h);
378 std::string current_tab;
380 if ((prop = mnode->property (X_("current-tab"))) != 0) {
381 current_tab = prop->value();
383 current_tab = "editor";
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()));
390 _tabs.set_current_page (_tabs.page_num (editor->contents()));
394 setup_toplevel_window (_main_window, "", this);
395 _main_window.show_all ();
397 _tabs.set_show_tabs (false);
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...
402 g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this);
408 ARDOUR_UI::bind_lua_action_script (GdkEventButton*ev, int i)
410 if (ev->button != 3) {
413 LuaInstance *li = LuaInstance::instance();
414 if (Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::TertiaryModifier)) {
415 li->remove_lua_action (i);
417 li->interactive_add (LuaScriptInfo::EditorAction, i);
423 ARDOUR_UI::update_action_script_btn (int i, const std::string& n)
425 if (LuaInstance::instance()->lua_action_has_icon (i)) {
427 action_script_call_btn[i].set_icon (&LuaInstance::render_action_icon, (void*)ii);
429 action_script_call_btn[i].set_icon (0, 0);
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());
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);
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);
444 KeyEditor::UpdateBindings ();