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"
45 #include "rc_option_editor.h"
46 #include "route_params_ui.h"
47 #include "time_info_box.h"
61 using namespace ARDOUR;
64 ARDOUR_UI::we_have_dependents ()
69 ProcessorBox::register_actions ();
71 /* Global, editor, mixer, processor box actions are defined now. Link
72 them with any bindings, so that GTK does not get a chance to define
73 the GTK accel map entries first when we ask the GtkUIManager to
76 If GTK adds the actions to its accel map before we do, we lose our
77 freedom to use any keys. More precisely, we can use any keys, but
78 ones that GTK considers illegal as accelerators will not show up in
81 There are other dynamic actions that can be created by a monitor
82 section, by step entry dialogs. These need to be handled
83 separately. They don't tend to use GTK-illegal bindings and more
84 importantly they don't have menus showing the bindings, so it is
88 Gtkmm2ext::Bindings::associate_all ();
90 editor->setup_tooltips ();
91 editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks));
93 /* catch up on tabbable state, in the right order to leave the editor
97 tabbable_state_change (*rc_option_editor);
98 tabbable_state_change (*mixer);
99 tabbable_state_change (*editor);
101 /* all actions are defined */
103 ActionManager::load_menus (ARDOUR_COMMAND_LINE::menus_file);
105 /* catch up on parameters */
107 boost::function<void (std::string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
108 Config->map_parameters (pc);
110 UIConfiguration::instance().reset_dpi ();
114 ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
117 BootMessage (_("Setup Editor"));
118 editor->set_session (s);
119 BootMessage (_("Setup Mixer"));
120 mixer->set_session (s);
121 meterbridge->set_session (s);
122 luawindow->set_session (s);
124 /* its safe to do this now */
126 BootMessage (_("Reload Session History"));
127 s->restore_history ("");
130 /** The main editor window has been closed */
132 ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
135 /* just hide the window, and return - the top menu stays up */
139 /* time to get out of here */
146 ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
153 Gtk::Notebook* nb = 0;
154 Gtk::Window* win = 0;
155 Gtkmm2ext::Tabbable* tabbable = 0;
158 if (w == GTK_WIDGET(editor->contents().gobj())) {
160 } else if (w == GTK_WIDGET(mixer->contents().gobj())) {
162 } else if (w == GTK_WIDGET(rc_option_editor->contents().gobj())) {
163 tabbable = rc_option_editor;
168 nb = tabbable->tab_root_drop ();
169 win = tabbable->own_window ();
178 return 0; /* what was that? */
182 ARDOUR_UI::idle_ask_about_quit ()
184 if (_session && _session->dirty()) {
187 /* no session or session not dirty, but still ask anyway */
189 Gtk::MessageDialog msg (string_compose (_("Quit %1?"), PROGRAM_NAME),
190 false, /* no markup */
194 msg.set_default_response (Gtk::RESPONSE_YES);
196 if (msg.run() == Gtk::RESPONSE_YES) {
201 /* not reached but keep the compiler happy */
207 ARDOUR_UI::main_window_delete_event (GdkEventAny* ev)
209 /* quit the application as soon as we go idle. If we call this here,
210 * the window manager/desktop can think we're taking too longer to
211 * handle the "delete" event
214 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_ask_about_quit));
220 tab_window_root_drop (GtkNotebook* src,
226 return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data);
230 ARDOUR_UI::setup_windows ()
232 /* actions do not need to be defined when we load keybindings. They
233 * will be lazily discovered. But bindings do need to exist when we
234 * create windows/tabs with their own binding sets.
237 keyboard->setup_keybindings ();
239 _tabs.set_show_border(false);
240 _tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch));
241 _tabs.signal_page_added().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_added));
242 _tabs.signal_page_removed().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_removed));
244 rc_option_editor = new RCOptionEditor;
245 rc_option_editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
247 if (create_editor ()) {
248 error << _("UI: cannot setup editor") << endmsg;
252 if (create_mixer ()) {
253 error << _("UI: cannot setup mixer") << endmsg;
257 if (create_meterbridge ()) {
258 error << _("UI: cannot setup meterbridge") << endmsg;
262 if (create_luawindow ()) {
263 error << _("UI: cannot setup luawindow") << endmsg;
267 /* order of addition affects order seen in initial window display */
269 rc_option_editor->add_to_notebook (_tabs, _("Preferences"));
270 mixer->add_to_notebook (_tabs, _("Mixer"));
271 editor->add_to_notebook (_tabs, _("Editor"));
273 time_info_box = new TimeInfoBox (false);
274 /* all other dialogs are created conditionally */
276 we_have_dependents ();
279 EventBox* status_bar_event_box = manage (new EventBox);
281 status_bar_event_box->add (status_bar_label);
282 status_bar_event_box->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
283 status_bar_label.set_size_request (300, -1);
285 status_bar_label.show ();
286 status_bar_event_box->show ();
288 status_bar_event_box->signal_button_press_event().connect (mem_fun (*this, &ARDOUR_UI::status_bar_button_press));
290 status_bar_hpacker.pack_start (*status_bar_event_box, true, true, 6);
291 status_bar_hpacker.pack_start (menu_bar_base, false, false, 2);
293 top_packer.pack_start (menu_bar_base, false, false);
296 main_vpacker.pack_start (top_packer, false, false);
298 /* now add the transport frame to the top of main window */
300 main_vpacker.pack_start (transport_frame, false, false);
301 main_vpacker.pack_start (_tabs, true, true);
304 main_vpacker.pack_start (status_bar_hpacker, false, false);
307 LuaInstance::instance()->ActionChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_action_script_btn));
309 for (int i = 0; i < 9; ++i) {
310 std::string const a = string_compose (X_("script-action-%1"), i + 1);
311 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
313 action_script_call_btn[i].set_text (string_compose ("%1", i+1));
314 action_script_call_btn[i].set_related_action (act);
315 action_script_call_btn[i].signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::bind_lua_action_script), i), false);
316 if (act->get_sensitive ()) {
317 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() & ~Gtkmm2ext::Insensitive));
319 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() | Gtkmm2ext::Insensitive));
321 const int row = i % 2;
322 const int col = i / 2;
323 action_script_table.attach (action_script_call_btn[i], col, col + 1, row, row + 1, EXPAND, EXPAND, 1, 0);
324 action_script_call_btn[i].set_no_show_all ();
326 action_script_table.show ();
332 _main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
334 /* pack the main vpacker into the main window and show everything
337 _main_window.add (main_vpacker);
338 transport_frame.show_all ();
340 const XMLNode* mnode = main_window_settings ();
343 XMLProperty const * prop;
349 if ((prop = mnode->property (X_("x"))) != 0) {
350 x = atoi (prop->value());
353 if ((prop = mnode->property (X_("y"))) != 0) {
354 y = atoi (prop->value());
357 if ((prop = mnode->property (X_("w"))) != 0) {
358 w = atoi (prop->value());
361 if ((prop = mnode->property (X_("h"))) != 0) {
362 h = atoi (prop->value());
365 if (x >= 0 && y >= 0 && w >= 0 && h >= 0) {
366 _main_window.set_position (Gtk::WIN_POS_NONE);
369 if (x >= 0 && y >= 0) {
370 _main_window.move (x, y);
373 if (w > 0 && h > 0) {
374 _main_window.set_default_size (w, h);
377 std::string current_tab;
379 if ((prop = mnode->property (X_("current-tab"))) != 0) {
380 current_tab = prop->value();
382 current_tab = "editor";
384 if (mixer && current_tab == "mixer") {
385 _tabs.set_current_page (_tabs.page_num (mixer->contents()));
386 } else if (rc_option_editor && current_tab == "preferences") {
387 _tabs.set_current_page (_tabs.page_num (rc_option_editor->contents()));
389 _tabs.set_current_page (_tabs.page_num (editor->contents()));
393 setup_toplevel_window (_main_window, "", this);
394 _main_window.show_all ();
396 _tabs.set_show_tabs (false);
398 /* It would be nice if Gtkmm had wrapped this rather than just
399 * deprecating the old set_window_creation_hook() method, but oh well...
401 g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this);
407 ARDOUR_UI::bind_lua_action_script (GdkEventButton*ev, int i)
409 if (ev->button != 3) {
412 LuaInstance *li = LuaInstance::instance();
413 li->interactive_add (LuaScriptInfo::EditorAction, i);
418 ARDOUR_UI::update_action_script_btn (int i, const std::string&)
420 if (LuaInstance::instance()->lua_action_has_icon (i)) {
422 action_script_call_btn[i].set_icon (&LuaInstance::render_action_icon, (void*)ii);
424 action_script_call_btn[i].set_icon (0, 0);