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"
44 #include "keyeditor.h"
46 #include "rc_option_editor.h"
47 #include "route_params_ui.h"
48 #include "time_info_box.h"
62 using namespace ARDOUR;
65 ARDOUR_UI::we_have_dependents ()
70 ProcessorBox::register_actions ();
72 /* Global, editor, mixer, processor box actions are defined now. Link
73 them with any bindings, so that GTK does not get a chance to define
74 the GTK accel map entries first when we ask the GtkUIManager to
77 If GTK adds the actions to its accel map before we do, we lose our
78 freedom to use any keys. More precisely, we can use any keys, but
79 ones that GTK considers illegal as accelerators will not show up in
82 There are other dynamic actions that can be created by a monitor
83 section, by step entry dialogs. These need to be handled
84 separately. They don't tend to use GTK-illegal bindings and more
85 importantly they don't have menus showing the bindings, so it is
89 Gtkmm2ext::Bindings::associate_all ();
91 editor->setup_tooltips ();
92 editor->UpdateAllTransportClocks.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_transport_clocks));
94 /* catch up on tabbable state, in the right order to leave the editor
98 tabbable_state_change (*rc_option_editor);
99 tabbable_state_change (*mixer);
100 tabbable_state_change (*editor);
102 /* all actions are defined */
104 ActionManager::load_menus (ARDOUR_COMMAND_LINE::menus_file);
106 /* catch up on parameters */
108 boost::function<void (std::string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
109 Config->map_parameters (pc);
111 UIConfiguration::instance().reset_dpi ();
115 ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
118 BootMessage (_("Setup Editor"));
119 editor->set_session (s);
120 BootMessage (_("Setup Mixer"));
121 mixer->set_session (s);
122 meterbridge->set_session (s);
123 luawindow->set_session (s);
125 /* its safe to do this now */
127 BootMessage (_("Reload Session History"));
128 s->restore_history ("");
131 /** The main editor window has been closed */
133 ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
136 /* just hide the window, and return - the top menu stays up */
140 /* time to get out of here */
147 ARDOUR_UI::tab_window_root_drop (GtkNotebook* src,
154 Gtk::Notebook* nb = 0;
155 Gtk::Window* win = 0;
156 ArdourWidgets::Tabbable* tabbable = 0;
159 if (w == GTK_WIDGET(editor->contents().gobj())) {
161 } else if (w == GTK_WIDGET(mixer->contents().gobj())) {
163 } else if (w == GTK_WIDGET(rc_option_editor->contents().gobj())) {
164 tabbable = rc_option_editor;
169 nb = tabbable->tab_root_drop ();
170 win = tabbable->own_window ();
179 return 0; /* what was that? */
183 ARDOUR_UI::idle_ask_about_quit ()
185 if (_session && _session->dirty()) {
188 /* no session or session not dirty, but still ask anyway */
190 Gtk::MessageDialog msg (string_compose (_("Quit %1?"), PROGRAM_NAME),
191 false, /* no markup */
195 msg.set_default_response (Gtk::RESPONSE_YES);
197 if (msg.run() == Gtk::RESPONSE_YES) {
202 /* not reached but keep the compiler happy */
208 ARDOUR_UI::main_window_delete_event (GdkEventAny* ev)
210 /* quit the application as soon as we go idle. If we call this here,
211 * the window manager/desktop can think we're taking too longer to
212 * handle the "delete" event
215 Glib::signal_idle().connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_ask_about_quit));
221 tab_window_root_drop (GtkNotebook* src,
227 return ARDOUR_UI::instance()->tab_window_root_drop (src, w, x, y, user_data);
231 ARDOUR_UI::setup_windows ()
233 /* actions do not need to be defined when we load keybindings. They
234 * will be lazily discovered. But bindings do need to exist when we
235 * create windows/tabs with their own binding sets.
238 keyboard->setup_keybindings ();
240 _tabs.set_show_border(false);
241 _tabs.signal_switch_page().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_switch));
242 _tabs.signal_page_added().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_added));
243 _tabs.signal_page_removed().connect (sigc::mem_fun (*this, &ARDOUR_UI::tabs_page_removed));
245 rc_option_editor = new RCOptionEditor;
246 rc_option_editor->StateChange.connect (sigc::mem_fun (*this, &ARDOUR_UI::tabbable_state_change));
248 if (create_editor ()) {
249 error << _("UI: cannot setup editor") << endmsg;
253 if (create_mixer ()) {
254 error << _("UI: cannot setup mixer") << endmsg;
258 if (create_meterbridge ()) {
259 error << _("UI: cannot setup meterbridge") << endmsg;
263 if (create_luawindow ()) {
264 error << _("UI: cannot setup luawindow") << endmsg;
268 /* order of addition affects order seen in initial window display */
270 rc_option_editor->add_to_notebook (_tabs, _("Preferences"));
271 mixer->add_to_notebook (_tabs, _("Mixer"));
272 editor->add_to_notebook (_tabs, _("Editor"));
274 time_info_box = new TimeInfoBox ("ToolbarTimeInfo", false);
275 /* all other dialogs are created conditionally */
277 we_have_dependents ();
279 top_packer.pack_start (menu_bar_base, false, false);
281 main_vpacker.pack_start (top_packer, false, false);
283 ArdourWidgets::ArdourDropShadow *spacer = manage (new (ArdourWidgets::ArdourDropShadow));
284 spacer->set_size_request( -1, 4 );
287 /* now add the transport sample to the top of main window */
289 main_vpacker.pack_start ( *spacer, false, false);
290 main_vpacker.pack_start (transport_frame, false, false);
291 main_vpacker.pack_start (_tabs, true, true);
293 LuaInstance::instance()->ActionChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::update_action_script_btn));
295 for (int i = 0; i < MAX_LUA_ACTION_SCRIPTS; ++i) {
296 std::string const a = string_compose (X_("script-action-%1"), i + 1);
297 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
299 action_script_call_btn[i].set_text (string_compose ("%1", i+1));
300 action_script_call_btn[i].set_related_action (act);
301 action_script_call_btn[i].signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &ARDOUR_UI::bind_lua_action_script), i), false);
302 if (act->get_sensitive ()) {
303 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() & ~Gtkmm2ext::Insensitive));
305 action_script_call_btn[i].set_visual_state (Gtkmm2ext::VisualState (action_script_call_btn[i].visual_state() | Gtkmm2ext::Insensitive));
307 const int row = i % 2;
308 const int col = i / 2;
309 action_script_table.attach (action_script_call_btn[i], col, col + 1, row, row + 1, EXPAND, EXPAND, 1, 0);
310 action_script_call_btn[i].set_no_show_all ();
312 action_script_table.show ();
318 _main_window.signal_delete_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::main_window_delete_event));
320 /* pack the main vpacker into the main window and show everything
323 _main_window.add (main_vpacker);
324 transport_frame.show_all ();
326 const XMLNode* mnode = main_window_settings ();
329 XMLProperty const * prop;
335 if ((prop = mnode->property (X_("x"))) != 0) {
336 x = atoi (prop->value());
339 if ((prop = mnode->property (X_("y"))) != 0) {
340 y = atoi (prop->value());
343 if ((prop = mnode->property (X_("w"))) != 0) {
344 w = atoi (prop->value());
347 if ((prop = mnode->property (X_("h"))) != 0) {
348 h = atoi (prop->value());
351 if (x >= 0 && y >= 0 && w >= 0 && h >= 0) {
352 _main_window.set_position (Gtk::WIN_POS_NONE);
355 if (x >= 0 && y >= 0) {
356 _main_window.move (x, y);
359 if (w > 0 && h > 0) {
360 _main_window.set_default_size (w, h);
363 std::string current_tab;
365 if ((prop = mnode->property (X_("current-tab"))) != 0) {
366 current_tab = prop->value();
368 current_tab = "editor";
370 if (mixer && current_tab == "mixer") {
371 _tabs.set_current_page (_tabs.page_num (mixer->contents()));
372 } else if (rc_option_editor && current_tab == "preferences") {
373 _tabs.set_current_page (_tabs.page_num (rc_option_editor->contents()));
375 _tabs.set_current_page (_tabs.page_num (editor->contents()));
379 setup_toplevel_window (_main_window, "", this);
380 _main_window.show_all ();
382 _tabs.set_show_tabs (false);
384 /* It would be nice if Gtkmm had wrapped this rather than just
385 * deprecating the old set_window_creation_hook() method, but oh well...
387 g_signal_connect (_tabs.gobj(), "create-window", (GCallback) ::tab_window_root_drop, this);
393 ARDOUR_UI::bind_lua_action_script (GdkEventButton*ev, int i)
395 if (ev->button != 3) {
398 LuaInstance *li = LuaInstance::instance();
399 if (Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::TertiaryModifier)) {
400 li->remove_lua_action (i);
402 li->interactive_add (LuaScriptInfo::EditorAction, i);
408 ARDOUR_UI::update_action_script_btn (int i, const std::string& n)
410 if (LuaInstance::instance()->lua_action_has_icon (i)) {
412 action_script_call_btn[i].set_icon (&LuaInstance::render_action_icon, (void*)ii);
414 action_script_call_btn[i].set_icon (0, 0);
417 std::string const a = string_compose (X_("script-action-%1"), i + 1);
418 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
421 act->set_label (string_compose (_("Unset #%1"), i + 1));
422 act->set_tooltip (_("No action bound\nRight-click to assign"));
423 act->set_sensitive (false);
426 act->set_tooltip (string_compose (_("%1\n\nClick to run\nRight-click to re-assign\nShift+right-click to unassign"), n));
427 act->set_sensitive (true);
429 KeyEditor::UpdateBindings ();