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"
43 #include "rc_option_editor.h"
44 #include "route_params_ui.h"
58 using namespace ARDOUR;
61 ARDOUR_UI::we_have_dependents ()
66 ProcessorBox::register_actions ();
68 /* Global, editor, mixer, processor box actions are defined now. Link
69 them with any bindings, so that GTK does not get a chance to define
70 the GTK accel map entries first when we ask the GtkUIManager to
73 If GTK adds the actions to its accel map before we do, we lose our
74 freedom to use any keys. More precisely, we can use any keys, but
75 ones that GTK considers illegal as accelerators will not show up in
78 There are other dynamic actions that can be created by a monitor
79 section, by step entry dialogs. These need to be handled
80 separately. They don't tend to use GTK-illegal bindings and more
81 importantly they don't have menus showing the bindings, so it is
85 Gtkmm2ext::Bindings::associate_all ();
87 editor->setup_tooltips ();
88 editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks));
90 /* catch up on tabbable state */
92 tabbable_state_change (*editor);
93 tabbable_state_change (*mixer);
94 tabbable_state_change (*rc_option_editor);
96 /* all actions are defined */
98 ActionManager::load_menus (ARDOUR_COMMAND_LINE::menus_file);
100 editor->track_mixer_selection ();
101 mixer->track_editor_selection ();
103 /* catch up on parameters */
105 boost::function<void (std::string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
106 Config->map_parameters (pc);
108 UIConfiguration::instance().reset_dpi ();
112 ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
115 BootMessage (_("Setup Editor"));
116 editor->set_session (s);
117 BootMessage (_("Setup Mixer"));
118 mixer->set_session (s);
119 meterbridge->set_session (s);
121 /* its safe to do this now */
123 BootMessage (_("Reload Session History"));
124 s->restore_history ("");
127 /** The main editor window has been closed */
129 ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
132 /* just hide the window, and return - the top menu stays up */
136 /* time to get out of here */
143 ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
150 Gtk::Notebook* nb = 0;
151 Gtk::Window* win = 0;
152 Gtkmm2ext::Tabbable* tabbable = 0;
155 if (w == GTK_WIDGET(editor->contents().gobj())) {
157 } else if (w == GTK_WIDGET(mixer->contents().gobj())) {
159 } else if (w == GTK_WIDGET(rc_option_editor->contents().gobj())) {
160 tabbable = rc_option_editor;
165 nb = tabbable->tab_root_drop ();
166 win = tabbable->own_window ();
175 return 0; /* what was that? */
179 ARDOUR_UI::idle_ask_about_quit ()
181 if (_session && _session->dirty()) {
184 /* no session or session not dirty, but still ask anyway */
186 Gtk::MessageDialog msg (string_compose ("Quit %1?", PROGRAM_NAME),
187 false, /* no markup */
191 msg.set_default_response (Gtk::RESPONSE_YES);
193 if (msg.run() == Gtk::RESPONSE_YES) {
198 /* not reached but keep the compiler happy */
204 ARDOUR_UI::main_window_delete_event (GdkEventAny* ev)
206 /* quit the application as soon as we go idle. If we call this here,
207 * the window manager/desktop can think we're taking too longer to
208 * handle the "delete" event
211 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_ask_about_quit));
217 tab_window_root_drop (GtkNotebook* src,
223 return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data);
227 ARDOUR_UI::setup_windows ()
229 /* actions do not need to be defined when we load keybindings. They
230 * will be lazily discovered. But bindings do need to exist when we
231 * create windows/tabs with their own binding sets.
234 keyboard->setup_keybindings ();
236 /* we don't use a widget with its own window for the tab close button,
237 which makes it impossible to rely on GTK+ to generate signals for
238 events occuring "in" this widget. Instead, we pre-connect a
239 handler to the relevant events on the notebook and then check
240 to see if the event coordinates tell us that it occured "in"
243 _tabs.signal_button_press_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_button_event), false);
244 _tabs.signal_button_release_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_button_event), false);
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 /* order of addition affects order seen in initial window display */
266 rc_option_editor->add_to_notebook (_tabs, _("Preferences"));
267 mixer->add_to_notebook (_tabs, _("Mixer"));
268 editor->add_to_notebook (_tabs, _("Editor"));
270 /* all other dialogs are created conditionally */
272 we_have_dependents ();
275 EventBox* status_bar_event_box = manage (new EventBox);
277 status_bar_event_box->add (status_bar_label);
278 status_bar_event_box->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
279 status_bar_label.set_size_request (300, -1);
281 status_bar_label.show ();
282 status_bar_event_box->show ();
284 status_bar_event_box->signal_button_press_event().connect (mem_fun (*this, &ARDOUR_UI::status_bar_button_press));
286 status_bar_hpacker.pack_start (*status_bar_event_box, true, true, 6);
287 status_bar_hpacker.pack_start (menu_bar_base, false, false, 2);
289 top_packer.pack_start (menu_bar_base, false, false);
292 main_vpacker.pack_start (top_packer, false, false);
294 /* now add the transport frame to the top of main window */
296 main_vpacker.pack_start (transport_frame, false, false);
297 main_vpacker.pack_start (_tabs, true, true);
300 main_vpacker.pack_start (status_bar_hpacker, false, false);
307 _main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
309 /* pack the main vpacker into the main window and show everything
312 _main_window.add (main_vpacker);
313 transport_frame.show_all ();
315 const XMLNode* mnode = main_window_settings ();
318 const XMLProperty* prop;
324 if ((prop = mnode->property (X_("x"))) != 0) {
325 x = atoi (prop->value());
328 if ((prop = mnode->property (X_("y"))) != 0) {
329 y = atoi (prop->value());
332 if ((prop = mnode->property (X_("w"))) != 0) {
333 w = atoi (prop->value());
336 if ((prop = mnode->property (X_("h"))) != 0) {
337 h = atoi (prop->value());
340 if (x >= 0 && y >= 0 && w >= 0 && h >= 0) {
341 _main_window.set_position (Gtk::WIN_POS_NONE);
344 if (x >= 0 && y >= 0) {
345 _main_window.move (x, y);
348 if (w > 0 && h > 0) {
349 _main_window.set_default_size (w, h);
352 std::string current_tab;
354 if ((prop = mnode->property (X_("current-tab"))) != 0) {
355 current_tab = prop->value();
357 current_tab = "editor";
359 if (mixer && current_tab == "mixer") {
360 _tabs.set_current_page (_tabs.page_num (mixer->contents()));
361 } else if (rc_option_editor && current_tab == "preferences") {
362 _tabs.set_current_page (_tabs.page_num (rc_option_editor->contents()));
364 _tabs.set_current_page (_tabs.page_num (editor->contents()));
368 _main_window.show_all ();
369 setup_toplevel_window (_main_window, "", this);
371 _tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch));
372 _tabs.signal_page_removed().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_removed));
373 _tabs.signal_page_added().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_added));
375 /* It would be nice if Gtkmm had wrapped this rather than just
376 * deprecating the old set_window_creation_hook() method, but oh well...
378 g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this);