#include "ardour/ardour.h"
#include "ardour/audio_backend.h"
+#include "ardour/audio_track.h"
#include "ardour/audioengine.h"
#include "ardour/audiofilesource.h"
#include "ardour/automation_watch.h"
#include "ardour/filename_extensions.h"
#include "ardour/filesystem_paths.h"
#include "ardour/ltc_file_reader.h"
+#include "ardour/midi_track.h"
#include "ardour/port.h"
#include "ardour/plugin_manager.h"
#include "ardour/process_thread.h"
#include "ardour/slave.h"
#include "ardour/system_exec.h"
+#include "LuaBridge/LuaBridge.h"
+
#ifdef WINDOWS_VST_SUPPORT
#include <fst.h>
#endif
#include "ardour/audio_unit.h"
#endif
+// fix for OSX (nsm.h has a check function, AU/Apple defines check)
+#ifdef check
+#undef check
+#endif
+
#include "timecode/time.h"
typedef uint64_t microseconds_t;
#include "keyboard.h"
#include "keyeditor.h"
#include "location_ui.h"
+#include "lua_script_manager.h"
+#include "luawindow.h"
#include "main_clock.h"
#include "missing_file_dialog.h"
#include "missing_plugin_dialog.h"
#include "route_time_axis.h"
#include "route_params_ui.h"
#include "save_as_dialog.h"
+#include "script_selector.h"
#include "session_dialog.h"
#include "session_metadata_dialog.h"
#include "session_option_editor.h"
ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
-<<<<<<< HEAD
-
: Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp)
-=======
- : Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp)
->>>>>>> first compilable version of tabbable design.
, session_loaded (false)
, gui_object_state (new GUIObjectState)
, primary_clock (new MainClock (X_("primary"), X_("transport"), true ))
, last_key_press_time (0)
, save_as_dialog (0)
, meterbridge (0)
+ , luawindow (0)
, rc_option_editor (0)
, speaker_config_window (X_("speaker-config"), _("Speaker Configuration"))
, add_route_dialog (X_("add-routes"), _("Add Tracks/Busses"))
, route_params (X_("inspector"), _("Tracks and Busses"))
, audio_midi_setup (X_("audio-midi-setup"), _("Audio/MIDI Setup"))
, export_video_dialog (X_("video-export"), _("Video Export Dialog"))
+ , lua_script_window (X_("script-manager"), _("Script Manager"))
, session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this))
, add_video_dialog (X_("add-video"), _("Add Video"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this))
, bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this))
, _feedback_exists (false)
, _log_not_acknowledged (LogLevelNone)
, duplicate_routes_dialog (0)
+ , editor_visibility_button (S_("Window|Editor"))
+ , mixer_visibility_button (S_("Window|Mixer"))
+ , prefs_visibility_button (S_("Window|Preferences"))
{
Gtkmm2ext::init (localedir);
keyboard->set_state (*node, Stateful::loading_state_version);
}
- /* we don't like certain modifiers */
- Bindings::set_ignored_state (GDK_LOCK_MASK|GDK_MOD2_MASK|GDK_MOD3_MASK);
-
UIConfiguration::instance().reset_dpi ();
TimeAxisViewItem::set_constant_heights ();
audio_port_matrix.set_state (*ui_xml, 0);
midi_port_matrix.set_state (*ui_xml, 0);
export_video_dialog.set_state (*ui_xml, 0);
+ lua_script_window.set_state (*ui_xml, 0);
}
/* Separate windows */
WM::Manager::instance().register_window (&route_params);
WM::Manager::instance().register_window (&audio_midi_setup);
WM::Manager::instance().register_window (&export_video_dialog);
+ WM::Manager::instance().register_window (&lua_script_window);
WM::Manager::instance().register_window (&bundle_manager);
WM::Manager::instance().register_window (&location_ui);
WM::Manager::instance().register_window (&big_clock_window);
/* start the time-of-day-clock */
-#ifndef GTKOSX
+#ifndef __APPLE__
/* OS X provides a nearly-always visible wallclock, so don't be stupid */
update_wall_clock ();
Glib::signal_timeout().connect_seconds (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 1);
if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
// don't bother at 'real' exit. the OS cleans up for us.
- delete big_clock;
- delete primary_clock;
- delete secondary_clock;
- delete _process_thread;
- delete meterbridge;
- delete editor;
- delete mixer;
- delete nsm;
- delete gui_object_state;
+ delete big_clock; big_clock = 0;
+ delete primary_clock; primary_clock = 0;
+ delete secondary_clock; secondary_clock = 0;
+ delete _process_thread; _process_thread = 0;
+ delete meterbridge; meterbridge = 0;
+ delete luawindow; luawindow = 0;
+ delete editor; editor = 0;
+ delete mixer; mixer = 0;
+ delete nsm; nsm = 0;
+ delete gui_object_state; gui_object_state = 0;
FastMeter::flush_pattern_cache ();
PixFader::flush_pattern_cache ();
}
}
}
-
void
-ARDOUR_UI::session_add_mixed_track (const ChanCount& input, const ChanCount& output, RouteGroup* route_group,
- uint32_t how_many, const string& name_template, PluginInfoPtr instrument)
+ARDOUR_UI::session_add_mixed_track (
+ const ChanCount& input,
+ const ChanCount& output,
+ RouteGroup* route_group,
+ uint32_t how_many,
+ const string& name_template,
+ bool strict_io,
+ PluginInfoPtr instrument)
{
list<boost::shared_ptr<MidiTrack> > tracks;
}
catch (...) {
- MessageDialog msg (_main_window,
- string_compose (_("There are insufficient ports available\n\
-to create a new track or bus.\n\
-You should save %1, exit and\n\
-restart with more ports."), PROGRAM_NAME));
- msg.run ();
+ display_insufficient_ports_message ();
+ return;
+ }
+
+ if (strict_io) {
+ for (list<boost::shared_ptr<MidiTrack> >::iterator i = tracks.begin(); i != tracks.end(); ++i) {
+ (*i)->set_strict_io (true);
+ }
}
}
+void
+ARDOUR_UI::session_add_midi_bus (
+ RouteGroup* route_group,
+ uint32_t how_many,
+ const string& name_template,
+ bool strict_io,
+ PluginInfoPtr instrument)
+{
+ RouteList routes;
+
+ if (_session == 0) {
+ warning << _("You cannot add a track without a session already loaded.") << endmsg;
+ return;
+ }
+
+ try {
+ routes = _session->new_midi_route (route_group, how_many, name_template, instrument);
+ if (routes.size() != how_many) {
+ error << string_compose(P_("could not create %1 new Midi Bus", "could not create %1 new Midi Busses", how_many), how_many) << endmsg;
+ }
+
+ }
+ catch (...) {
+ display_insufficient_ports_message ();
+ return;
+ }
+
+ if (strict_io) {
+ for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+ (*i)->set_strict_io (true);
+ }
+ }
+}
void
-ARDOUR_UI::session_add_midi_route (bool disk, RouteGroup* route_group, uint32_t how_many, const string& name_template, PluginInfoPtr instrument)
+ARDOUR_UI::session_add_midi_route (
+ bool disk,
+ RouteGroup* route_group,
+ uint32_t how_many,
+ const string& name_template,
+ bool strict_io,
+ PluginInfoPtr instrument)
{
ChanCount one_midi_channel;
one_midi_channel.set (DataType::MIDI, 1);
if (disk) {
- session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, instrument);
+ session_add_mixed_track (one_midi_channel, one_midi_channel, route_group, how_many, name_template, strict_io, instrument);
+ } else {
+ session_add_midi_bus (route_group, how_many, name_template, strict_io, instrument);
}
}
ARDOUR::TrackMode mode,
RouteGroup* route_group,
uint32_t how_many,
- string const & name_template
+ string const & name_template,
+ bool strict_io
)
{
list<boost::shared_ptr<AudioTrack> > tracks;
}
catch (...) {
- MessageDialog msg (_main_window,
- string_compose (_("There are insufficient ports available\n\
+ display_insufficient_ports_message ();
+ return;
+ }
+
+ if (strict_io) {
+ for (list<boost::shared_ptr<AudioTrack> >::iterator i = tracks.begin(); i != tracks.end(); ++i) {
+ (*i)->set_strict_io (true);
+ }
+ for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
+ (*i)->set_strict_io (true);
+ }
+ }
+}
+
+void
+ARDOUR_UI::display_insufficient_ports_message ()
+{
+ MessageDialog msg (_main_window,
+ string_compose (_("There are insufficient ports available\n\
to create a new track or bus.\n\
You should save %1, exit and\n\
restart with more ports."), PROGRAM_NAME));
- pop_back_splash (msg);
- msg.run ();
- }
+ pop_back_splash (msg);
+ msg.run ();
}
void
if (get_session_parameters (true, false)) {
exit (1);
}
-
- goto_editor_window ();
}
}
}
setup_order_hint(add_route_dialog->insert_at());
-
string template_path = add_route_dialog->track_template();
DisplaySuspender ds;
PluginInfoPtr instrument = add_route_dialog->requested_instrument ();
RouteGroup* route_group = add_route_dialog->route_group ();
AutoConnectOption oac = Config->get_output_auto_connect();
+ bool strict_io = add_route_dialog->use_strict_io ();
if (oac & AutoConnectMaster) {
output_chan.set (DataType::AUDIO, (_session->master_out() ? _session->master_out()->n_inputs().n_audio() : input_chan.n_audio()));
switch (add_route_dialog->type_wanted()) {
case AddRouteDialog::AudioTrack:
- session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template);
+ session_add_audio_track (input_chan.n_audio(), output_chan.n_audio(), add_route_dialog->mode(), route_group, count, name_template, strict_io);
break;
case AddRouteDialog::MidiTrack:
- session_add_midi_track (route_group, count, name_template, instrument);
+ session_add_midi_track (route_group, count, name_template, strict_io, instrument);
break;
case AddRouteDialog::MixedTrack:
- session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, instrument);
+ session_add_mixed_track (input_chan, output_chan, route_group, count, name_template, strict_io, instrument);
break;
case AddRouteDialog::AudioBus:
- session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template);
+ session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template, strict_io);
+ break;
+ case AddRouteDialog::MidiBus:
+ session_add_midi_bus (route_group, count, name_template, strict_io, instrument);
break;
}
}
+void
+ARDOUR_UI::add_lua_script ()
+{
+ if (!_session) {
+ return;
+ }
+
+ LuaScriptInfoPtr spi;
+ ScriptSelector ss ("Add Lua Session Script", LuaScriptInfo::Session);
+ switch (ss.run ()) {
+ case Gtk::RESPONSE_ACCEPT:
+ spi = ss.script();
+ break;
+ default:
+ return;
+ }
+ ss.hide();
+
+ std::string script = "";
+
+ try {
+ script = Glib::file_get_contents (spi->path);
+ } catch (Glib::FileError e) {
+ string msg = string_compose (_("Cannot read session script '%1': %2"), spi->path, e.what());
+ MessageDialog am (msg);
+ am.run ();
+ return;
+ }
+
+ LuaScriptParamList lsp = LuaScriptParams::script_params (spi, "sess_params");
+ std::vector<std::string> reg = _session->registered_lua_functions ();
+
+ ScriptParameterDialog spd (_("Set Script Parameters"), spi, reg, lsp);
+ switch (spd.run ()) {
+ case Gtk::RESPONSE_ACCEPT:
+ break;
+ default:
+ return;
+ }
+
+ try {
+ _session->register_lua_function (spd.name(), script, lsp);
+ } catch (luabridge::LuaException const& e) {
+ string msg = string_compose (_("Session script '%1' instantiation failed: %2"), spd.name(), e.what ());
+ MessageDialog am (msg);
+ am.run ();
+ } catch (SessionException e) {
+ string msg = string_compose (_("Loading Session script '%1' failed: %2"), spd.name(), e.what ());
+ MessageDialog am (msg);
+ am.run ();
+ }
+}
+
+void
+ARDOUR_UI::remove_lua_script ()
+{
+ if (!_session) {
+ return;
+ }
+ if (_session->registered_lua_function_count () == 0) {
+ string msg = _("There are no active Lua session scripts present in this session.");
+ MessageDialog am (msg);
+ am.run ();
+ return;
+ }
+
+ std::vector<std::string> reg = _session->registered_lua_functions ();
+ SessionScriptManager sm ("Remove Lua Session Script", reg);
+ switch (sm.run ()) {
+ case Gtk::RESPONSE_ACCEPT:
+ break;
+ default:
+ return;
+ }
+ try {
+ _session->unregister_lua_function (sm.name());
+ } catch (luabridge::LuaException const& e) {
+ string msg = string_compose (_("Session script '%1' removal failed: %2"), sm.name(), e.what ());
+ MessageDialog am (msg);
+ am.run ();
+ }
+}
+
void
ARDOUR_UI::stop_video_server (bool ask_confirm)
{
return key_press_focus_accelerator_handler (*window, ev, bindings);
}
+static Gtkmm2ext::Bindings*
+get_bindings_from_widget_heirarchy (GtkWidget* w)
+{
+ void* p;
+
+ while (w) {
+ if ((p = g_object_get_data (G_OBJECT(w), "ardour-bindings")) != 0) {
+ break;
+ }
+ w = gtk_widget_get_parent (w);
+ }
+
+ return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
+}
+
bool
ARDOUR_UI::key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev, Gtkmm2ext::Bindings* bindings)
{
GtkWindow* win = window.gobj();
GtkWidget* focus = gtk_window_get_focus (win);
bool special_handling_of_unmodified_accelerators = false;
- /* consider all relevant modifiers but not LOCK or SHIFT */
const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
- GdkModifierType modifier = GdkModifierType (ev->state);
- modifier = GdkModifierType (modifier & gtk_accelerator_get_default_mod_mask());
- Gtkmm2ext::possibly_translate_mod_to_make_legal_accelerator(modifier);
-
if (focus) {
/* some widget has keyboard focus */
*/
special_handling_of_unmodified_accelerators = true;
+
+ } else {
+
+ Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (focus);
+ if (focus_bindings) {
+ bindings = focus_bindings;
+ DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Switch bindings based on focus widget, now using %1\n", bindings->name()));
+ }
}
}
- DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 focus = %7 (%8) Key event: code = %2 state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7\n",
+ DEBUG_TRACE (DEBUG::Accelerators, string_compose ("Win = %1 focus = %7 (%8) Key event: code = %2 state = %3 special handling ? %4 magic widget focus ? %5 focus widget %6 named %7 mods ? %8\n",
win,
ev->keyval,
show_gdk_event_state (ev->state),
special_handling_of_unmodified_accelerators,
Keyboard::some_magic_widget_has_focus(),
focus,
- (focus ? gtk_widget_get_name (focus) : "no focus widget")));
+ (focus ? gtk_widget_get_name (focus) : "no focus widget"),
+ ((ev->state & mask) ? "yes" : "no")));
/* This exists to allow us to override the way GTK handles
key events. The normal sequence is:
if (bindings) {
- DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 for this event\n", bindings));
+ DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
if (bindings->activate (k, Bindings::Press)) {
DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
void
ARDOUR_UI::load_bindings ()
{
- if ((global_bindings = Bindings::get_bindings ("global", global_actions)) == 0) {
+ if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) {
error << _("Global keybindings are missing") << endmsg;
}
}