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 /* catch up on parameters */
106 boost::function<void (std::string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
107 Config->map_parameters (pc);
109 UIConfiguration::instance().reset_dpi ();
113 ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
116 BootMessage (_("Setup Editor"));
117 editor->set_session (s);
118 BootMessage (_("Setup Mixer"));
119 mixer->set_session (s);
120 meterbridge->set_session (s);
121 luawindow->set_session (s);
123 /* its safe to do this now */
125 BootMessage (_("Reload Session History"));
126 s->restore_history ("");
129 /** The main editor window has been closed */
131 ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
134 /* just hide the window, and return - the top menu stays up */
138 /* time to get out of here */
145 ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
152 Gtk::Notebook* nb = 0;
153 Gtk::Window* win = 0;
154 Gtkmm2ext::Tabbable* tabbable = 0;
157 if (w == GTK_WIDGET(editor->contents().gobj())) {
159 } else if (w == GTK_WIDGET(mixer->contents().gobj())) {
161 } else if (w == GTK_WIDGET(rc_option_editor->contents().gobj())) {
162 tabbable = rc_option_editor;
167 nb = tabbable->tab_root_drop ();
168 win = tabbable->own_window ();
177 return 0; /* what was that? */
181 ARDOUR_UI::idle_ask_about_quit ()
183 if (_session && _session->dirty()) {
186 /* no session or session not dirty, but still ask anyway */
188 Gtk::MessageDialog msg (string_compose (_("Quit %1?"), PROGRAM_NAME),
189 false, /* no markup */
193 msg.set_default_response (Gtk::RESPONSE_YES);
195 if (msg.run() == Gtk::RESPONSE_YES) {
200 /* not reached but keep the compiler happy */
206 ARDOUR_UI::main_window_delete_event (GdkEventAny* ev)
208 /* quit the application as soon as we go idle. If we call this here,
209 * the window manager/desktop can think we're taking too longer to
210 * handle the "delete" event
213 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_ask_about_quit));
219 tab_window_root_drop (GtkNotebook* src,
225 return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data);
229 ARDOUR_UI::setup_windows ()
231 /* actions do not need to be defined when we load keybindings. They
232 * will be lazily discovered. But bindings do need to exist when we
233 * create windows/tabs with their own binding sets.
236 keyboard->setup_keybindings ();
238 _tabs.set_show_border(false);
239 _tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch));
240 _tabs.signal_page_added().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_added));
241 _tabs.signal_page_removed().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_removed));
243 rc_option_editor = new RCOptionEditor;
244 rc_option_editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
246 if (create_editor ()) {
247 error << _("UI: cannot setup editor") << endmsg;
251 if (create_mixer ()) {
252 error << _("UI: cannot setup mixer") << endmsg;
256 if (create_meterbridge ()) {
257 error << _("UI: cannot setup meterbridge") << endmsg;
261 if (create_luawindow ()) {
262 error << _("UI: cannot setup luawindow") << endmsg;
266 /* order of addition affects order seen in initial window display */
268 rc_option_editor->add_to_notebook (_tabs, _("Preferences"));
269 mixer->add_to_notebook (_tabs, _("Mixer"));
270 editor->add_to_notebook (_tabs, _("Editor"));
272 time_info_box = new TimeInfoBox (false);
273 /* all other dialogs are created conditionally */
275 we_have_dependents ();
278 EventBox* status_bar_event_box = manage (new EventBox);
280 status_bar_event_box->add (status_bar_label);
281 status_bar_event_box->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
282 status_bar_label.set_size_request (300, -1);
284 status_bar_label.show ();
285 status_bar_event_box->show ();
287 status_bar_event_box->signal_button_press_event().connect (mem_fun (*this, &ARDOUR_UI::status_bar_button_press));
289 status_bar_hpacker.pack_start (*status_bar_event_box, true, true, 6);
290 status_bar_hpacker.pack_start (menu_bar_base, false, false, 2);
292 top_packer.pack_start (menu_bar_base, false, false);
295 main_vpacker.pack_start (top_packer, false, false);
297 /* now add the transport frame to the top of main window */
299 main_vpacker.pack_start (transport_frame, false, false);
300 main_vpacker.pack_start (_tabs, true, true);
303 main_vpacker.pack_start (status_bar_hpacker, false, false);
306 for (int i = 0; i < 9; ++i) {
307 std::string const a = string_compose (X_("script-action-%1"), i + 1);
308 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
310 action_script_call_btn[i].set_text (string_compose ("%1", i+1));
311 action_script_call_btn[i].set_related_action (act);
312 if (act->get_sensitive ()) {
313 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() & ~Gtkmm2ext::Insensitive));
315 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() | Gtkmm2ext::Insensitive));
317 const int row = i % 2;
318 const int col = i / 2;
319 action_script_table.attach (action_script_call_btn[i], col, col + 1, row, row + 1, EXPAND, EXPAND, 1, 0);
320 action_script_call_btn[i].set_no_show_all ();
322 action_script_table.show ();
328 _main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
330 /* pack the main vpacker into the main window and show everything
333 _main_window.add (main_vpacker);
334 transport_frame.show_all ();
336 const XMLNode* mnode = main_window_settings ();
339 XMLProperty const * prop;
345 if ((prop = mnode->property (X_("x"))) != 0) {
346 x = atoi (prop->value());
349 if ((prop = mnode->property (X_("y"))) != 0) {
350 y = atoi (prop->value());
353 if ((prop = mnode->property (X_("w"))) != 0) {
354 w = atoi (prop->value());
357 if ((prop = mnode->property (X_("h"))) != 0) {
358 h = atoi (prop->value());
361 if (x >= 0 && y >= 0 && w >= 0 && h >= 0) {
362 _main_window.set_position (Gtk::WIN_POS_NONE);
365 if (x >= 0 && y >= 0) {
366 _main_window.move (x, y);
369 if (w > 0 && h > 0) {
370 _main_window.set_default_size (w, h);
373 std::string current_tab;
375 if ((prop = mnode->property (X_("current-tab"))) != 0) {
376 current_tab = prop->value();
378 current_tab = "editor";
380 if (mixer && current_tab == "mixer") {
381 _tabs.set_current_page (_tabs.page_num (mixer->contents()));
382 } else if (rc_option_editor && current_tab == "preferences") {
383 _tabs.set_current_page (_tabs.page_num (rc_option_editor->contents()));
385 _tabs.set_current_page (_tabs.page_num (editor->contents()));
389 setup_toplevel_window (_main_window, "", this);
390 _main_window.show_all ();
392 _tabs.set_show_tabs (false);
394 /* It would be nice if Gtkmm had wrapped this rather than just
395 * deprecating the old set_window_creation_hook() method, but oh well...
397 g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this);