#include <sys/resource.h>
#endif
+#ifdef __FreeBSD__
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
+
#include <stdint.h>
#include <fcntl.h>
#include <signal.h>
#include <gtkmm/messagedialog.h>
#include <gtkmm/accelmap.h>
+#include <gtkmm/stock.h>
#include "pbd/error.h"
#include "pbd/basename.h"
#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/profile.h"
#include "ardour/recent_sessions.h"
+#include "ardour/record_enable_control.h"
#include "ardour/session_directory.h"
#include "ardour/session_route.h"
#include "ardour/session_state_utils.h"
#include "ardour/source_factory.h"
#include "ardour/slave.h"
#include "ardour/system_exec.h"
+#include "ardour/track.h"
+#include "ardour/vca_manager.h"
+#include "ardour/utils.h"
+
+#include "LuaBridge/LuaBridge.h"
#ifdef WINDOWS_VST_SUPPORT
#include <fst.h>
#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"
replace_all (msg, "\n", "");
- if (err->file && err->line) {
- error << X_("XML error: ") << msg << " in " << err->file << " at line " << err->line;
+ if (!msg.empty()) {
+ if (err->file && err->line) {
+ error << X_("XML error: ") << msg << " in " << err->file << " at line " << err->line;
+
+ if (err->int2) {
+ error << ':' << err->int2;
+ }
- if (err->int2) {
- error << ':' << err->int2;
+ error << endmsg;
+ } else {
+ error << X_("XML error: ") << msg << endmsg;
}
}
- error << endmsg;
}
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 ))
, secondary_clock (new MainClock (X_("secondary"), X_("secondary"), false))
, big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false))
, video_timeline(0)
+ , global_actions (X_("global"))
, ignore_dual_punch (false)
+ , main_window_visibility (0)
, editor (0)
, mixer (0)
, nsm (0)
, 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"))
- , key_editor (X_("key-editor"), _("Key Bindings"))
, add_route_dialog (X_("add-routes"), _("Add Tracks/Busses"))
, about (X_("about"), _("About"))
- , location_ui (X_("locations"), _("Locations"))
+ , location_ui (X_("locations"), S_("Ranges|Locations"))
, 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 Tracks/Busses"), boost::bind (&ARDOUR_UI::create_add_video_dialog, 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))
, big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this))
, audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO))
, midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI))
+ , key_editor (X_("key-editor"), _("Bindings Editor"), boost::bind (&ARDOUR_UI::create_key_editor, this))
, video_server_process (0)
, splash (0)
, have_configure_timeout (false)
, _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);
_exit (0);
}
+
+ if (string (VERSIONSTRING).find (".pre") != string::npos) {
+ /* check this is not being run from ./ardev etc. */
+ if (!running_from_source_tree ()) {
+ pre_release_dialog ();
+ }
+ }
+
if (theArdourUI == 0) {
theArdourUI = this;
}
+ /* track main window visibility */
+
+ main_window_visibility = new VisibilityTracker (_main_window);
+
/* stop libxml from spewing to stdout/stderr */
xmlSetGenericErrorFunc (this, libxml_generic_error_func);
ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2));
+ /* handle sr mismatch with a dialog - cross-thread from engine */
+ ARDOUR::Session::NotifyAboutSampleRateMismatch.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::sr_mismatch_message, this, _1, _2), gui_context ());
+
/* handle requests to quit (coming from JACK session) */
ARDOUR::Session::Quit.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::finish, this), gui_context ());
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 (&key_editor);
WM::Manager::instance().register_window (&session_option_editor);
WM::Manager::instance().register_window (&speaker_config_window);
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);
WM::Manager::instance().register_window (&audio_port_matrix);
WM::Manager::instance().register_window (&midi_port_matrix);
+ /* do not retain position for add route dialog */
+ add_route_dialog.set_state_mask (WindowProxy::Size);
+
/* Trigger setting up the color scheme and loading the GTK RC file */
UIConfiguration::instance().load_rc_file (false);
attach_to_engine ();
}
+void
+ARDOUR_UI::pre_release_dialog ()
+{
+ ArdourDialog d (_("Pre-Release Warning"), true, false);
+ d.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
+
+ Label* label = manage (new Label);
+ label->set_markup (string_compose (_("<b>Welcome to this pre-release build of %1 %2</b>\n\n\
+There are still several issues and bugs to be worked on,\n\
+as well as general workflow improvements, before this can be considered\n\
+release software. So, a few guidelines:\n\
+\n\
+1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
+ though it may be so, depending on your workflow.\n\
+2) Please wait for a helpful writeup of new features.\n\
+3) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
+4) Please <b>DO</b> use the bugtracker at http://tracker.ardour.org/ to report issues\n\
+ making sure to note the product version number as 5.0-pre.\n\
+5) Please <b>DO</b> use the ardour-users mailing list to discuss ideas and pass on comments.\n\
+6) Please <b>DO</b> join us on IRC for real time discussions about %1 %2. You\n\
+ can get there directly from within the program via the Help->Chat menu option.\n\
+\n\
+Full information on all the above can be found on the support page at\n\
+\n\
+ http://ardour.org/support\n\
+"), PROGRAM_NAME, VERSIONSTRING));
+
+ d.get_vbox()->set_border_width (12);
+ d.get_vbox()->pack_start (*label, false, false, 12);
+ d.get_vbox()->show_all ();
+
+ d.run ();
+}
+
GlobalPortMatrixWindow*
ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type)
{
check_memory_locking();
- /* this is the first point at which all the keybindings are available */
+ /* this is the first point at which all the possible actions are
+ * available, because some of the available actions are dependent on
+ * aspects of the engine/backend.
+ */
if (ARDOUR_COMMAND_LINE::show_key_actions) {
- vector<string> names;
+
+
vector<string> paths;
+ vector<string> labels;
vector<string> tooltips;
vector<string> keys;
- vector<AccelKey> bindings;
+ vector<Glib::RefPtr<Gtk::Action> > actions;
- ActionManager::get_all_actions (names, paths, tooltips, keys, bindings);
+ Gtkmm2ext::ActionMap::get_all_actions (paths, labels, tooltips, keys, actions);
- vector<string>::iterator n;
vector<string>::iterator k;
vector<string>::iterator p;
- for (n = names.begin(), k = keys.begin(), p = paths.begin(); n != names.end(); ++n, ++k, ++p) {
- cout << "Action: '" << (*n) << "' bound to '" << (*k) << "' Path: '" << (*p) << "'" << endl;
+
+ for (p = paths.begin(), k = keys.begin(); p != paths.end(); ++k, ++p) {
+
+ if ((*k).empty()) {
+ cout << *p << endl;
+ } else {
+ cout << *p << " => " << *k << endl;
+ }
}
halt_connection.disconnect ();
/* set default clock modes */
- if (Profile->get_sae()) {
- primary_clock->set_mode (AudioClock::BBT);
- secondary_clock->set_mode (AudioClock::MinSec);
- } else {
- primary_clock->set_mode (AudioClock::Timecode);
- secondary_clock->set_mode (AudioClock::BBT);
- }
+ primary_clock->set_mode (AudioClock::Timecode);
+ secondary_clock->set_mode (AudioClock::BBT);
/* 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;
+ delete main_window_visibility;
FastMeter::flush_pattern_cache ();
PixFader::flush_pattern_cache ();
}
void
ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
{
- const XMLProperty* prop;
+ XMLProperty const * prop;
if ((prop = node.property ("roll")) != 0) {
roll_controllable->set_id (prop->value());
#endif
}
+static bool
+_hide_splash (gpointer arg)
+{
+ ((ARDOUR_UI*)arg)->hide_splash();
+ return false;
+}
+
int
ARDOUR_UI::starting ()
{
_status_bar_visibility.update ();
BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
+
+ if (splash && splash->is_visible()) {
+ // in 1 second, hide the splash screen
+ Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
+ }
+
+ /* all other dialogs are created conditionally */
+
return 0;
}
ARDOUR_UI::count_recenabled_streams (Route& route)
{
Track* track = dynamic_cast<Track*>(&route);
- if (track && track->record_enabled()) {
+ if (track && track->rec_enable_control()->get_value()) {
rec_enabled_streams += track->n_inputs().n_total();
}
}
can_return = false;
}
+ if (splash && splash->is_visible()) {
+ // in 1 second, hide the splash screen
+ Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
+ }
}
bool
{
if (!AudioEngine::instance()->connected()) {
MessageDialog msg (parent, string_compose (
- _("%1 is not connected to any audio backend.\n"
- "You cannot open or close sessions in this condition"),
+ _("%1 is not connected to any audio backend.\n"
+ "You cannot open or close sessions in this condition"),
PROGRAM_NAME));
pop_back_splash (msg);
msg.run ();
void
ARDOUR_UI::open_session ()
{
- if (!check_audioengine(*editor)) {
+ if (!check_audioengine (_main_window)) {
return;
}
}
}
+void
+ARDOUR_UI::session_add_vca (const string& name_template, uint32_t n)
+{
+ if (!_session) {
+ return;
+ }
+
+ _session->vca_manager().create_vca (n, name_template);
+}
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,
+ Plugin::PresetRecord* pset,
+ ARDOUR::PresentationInfo::order_t order)
{
list<boost::shared_ptr<MidiTrack> > tracks;
}
try {
- tracks = _session->new_midi_track (input, output, instrument, ARDOUR::Normal, route_group, how_many, name_template);
+ tracks = _session->new_midi_track (input, output, instrument, pset, route_group, how_many, name_template, order, ARDOUR::Normal);
if (tracks.size() != how_many) {
error << string_compose(P_("could not create %1 new mixed track", "could not create %1 new mixed tracks", how_many), how_many) << endmsg;
}
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,
+ Plugin::PresetRecord* pset,
+ ARDOUR::PresentationInfo::order_t order)
+{
+ 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, pset, PresentationInfo::MidiBus, order);
+ 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,
+ Plugin::PresetRecord* pset,
+ ARDOUR::PresentationInfo::order_t order)
{
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, pset, order);
+ } else {
+ session_add_midi_bus (route_group, how_many, name_template, strict_io, instrument, pset, order);
}
}
ARDOUR::TrackMode mode,
RouteGroup* route_group,
uint32_t how_many,
- string const & name_template
- )
+ string const & name_template,
+ bool strict_io,
+ ARDOUR::PresentationInfo::order_t order)
{
list<boost::shared_ptr<AudioTrack> > tracks;
RouteList routes;
try {
if (track) {
- tracks = _session->new_audio_track (input_channels, output_channels, mode, route_group, how_many, name_template);
+ tracks = _session->new_audio_track (input_channels, output_channels, route_group, how_many, name_template, order, mode);
if (tracks.size() != how_many) {
error << string_compose (P_("could not create %1 new audio track", "could not create %1 new audio tracks", how_many), how_many)
} else {
- routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template);
+ routes = _session->new_audio_route (input_channels, output_channels, route_group, how_many, name_template, PresentationInfo::AudioBus, order);
if (routes.size() != how_many) {
error << string_compose (P_("could not create %1 new audio bus", "could not create %1 new audio busses", how_many), how_many)
}
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
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*r);
assert (t);
- if (t->record_enabled()) {
+ if (t->rec_enable_control()->get_value()) {
none_record_enabled = false;
break;
}
}
if (none_record_enabled) {
- _session->set_record_enabled (rl, true, Session::rt_cleanup);
+ _session->set_controls (route_list_to_control_list (rl, &Stripable::rec_enable_control), 1.0, Controllable::NoGroup);
}
return none_record_enabled;
if (affect_transport) {
if (rolling) {
_session->request_stop (with_abort, true);
- } else {
+
+ } else if (!with_abort) { /* with_abort == true means the
+ * command was intended to stop
+ * transport, not start.
+ */
+
/* the only external sync condition we can be in here
* would be Engine (JACK) sync, in which case we still
* want to do this.
}
void
-ARDOUR_UI::toggle_record_enable (uint32_t rid)
+ARDOUR_UI::toggle_record_enable (uint16_t rid)
{
if (!_session) {
return;
boost::shared_ptr<Route> r;
- if ((r = _session->route_by_remote_id (rid)) != 0) {
+ if ((r = _session->get_remote_nth_route (rid)) != 0) {
boost::shared_ptr<Track> t;
if ((t = boost::dynamic_pointer_cast<Track>(r)) != 0) {
- t->set_record_enabled (!t->record_enabled(), Controllable::UseGroup);
+ t->rec_enable_control()->set_value (!t->rec_enable_control()->get_value(), Controllable::UseGroup);
}
}
}
prompter.set_name ("Prompter");
prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
if (switch_to_it) {
- prompter.set_title (_("Save as..."));
+ prompter.set_title (_("Snapshot and switch"));
prompter.set_prompt (_("New session name"));
} else {
prompter.set_title (_("Take Snapshot"));
{
ArdourPrompter prompter (true);
- if (!check_audioengine(*editor)) {
+ if (!check_audioengine (_main_window)) {
return;
}
{
BusProfile bus_profile;
- if (nsm || Profile->get_sae()) {
+ if (nsm) {
bus_profile.master_out_channels = 2;
bus_profile.input_ac = AutoConnectPhysical;
if (get_session_parameters (true, false)) {
exit (1);
}
-
- goto_editor_window ();
}
}
void
ARDOUR_UI::close_session()
{
- if (!check_audioengine(*editor)) {
+ if (!check_audioengine (_main_window)) {
return;
}
if (get_session_parameters (true, false)) {
exit (1);
}
+ if (splash && splash->is_visible()) {
+ // in 1 second, hide the splash screen
+ Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
+ }
}
/** @param snap_name Snapshot name (without .ardour suffix).
}
}
-void
-ARDOUR_UI::setup_order_hint (AddRouteDialog::InsertAt place)
+PresentationInfo::order_t
+ARDOUR_UI::translate_order (AddRouteDialog::InsertAt place)
{
- uint32_t order_hint = UINT32_MAX;
-
if (editor->get_selection().tracks.empty()) {
- return;
+ return PresentationInfo::max_order;
}
+ PresentationInfo::order_t order_hint = PresentationInfo::max_order;
+
/*
we want the new routes to have their order keys set starting from
the highest order key in the selection + 1 (if available).
if (place == AddRouteDialog::AfterSelection) {
RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
if (rtav) {
- order_hint = rtav->route()->order_key();
+ order_hint = rtav->route()->presentation_info().order();
order_hint++;
}
} else if (place == AddRouteDialog::BeforeSelection) {
RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
if (rtav) {
- order_hint = rtav->route()->order_key();
+ order_hint = rtav->route()->presentation_info().order();
}
} else if (place == AddRouteDialog::First) {
order_hint = 0;
} else {
- /* leave order_hint at UINT32_MAX */
- }
-
- if (order_hint == UINT32_MAX) {
- /** AddRouteDialog::Last or selection with first/last not a RouteTimeAxisView
- * not setting an order hint will place new routes last.
- */
- return;
+ /* leave order_hint at max_order */
}
- _session->set_order_hint (order_hint);
-
- /* create a gap in the existing route order keys to accomodate new routes.*/
- boost::shared_ptr <RouteList> rd = _session->get_routes();
- for (RouteList::iterator ri = rd->begin(); ri != rd->end(); ++ri) {
- boost::shared_ptr<Route> rt (*ri);
-
- if (rt->is_monitor()) {
- continue;
- }
-
- if (rt->order_key () >= order_hint) {
- rt->set_order_key (rt->order_key () + add_route_dialog->count());
- }
- }
+ return order_hint;
}
void
}
void
-ARDOUR_UI::add_route (Gtk::Window* /* ignored */)
+ARDOUR_UI::add_route ()
{
- int count;
+ if (!add_route_dialog.get (false)) {
+ add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_finished));
+ }
if (!_session) {
return;
return;
}
- ResponseType r = (ResponseType) add_route_dialog->run ();
+ add_route_dialog->set_position (WIN_POS_MOUSE);
+ add_route_dialog->present();
+}
+
+void
+ARDOUR_UI::add_route_dialog_finished (int r)
+{
+ int count;
add_route_dialog->hide();
return;
}
- setup_order_hint(add_route_dialog->insert_at());
-
+ PresentationInfo::order_t order = translate_order (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, order);
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, 0, order);
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, 0, order);
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, order);
+ break;
+ case AddRouteDialog::MidiBus:
+ session_add_midi_bus (route_group, count, name_template, strict_io, instrument, 0, order);
+ break;
+ case AddRouteDialog::VCAMaster:
+ session_add_vca (name_template, count);
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 1;
}
+void
+ARDOUR_UI::sr_mismatch_message (framecnt_t desired, framecnt_t actual)
+{
+ MessageDialog msg (string_compose (_("\
+This session was created with a sample rate of %1 Hz, but\n\
+%2 is currently running at %3 Hz.\n\
+Audio will be recorded and played at the wrong sample rate.\n\
+Re-Configure the Audio Engine in\n\
+Menu > Window > Audio/Midi Setup"),
+ desired, PROGRAM_NAME, actual),
+ true,
+ Gtk::MESSAGE_WARNING);
+ msg.run ();
+}
+
void
ARDOUR_UI::use_config ()
{
Profile->set_small_screen ();
}
- if (g_getenv ("ARDOUR_SAE")) {
- Profile->set_sae ();
- Profile->set_single_package ();
- }
-
if (g_getenv ("TRX")) {
Profile->set_trx ();
}
MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
"%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
- "From now on, use the -2000 version with older versions of %3"),
+ "From now on, use the backup copy with older versions of %3"),
xml_path, backup_path, PROGRAM_NAME,
start_big, end_big,
start_mono, end_mono), true);
audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
audio_midi_setup->set_position (WIN_POS_CENTER);
- int response;
+ if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
+ audio_midi_setup->try_autostart ();
+ if (ARDOUR::AudioEngine::instance()->running()) {
+ return 0;
+ }
+ }
while (true) {
- response = audio_midi_setup->run();
+ int response = audio_midi_setup->run();
switch (response) {
case Gtk::RESPONSE_OK:
if (!AudioEngine::instance()->running()) {
if (window_icons.empty()) {
Glib::RefPtr<Gdk::Pixbuf> icon;
- if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
+ if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px")) != 0) {
window_icons.push_back (icon);
}
- if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
+ if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px")) != 0) {
window_icons.push_back (icon);
}
- if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
+ if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px")) != 0) {
window_icons.push_back (icon);
}
- if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
+ if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px")) != 0) {
window_icons.push_back (icon);
}
}
if (!window_icons.empty()) {
window.set_default_icon_list (window_icons);
}
-
+
Gtkmm2ext::WindowTitle title (Glib::get_application_name());
if (!name.empty()) {
window.set_flags (CAN_FOCUS);
window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
+ /* This is a hack to ensure that GTK-accelerators continue to
+ * work. Once we switch over to entirely native bindings, this will be
+ * unnecessary and should be removed
+ */
window.add_accel_group (ActionManager::ui_manager->get_accel_group());
window.signal_configure_event().connect (sigc::mem_fun (*this, &ARDOUR_UI::configure_handler));
/* until we get ardour bindings working, we are not handling key
* releases yet.
*/
-
+
if (ev->type != GDK_KEY_PRESS) {
return false;
}
-
+
if (event_window == &_main_window) {
window = event_window;
-
+
/* find current tab contents */
Gtk::Widget* w = _tabs.get_nth_page (_tabs.get_current_page());
if (w) {
bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(w->get_data ("ardour-bindings"));
- } else {
- bindings = &_global_bindings;
}
- } else if (event_window != 0) {
+ DEBUG_TRACE (DEBUG::Accelerators, string_compose ("main window key event, bindings = %1, global = %2\n", bindings, &global_bindings));
+
+ } else {
window = event_window;
-
+
/* see if window uses ardour binding system */
bindings = reinterpret_cast<Gtkmm2ext::Bindings*>(window->get_data ("ardour-bindings"));
-
- }
+ }
/* An empty binding set is treated as if it doesn't exist */
-
+
if (bindings && bindings->empty()) {
bindings = 0;
}
-
+
return key_press_focus_accelerator_handler (*window, ev, bindings);
}
-
+
+static Gtkmm2ext::Bindings*
+get_bindings_from_widget_heirarchy (GtkWidget* w)
+{
+ void* p = NULL;
+
+ 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 */
if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
/* A particular kind of focusable widget currently has keyboard
* focus. All unmodified key events should go to that widget
- * first and not be used as an accelerator by default
+ * first and not be used as an accelerator by default
*/
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 [title = %9] 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"),
+ window.get_title()));
/* This exists to allow us to override the way GTK handles
key events. The normal sequence is:
all "normal text" accelerators.
*/
-
+
if (!special_handling_of_unmodified_accelerators || (ev->state & mask)) {
-
+
/* no special handling or there are modifiers in effect: accelerate first */
DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
ev->send_event, ev->time, ev->length, ev->string, ev->hardware_keycode, ev->group, gdk_keyval_name (ev->keyval)));
DEBUG_TRACE (DEBUG::Accelerators, "\tsending to window\n");
+ KeyboardKey k (ev->state, ev->keyval);
if (bindings) {
- DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
- KeyboardKey k (ev->state, ev->keyval);
-
+ 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");
return true;
}
}
- if (try_gtk_accel_binding (win, ev, !special_handling_of_unmodified_accelerators, modifier)) {
+ DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
+
+ if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
return true;
}
-
DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
-
+
if (gtk_window_propagate_key_event (win, ev)) {
DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
return true;
}
} else {
-
+
/* no modifiers, propagate first */
-
+
DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate, then activate\n");
-
+
if (gtk_window_propagate_key_event (win, ev)) {
DEBUG_TRACE (DEBUG::Accelerators, "\thandled by propagate\n");
return true;
}
DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
-
+ KeyboardKey k (ev->state, ev->keyval);
+
if (bindings) {
-
+
DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
- KeyboardKey k (ev->state, ev->keyval);
-
+
+
if (bindings->activate (k, Bindings::Press)) {
DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
return true;
}
-
- }
-
- DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try GTK bindings\n");
-
- if (try_gtk_accel_binding (win, ev, !special_handling_of_unmodified_accelerators, modifier)) {
+
+ }
+
+ DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
+
+ if (global_bindings && global_bindings->activate (k, Bindings::Press)) {
DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
return true;
}
}
- DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
-
- KeyboardKey k (ev->state, ev->keyval);
-
- if (_global_bindings.activate (k, Bindings::Press)) {
- DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
- return true;
- }
-
DEBUG_TRACE (DEBUG::Accelerators, "\tnot handled\n");
return true;
}
-bool
-ARDOUR_UI::try_gtk_accel_binding (GtkWindow* win, GdkEventKey* ev, bool translate, GdkModifierType modifier)
+void
+ARDOUR_UI::load_bindings ()
{
- uint32_t fakekey = ev->keyval;
-
- if (translate) {
-
- /* pretend that certain key events that GTK does not allow
- to be used as accelerators are actually something that
- it does allow. but only where there are no modifiers.
- */
+ if ((global_bindings = Bindings::get_bindings (X_("Global"), global_actions)) == 0) {
+ error << _("Global keybindings are missing") << endmsg;
+ }
+}
- if (Gtkmm2ext::possibly_translate_keyval_to_make_legal_accelerator (fakekey)) {
- DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tactivate (was %1 now %2) without special hanlding of unmodified accels, modifier was %3\n",
- ev->keyval, fakekey, show_gdk_event_state (modifier)));
+void
+ARDOUR_UI::cancel_solo ()
+{
+ if (_session) {
+ if (_session) {
+ _session->set_controls (route_list_to_control_list (_session->get_routes(), &Stripable::solo_control), 0.0, Controllable::NoGroup);
}
+ _session->clear_all_solo_state (_session->get_routes()); // safeguard, ideally this won't do anything, check the log-window
}
-
- if (gtk_accel_groups_activate (G_OBJECT(win), fakekey, modifier)) {
- DEBUG_TRACE (DEBUG::Accelerators, "\tGTK accel group activated\n");
- return true;
- }
-
- return false;
}