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 "master_faders.h"
40 #include "meterbridge.h"
41 #include "luawindow.h"
45 #include "rc_option_editor.h"
46 #include "route_params_ui.h"
60 using namespace ARDOUR;
63 ARDOUR_UI::we_have_dependents ()
68 ProcessorBox::register_actions ();
70 /* Global, editor, mixer, processor box actions are defined now. Link
71 them with any bindings, so that GTK does not get a chance to define
72 the GTK accel map entries first when we ask the GtkUIManager to
75 If GTK adds the actions to its accel map before we do, we lose our
76 freedom to use any keys. More precisely, we can use any keys, but
77 ones that GTK considers illegal as accelerators will not show up in
80 There are other dynamic actions that can be created by a monitor
81 section, by step entry dialogs. These need to be handled
82 separately. They don't tend to use GTK-illegal bindings and more
83 importantly they don't have menus showing the bindings, so it is
87 Gtkmm2ext::Bindings::associate_all ();
89 editor->setup_tooltips ();
90 editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks));
92 /* catch up on tabbable state, in the right order to leave the editor
96 tabbable_state_change (*rc_option_editor);
97 tabbable_state_change (*mixer);
98 tabbable_state_change (*editor);
100 /* all actions are defined */
102 ActionManager::load_menus (ARDOUR_COMMAND_LINE::menus_file);
104 editor->track_mixer_selection ();
105 mixer->track_editor_selection ();
107 /* catch up on parameters */
109 boost::function<void (std::string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
110 Config->map_parameters (pc);
112 UIConfiguration::instance().reset_dpi ();
116 ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
119 BootMessage (_("Setup Editor"));
120 editor->set_session (s);
121 BootMessage (_("Setup Mixer"));
122 mixer->set_session (s);
123 meterbridge->set_session (s);
124 luawindow->set_session (s);
125 masters->set_session (s);
127 /* its safe to do this now */
129 BootMessage (_("Reload Session History"));
130 s->restore_history ("");
133 /** The main editor window has been closed */
135 ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
138 /* just hide the window, and return - the top menu stays up */
142 /* time to get out of here */
149 ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
156 Gtk::Notebook* nb = 0;
157 Gtk::Window* win = 0;
158 Gtkmm2ext::Tabbable* tabbable = 0;
161 if (w == GTK_WIDGET(editor->contents().gobj())) {
163 } else if (w == GTK_WIDGET(mixer->contents().gobj())) {
165 } else if (w == GTK_WIDGET(rc_option_editor->contents().gobj())) {
166 tabbable = rc_option_editor;
167 } else if (w == GTK_WIDGET(masters->contents().gobj())) {
172 nb = tabbable->tab_root_drop ();
173 win = tabbable->own_window ();
182 return 0; /* what was that? */
186 ARDOUR_UI::idle_ask_about_quit ()
188 if (_session && _session->dirty()) {
191 /* no session or session not dirty, but still ask anyway */
193 Gtk::MessageDialog msg (string_compose ("Quit %1?", PROGRAM_NAME),
194 false, /* no markup */
198 msg.set_default_response (Gtk::RESPONSE_YES);
200 if (msg.run() == Gtk::RESPONSE_YES) {
205 /* not reached but keep the compiler happy */
211 ARDOUR_UI::main_window_delete_event (GdkEventAny* ev)
213 /* quit the application as soon as we go idle. If we call this here,
214 * the window manager/desktop can think we're taking too longer to
215 * handle the "delete" event
218 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_ask_about_quit));
224 tab_window_root_drop (GtkNotebook* src,
230 return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data);
234 ARDOUR_UI::setup_windows ()
236 /* actions do not need to be defined when we load keybindings. They
237 * will be lazily discovered. But bindings do need to exist when we
238 * create windows/tabs with their own binding sets.
241 keyboard->setup_keybindings ();
243 _tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch));
244 _tabs.signal_page_added().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_added));
245 _tabs.signal_page_removed().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_removed));
247 rc_option_editor = new RCOptionEditor;
248 rc_option_editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
250 if (create_editor ()) {
251 error << _("UI: cannot setup editor") << endmsg;
255 if (create_mixer ()) {
256 error << _("UI: cannot setup mixer") << endmsg;
260 if (create_meterbridge ()) {
261 error << _("UI: cannot setup meterbridge") << endmsg;
265 if (create_luawindow ()) {
266 error << _("UI: cannot setup luawindow") << endmsg;
270 if (create_masters()) {
271 error << _("UI: cannot setup meterbridge") << endmsg;
275 /* order of addition affects order seen in initial window display */
277 masters->add_to_notebook (_tabs, _("Masters"));
278 rc_option_editor->add_to_notebook (_tabs, _("Preferences"));
279 mixer->add_to_notebook (_tabs, _("Mixer"));
280 editor->add_to_notebook (_tabs, _("Editor"));
282 /* all other dialogs are created conditionally */
284 we_have_dependents ();
287 EventBox* status_bar_event_box = manage (new EventBox);
289 status_bar_event_box->add (status_bar_label);
290 status_bar_event_box->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
291 status_bar_label.set_size_request (300, -1);
293 status_bar_label.show ();
294 status_bar_event_box->show ();
296 status_bar_event_box->signal_button_press_event().connect (mem_fun (*this, &ARDOUR_UI::status_bar_button_press));
298 status_bar_hpacker.pack_start (*status_bar_event_box, true, true, 6);
299 status_bar_hpacker.pack_start (menu_bar_base, false, false, 2);
301 top_packer.pack_start (menu_bar_base, false, false);
304 main_vpacker.pack_start (top_packer, false, false);
306 /* now add the transport frame to the top of main window */
308 main_vpacker.pack_start (transport_frame, false, false);
309 main_vpacker.pack_start (_tabs, true, true);
312 main_vpacker.pack_start (status_bar_hpacker, false, false);
315 for (int i = 0; i < 9; ++i) {
316 std::string const a = string_compose (X_("script-action-%1"), i + 1);
317 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
319 action_script_call_btn[i].set_text (string_compose ("%1", i+1));
320 action_script_call_btn[i].set_related_action (act);
321 if (act->get_sensitive ()) {
322 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() & ~Gtkmm2ext::Insensitive));
324 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() | Gtkmm2ext::Insensitive));
326 const int row = i % 3;
327 const int col = i / 3;
328 action_script_table.attach (action_script_call_btn[i], col, col + 1, row, row + 1, EXPAND, EXPAND, 1, 1);
329 action_script_call_btn[i].set_no_show_all ();
331 action_script_table.show ();
337 _main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
339 /* pack the main vpacker into the main window and show everything
342 _main_window.add (main_vpacker);
343 transport_frame.show_all ();
345 const XMLNode* mnode = main_window_settings ();
348 XMLProperty const * prop;
354 if ((prop = mnode->property (X_("x"))) != 0) {
355 x = atoi (prop->value());
358 if ((prop = mnode->property (X_("y"))) != 0) {
359 y = atoi (prop->value());
362 if ((prop = mnode->property (X_("w"))) != 0) {
363 w = atoi (prop->value());
366 if ((prop = mnode->property (X_("h"))) != 0) {
367 h = atoi (prop->value());
370 if (x >= 0 && y >= 0 && w >= 0 && h >= 0) {
371 _main_window.set_position (Gtk::WIN_POS_NONE);
374 if (x >= 0 && y >= 0) {
375 _main_window.move (x, y);
378 if (w > 0 && h > 0) {
379 _main_window.set_default_size (w, h);
382 std::string current_tab;
384 if ((prop = mnode->property (X_("current-tab"))) != 0) {
385 current_tab = prop->value();
387 current_tab = "editor";
389 if (mixer && current_tab == "mixer") {
390 _tabs.set_current_page (_tabs.page_num (mixer->contents()));
391 } else if (rc_option_editor && current_tab == "preferences") {
392 _tabs.set_current_page (_tabs.page_num (rc_option_editor->contents()));
393 } else if (masters && current_tab == "masters") {
394 _tabs.set_current_page (_tabs.page_num (masters->contents()));
396 _tabs.set_current_page (_tabs.page_num (editor->contents()));
400 setup_toplevel_window (_main_window, "", this);
401 _main_window.show_all ();
403 _tabs.set_show_tabs (false);
405 /* It would be nice if Gtkmm had wrapped this rather than just
406 * deprecating the old set_window_creation_hook() method, but oh well...
408 g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this);