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 "luawindow.h"
44 #include "rc_option_editor.h"
45 #include "route_params_ui.h"
46 #include "time_info_box.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);
126 /* its safe to do this now */
128 BootMessage (_("Reload Session History"));
129 s->restore_history ("");
132 /** The main editor window has been closed */
134 ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
137 /* just hide the window, and return - the top menu stays up */
141 /* time to get out of here */
148 ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
155 Gtk::Notebook* nb = 0;
156 Gtk::Window* win = 0;
157 Gtkmm2ext::Tabbable* tabbable = 0;
160 if (w == GTK_WIDGET(editor->contents().gobj())) {
162 } else if (w == GTK_WIDGET(mixer->contents().gobj())) {
164 } else if (w == GTK_WIDGET(rc_option_editor->contents().gobj())) {
165 tabbable = rc_option_editor;
170 nb = tabbable->tab_root_drop ();
171 win = tabbable->own_window ();
180 return 0; /* what was that? */
184 ARDOUR_UI::idle_ask_about_quit ()
186 if (_session && _session->dirty()) {
189 /* no session or session not dirty, but still ask anyway */
191 Gtk::MessageDialog msg (string_compose (_("Quit %1?"), PROGRAM_NAME),
192 false, /* no markup */
196 msg.set_default_response (Gtk::RESPONSE_YES);
198 if (msg.run() == Gtk::RESPONSE_YES) {
203 /* not reached but keep the compiler happy */
209 ARDOUR_UI::main_window_delete_event (GdkEventAny* ev)
211 /* quit the application as soon as we go idle. If we call this here,
212 * the window manager/desktop can think we're taking too longer to
213 * handle the "delete" event
216 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_ask_about_quit));
222 tab_window_root_drop (GtkNotebook* src,
228 return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data);
232 ARDOUR_UI::setup_windows ()
234 /* actions do not need to be defined when we load keybindings. They
235 * will be lazily discovered. But bindings do need to exist when we
236 * create windows/tabs with their own binding sets.
239 keyboard->setup_keybindings ();
241 _tabs.set_show_border(false);
242 _tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch));
243 _tabs.signal_page_added().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_added));
244 _tabs.signal_page_removed().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_removed));
246 rc_option_editor = new RCOptionEditor;
247 rc_option_editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
249 if (create_editor ()) {
250 error << _("UI: cannot setup editor") << endmsg;
254 if (create_mixer ()) {
255 error << _("UI: cannot setup mixer") << endmsg;
259 if (create_meterbridge ()) {
260 error << _("UI: cannot setup meterbridge") << endmsg;
264 if (create_luawindow ()) {
265 error << _("UI: cannot setup luawindow") << endmsg;
269 /* order of addition affects order seen in initial window display */
271 rc_option_editor->add_to_notebook (_tabs, _("Preferences"));
272 mixer->add_to_notebook (_tabs, _("Mixer"));
273 editor->add_to_notebook (_tabs, _("Editor"));
275 time_info_box = new TimeInfoBox (false);
276 /* all other dialogs are created conditionally */
278 we_have_dependents ();
281 EventBox* status_bar_event_box = manage (new EventBox);
283 status_bar_event_box->add (status_bar_label);
284 status_bar_event_box->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
285 status_bar_label.set_size_request (300, -1);
287 status_bar_label.show ();
288 status_bar_event_box->show ();
290 status_bar_event_box->signal_button_press_event().connect (mem_fun (*this, &ARDOUR_UI::status_bar_button_press));
292 status_bar_hpacker.pack_start (*status_bar_event_box, true, true, 6);
293 status_bar_hpacker.pack_start (menu_bar_base, false, false, 2);
295 top_packer.pack_start (menu_bar_base, false, false);
298 main_vpacker.pack_start (top_packer, false, false);
300 /* now add the transport frame to the top of main window */
302 main_vpacker.pack_start (transport_frame, false, false);
303 main_vpacker.pack_start (_tabs, true, true);
306 main_vpacker.pack_start (status_bar_hpacker, false, false);
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 if (act->get_sensitive ()) {
316 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() & ~Gtkmm2ext::Insensitive));
318 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() | Gtkmm2ext::Insensitive));
320 const int row = i % 2;
321 const int col = i / 2;
322 action_script_table.attach (action_script_call_btn[i], col, col + 1, row, row + 1, EXPAND, EXPAND, 1, 0);
323 action_script_call_btn[i].set_no_show_all ();
325 action_script_table.show ();
331 _main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
333 /* pack the main vpacker into the main window and show everything
336 _main_window.add (main_vpacker);
337 transport_frame.show_all ();
339 const XMLNode* mnode = main_window_settings ();
342 XMLProperty const * prop;
348 if ((prop = mnode->property (X_("x"))) != 0) {
349 x = atoi (prop->value());
352 if ((prop = mnode->property (X_("y"))) != 0) {
353 y = atoi (prop->value());
356 if ((prop = mnode->property (X_("w"))) != 0) {
357 w = atoi (prop->value());
360 if ((prop = mnode->property (X_("h"))) != 0) {
361 h = atoi (prop->value());
364 if (x >= 0 && y >= 0 && w >= 0 && h >= 0) {
365 _main_window.set_position (Gtk::WIN_POS_NONE);
368 if (x >= 0 && y >= 0) {
369 _main_window.move (x, y);
372 if (w > 0 && h > 0) {
373 _main_window.set_default_size (w, h);
376 std::string current_tab;
378 if ((prop = mnode->property (X_("current-tab"))) != 0) {
379 current_tab = prop->value();
381 current_tab = "editor";
383 if (mixer && current_tab == "mixer") {
384 _tabs.set_current_page (_tabs.page_num (mixer->contents()));
385 } else if (rc_option_editor && current_tab == "preferences") {
386 _tabs.set_current_page (_tabs.page_num (rc_option_editor->contents()));
388 _tabs.set_current_page (_tabs.page_num (editor->contents()));
392 setup_toplevel_window (_main_window, "", this);
393 _main_window.show_all ();
395 _tabs.set_show_tabs (false);
397 /* It would be nice if Gtkmm had wrapped this rather than just
398 * deprecating the old set_window_creation_hook() method, but oh well...
400 g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this);