#include <glib.h>
#include "pbd/gstdio_compat.h"
-#include <gtkmm/messagedialog.h>
#include <gtkmm/accelmap.h>
+#include <gtkmm/messagedialog.h>
#include <gtkmm/stock.h>
+#include <gtkmm/uimanager.h>
#include "pbd/error.h"
#include "pbd/basename.h"
#include "pbd/compose.h"
#include "pbd/convert.h"
#include "pbd/failed_constructor.h"
+#include "pbd/file_archive.h"
#include "pbd/enumwriter.h"
#include "pbd/memento_command.h"
#include "pbd/openuri.h"
#include "pbd/stl_delete.h"
+#include "pbd/types_convert.h"
+#include "pbd/unwind.h"
#include "pbd/file_utils.h"
#include "pbd/localtime_r.h"
#include "pbd/pthread_utils.h"
#include "pbd/replace_all.h"
+#include "pbd/scoped_file_descriptor.h"
#include "pbd/xml++.h"
#include "gtkmm2ext/application.h"
#include "gtkmm2ext/bindings.h"
#include "gtkmm2ext/gtk_ui.h"
#include "gtkmm2ext/utils.h"
-#include "gtkmm2ext/click_box.h"
-#include "gtkmm2ext/fastmeter.h"
-#include "gtkmm2ext/popup.h"
#include "gtkmm2ext/window_title.h"
+#include "widgets/fastmeter.h"
+#include "widgets/prompter.h"
+
#include "ardour/ardour.h"
#include "ardour/audio_backend.h"
#include "ardour/audio_track.h"
#include "ardour/profile.h"
#include "ardour/recent_sessions.h"
#include "ardour/record_enable_control.h"
+#include "ardour/revision.h"
#include "ardour/session_directory.h"
#include "ardour/session_route.h"
#include "ardour/session_state_utils.h"
#include "about.h"
#include "editing.h"
+#include "enums_convert.h"
#include "actions.h"
#include "add_route_dialog.h"
#include "ambiguous_file_dialog.h"
#include "global_port_matrix.h"
#include "gui_object.h"
#include "gui_thread.h"
+#include "idleometer.h"
#include "keyboard.h"
#include "keyeditor.h"
#include "location_ui.h"
#include "missing_plugin_dialog.h"
#include "mixer_ui.h"
#include "meterbridge.h"
+#include "meter_patterns.h"
#include "mouse_cursors.h"
#include "nsm.h"
#include "opts.h"
#include "pingback.h"
#include "processor_box.h"
-#include "prompter.h"
#include "public_editor.h"
#include "rc_option_editor.h"
#include "route_time_axis.h"
#include "route_params_ui.h"
#include "save_as_dialog.h"
#include "script_selector.h"
+#include "session_archive_dialog.h"
#include "session_dialog.h"
#include "session_metadata_dialog.h"
#include "session_option_editor.h"
-#include "shuttle_control.h"
#include "speaker_dialog.h"
#include "splash.h"
#include "startup.h"
-#include "theme_manager.h"
+#include "template_dialog.h"
#include "time_axis_view_item.h"
+#include "time_info_box.h"
#include "timers.h"
#include "utils.h"
+#include "utils_videotl.h"
#include "video_server_dialog.h"
#include "add_video_dialog.h"
#include "transcode_video_dialog.h"
using namespace ARDOUR_UI_UTILS;
using namespace PBD;
using namespace Gtkmm2ext;
+using namespace ArdourWidgets;
using namespace Gtk;
using namespace std;
using namespace Editing;
ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
sigc::signal<void, framepos_t, bool, framepos_t> ARDOUR_UI::Clock;
-sigc::signal<void> ARDOUR_UI::CloseAllDialogs;
+sigc::signal<void> ARDOUR_UI::CloseAllDialogs;
static bool
ask_about_configuration_copy (string const & old_dir, string const & new_dir, int version)
Gtk::MESSAGE_INFO,
Gtk::BUTTONS_YES_NO,
true /* modal, though it hardly matters since it is the only window */
- );
+ );
msg.set_default_response (Gtk::RESPONSE_YES);
msg.show_all ();
static void
libxml_generic_error_func (void* /* parsing_context*/,
- const char* msg,
- ...)
+ const char* msg,
+ ...)
{
va_list ap;
char buf[2048];
ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
: Gtkmm2ext::UI (PROGRAM_NAME, X_("gui"), argcp, argvp)
, session_loaded (false)
+ , session_load_in_progress (false)
, gui_object_state (new GUIObjectState)
, primary_clock (new MainClock (X_("primary"), X_("transport"), true ))
, secondary_clock (new MainClock (X_("secondary"), X_("secondary"), false))
, _mixer_on_top (false)
, _initial_verbose_plugin_scan (false)
, first_time_engine_run (true)
+ , secondary_clock_spacer (0)
, roll_controllable (new TransportControllable ("transport roll", *this, TransportControllable::Roll))
, stop_controllable (new TransportControllable ("transport stop", *this, TransportControllable::Stop))
, goto_start_controllable (new TransportControllable ("transport goto start", *this, TransportControllable::GotoStart))
, auto_loop_controllable (new TransportControllable ("transport auto loop", *this, TransportControllable::AutoLoop))
, play_selection_controllable (new TransportControllable ("transport play selection", *this, TransportControllable::PlaySelection))
, rec_controllable (new TransportControllable ("transport rec-enable", *this, TransportControllable::RecordEnable))
+ , auto_input_button (ArdourButton::led_default_elements)
+ , time_info_box (0)
, auto_return_button (ArdourButton::led_default_elements)
, follow_edits_button (ArdourButton::led_default_elements)
- , auto_input_button (ArdourButton::led_default_elements)
, auditioning_alert_button (_("Audition"))
, solo_alert_button (_("Solo"))
, feedback_alert_button (_("Feedback"))
, error_alert_button ( ArdourButton::just_led_default_elements )
- , editor_meter(0)
, editor_meter_peak_display()
+ , editor_meter(0)
+ , _suspend_editor_meter_callbacks (false)
, _numpad_locate_happening (false)
, _session_is_new (false)
, last_key_press_time (0)
, 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"))
+ , idleometer (X_("idle-o-meter"), _("Idle'o'Meter"))
, 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))
, 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))
+ , key_editor (X_("key-editor"), _("Keyboard Shortcuts"), boost::bind (&ARDOUR_UI::create_key_editor, this))
, video_server_process (0)
, splash (0)
, have_configure_timeout (false)
UIConfiguration::instance().post_gui_init ();
if (ARDOUR::handle_old_configuration_files (boost::bind (ask_about_configuration_copy, _1, _2, _3))) {
+ {
+ /* "touch" the been-here-before path now that config has been migrated */
+ PBD::ScopedFileDescriptor fout (g_open (been_here_before_path ().c_str(), O_CREAT|O_TRUNC|O_RDWR, 0666));
+ }
MessageDialog msg (string_compose (_("Your configuration files were copied. You can now restart %1."), PROGRAM_NAME), true);
msg.run ();
/* configuration was modified, exit immediately */
TimeAxisViewItem::set_constant_heights ();
- /* Set this up so that our window proxies can register actions */
+ /* Set this up so that our window proxies can register actions */
ActionManager::init ();
midi_port_matrix.set_state (*ui_xml, 0);
export_video_dialog.set_state (*ui_xml, 0);
lua_script_window.set_state (*ui_xml, 0);
+ idleometer.set_state (*ui_xml, 0);
}
/* Separate windows */
WM::Manager::instance().register_window (&big_clock_window);
WM::Manager::instance().register_window (&audio_port_matrix);
WM::Manager::instance().register_window (&midi_port_matrix);
+ WM::Manager::instance().register_window (&idleometer);
/* do not retain position for add route dialog */
add_route_dialog.set_state_mask (WindowProxy::Size);
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\
+ 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\
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.get_vbox()->set_border_width (12);
+ d.get_vbox()->pack_start (*label, false, false, 12);
+ d.get_vbox()->show_all ();
- d.run ();
+ d.run ();
}
GlobalPortMatrixWindow*
*/
if (ARDOUR_COMMAND_LINE::show_key_actions) {
+ stringstream sstr;
+ Bindings::save_all_bindings_as_html (sstr);
+
+ if (sstr.str().empty()) {
+ return;
+ }
+ gchar* file_name;
+ GError *err = NULL;
+ gint fd;
+
+ if ((fd = g_file_open_tmp ("akprintXXXXXX.html", &file_name, &err)) < 0) {
+ if (err) {
+ error << string_compose (_("Could not open temporary file to print bindings (%1)"), err->message) << endmsg;
+ g_error_free (err);
+ }
+ return;
+ }
+
+#ifdef PLATFORM_WINDOWS
+ ::close (fd);
+#endif
+
+ err = NULL;
+
+ if (!g_file_set_contents (file_name, sstr.str().c_str(), sstr.str().size(), &err)) {
+#ifndef PLATFORM_WINDOWS
+ ::close (fd);
+#endif
+ g_unlink (file_name);
+ if (err) {
+ error << string_compose (_("Could not save bindings to file (%1)"), err->message) << endmsg;
+ g_error_free (err);
+ }
+ return;
+ }
+
+#ifndef PLATFORM_WINDOWS
+ ::close (fd);
+#endif
+
+ PBD::open_uri (string_compose ("file:///%1", file_name));
+
+ halt_connection.disconnect ();
+ AudioEngine::instance()->stop ();
+ exit (0);
+
+ }
+
+ if (ARDOUR_COMMAND_LINE::show_actions) {
vector<string> paths;
vector<string> tooltips;
vector<string> keys;
vector<Glib::RefPtr<Gtk::Action> > actions;
+ string ver_in = revision;
+ string ver = ver_in.substr(0, ver_in.find("-"));
+
+ stringstream output;
+ output << "\n<h2>Menu actions</h2>" << endl;
+ output << "<p>\n Every single menu item in " << PROGRAM_NAME << "'s GUI is accessible by control" << endl;
+ output << " surfaces or scripts.\n</p>\n" << endl;
+ output << "<p>\n The list below shows all available values of <em>action-name</em> as of" << endl;
+ output << " " << PROGRAM_NAME << " " << ver << ". You can get the current list at any" << endl;
+ output << " time by running " << PROGRAM_NAME << " with the -A flag.\n</p>\n" << endl;
+ output << "<table class=\"dl\">\n <thead>" << endl;
+ output << " <tr><th>Action Name</th><th>Menu Name</th></tr>" << endl;
+ output << " </thead>\n <tbody>" << endl;
Gtkmm2ext::ActionMap::get_all_actions (paths, labels, tooltips, keys, actions);
- vector<string>::iterator k;
vector<string>::iterator p;
+ vector<string>::iterator l;
+
+ for (p = paths.begin(), l = labels.begin(); p != paths.end(); ++p, ++l) {
+ output << " <tr><th><kbd class=\"osc\">" << (*p).substr (9, string::npos);
+ output << "</kbd></th><td>" << *l << "</td></tr>" << endl;
+ }
+ output << " </tbody>\n </table>" << endl;
+
+ // output this mess to a browser for easiest X-platform use
+ // it is not pretty HTML, but it works and it's main purpose
+ // is to create raw html to fit in Ardour's manual with no editing
+ gchar* file_name;
+ GError *err = NULL;
+ gint fd;
+
+ if ((fd = g_file_open_tmp ("akprintXXXXXX.html", &file_name, &err)) < 0) {
+ if (err) {
+ error << string_compose (_("Could not open temporary file to print bindings (%1)"), err->message) << endmsg;
+ g_error_free (err);
+ }
+ return;
+ }
+
+#ifdef PLATFORM_WINDOWS
+ ::close (fd);
+#endif
- for (p = paths.begin(), k = keys.begin(); p != paths.end(); ++k, ++p) {
+ err = NULL;
- if ((*k).empty()) {
- cout << *p << endl;
- } else {
- cout << *p << " => " << *k << endl;
+ if (!g_file_set_contents (file_name, output.str().c_str(), output.str().size(), &err)) {
+#ifndef PLATFORM_WINDOWS
+ ::close (fd);
+#endif
+ g_unlink (file_name);
+ if (err) {
+ error << string_compose (_("Could not save bindings to file (%1)"), err->message) << endmsg;
+ g_error_free (err);
}
+ return;
}
+#ifndef PLATFORM_WINDOWS
+ ::close (fd);
+#endif
+
+ PBD::open_uri (string_compose ("file:///%1", file_name));
+
halt_connection.disconnect ();
AudioEngine::instance()->stop ();
exit (0);
delete primary_clock; primary_clock = 0;
delete secondary_clock; secondary_clock = 0;
delete _process_thread; _process_thread = 0;
+ delete time_info_box; time_info_box = 0;
delete meterbridge; meterbridge = 0;
delete luawindow; luawindow = 0;
delete editor; editor = 0;
delete mixer; mixer = 0;
+ delete rc_option_editor; rc_option_editor = 0; // failed to wrap object warning
delete nsm; nsm = 0;
delete gui_object_state; gui_object_state = 0;
delete main_window_visibility;
FastMeter::flush_pattern_cache ();
- PixFader::flush_pattern_cache ();
+ ArdourFader::flush_pattern_cache ();
}
#ifndef NDEBUG
void
ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
{
- XMLProperty const * prop;
+ std::string str;
- if ((prop = node.property ("roll")) != 0) {
- roll_controllable->set_id (prop->value());
+ if (node.get_property ("roll", str)){
+ roll_controllable->set_id (str);
}
- if ((prop = node.property ("stop")) != 0) {
- stop_controllable->set_id (prop->value());
+ if (node.get_property ("stop", str)) {
+ stop_controllable->set_id (str);
}
- if ((prop = node.property ("goto-start")) != 0) {
- goto_start_controllable->set_id (prop->value());
+ if (node.get_property ("goto-start", str)) {
+ goto_start_controllable->set_id (str);
}
- if ((prop = node.property ("goto-end")) != 0) {
- goto_end_controllable->set_id (prop->value());
+ if (node.get_property ("goto-end", str)) {
+ goto_end_controllable->set_id (str);
}
- if ((prop = node.property ("auto-loop")) != 0) {
- auto_loop_controllable->set_id (prop->value());
+ if (node.get_property ("auto-loop", str)) {
+ auto_loop_controllable->set_id (str);
}
- if ((prop = node.property ("play-selection")) != 0) {
- play_selection_controllable->set_id (prop->value());
+ if (node.get_property ("play-selection", str)) {
+ play_selection_controllable->set_id (str);
}
- if ((prop = node.property ("rec")) != 0) {
- rec_controllable->set_id (prop->value());
+ if (node.get_property ("rec", str)) {
+ rec_controllable->set_id (str);
}
- if ((prop = node.property ("shuttle")) != 0) {
- shuttle_box->controllable()->set_id (prop->value());
+ if (node.get_property ("shuttle", str)) {
+ shuttle_box.controllable()->set_id (str);
}
}
ARDOUR_UI::get_transport_controllable_state ()
{
XMLNode* node = new XMLNode(X_("TransportControllables"));
- char buf[64];
- roll_controllable->id().print (buf, sizeof (buf));
- node->add_property (X_("roll"), buf);
- stop_controllable->id().print (buf, sizeof (buf));
- node->add_property (X_("stop"), buf);
- goto_start_controllable->id().print (buf, sizeof (buf));
- node->add_property (X_("goto_start"), buf);
- goto_end_controllable->id().print (buf, sizeof (buf));
- node->add_property (X_("goto_end"), buf);
- auto_loop_controllable->id().print (buf, sizeof (buf));
- node->add_property (X_("auto_loop"), buf);
- play_selection_controllable->id().print (buf, sizeof (buf));
- node->add_property (X_("play_selection"), buf);
- rec_controllable->id().print (buf, sizeof (buf));
- node->add_property (X_("rec"), buf);
- shuttle_box->controllable()->id().print (buf, sizeof (buf));
- node->add_property (X_("shuttle"), buf);
+ node->set_property (X_("roll"), roll_controllable->id());
+ node->set_property (X_("stop"), stop_controllable->id());
+ node->set_property (X_("goto-start"), goto_start_controllable->id());
+ node->set_property (X_("goto-end"), goto_end_controllable->id());
+ node->set_property (X_("auto-loop"), auto_loop_controllable->id());
+ node->set_property (X_("play-selection"), play_selection_controllable->id());
+ node->set_property (X_("rec"), rec_controllable->id());
+ node->set_property (X_("shuttle"), shuttle_box.controllable()->id());
return *node;
}
}
}
+ // TODO: maybe IFF brand_new_user
+ if (ARDOUR::Profile->get_mixbus () && Config->get_copy_demo_sessions ()) {
+ std::string dspd (Config->get_default_session_parent_dir());
+ Searchpath ds (ARDOUR::ardour_data_search_path());
+ ds.add_subdirectory_to_paths ("sessions");
+ vector<string> demos;
+ find_files_matching_pattern (demos, ds, "*.tar.xz");
+
+ ARDOUR::RecentSessions rs;
+ ARDOUR::read_recent_sessions (rs);
+
+ for (vector<string>::iterator i = demos.begin(); i != demos.end (); ++i) {
+ /* "demo-session" must be inside "demo-session.tar.xz"
+ * strip ".tar.xz"
+ */
+ std::string name = basename_nosuffix (basename_nosuffix (*i));
+ std::string path = Glib::build_filename (dspd, name);
+ /* skip if session-dir already exists */
+ if (Glib::file_test(path.c_str(), Glib::FILE_TEST_IS_DIR)) {
+ continue;
+ }
+ /* skip sessions that are already in 'recent'.
+ * eg. a new user changed <session-default-dir> shorly after installation
+ */
+ for (ARDOUR::RecentSessions::iterator r = rs.begin(); r != rs.end(); ++r) {
+ if ((*r).first == name) {
+ continue;
+ }
+ }
+ try {
+ PBD::FileArchive ar (*i);
+ if (0 == ar.inflate (dspd)) {
+ store_recent_sessions (name, path);
+ info << string_compose (_("Copied Demo Session %1."), name) << endmsg;
+ }
+ } catch (...) {}
+ }
+ }
+
#ifdef NO_PLUGIN_STATE
ARDOUR::RecentSessions rs;
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;
*/
save_ardour_state ();
+ if (key_editor.get (false)) {
+ key_editor->disconnect ();
+ }
+
close_all_dialogs ();
if (_session) {
{
// august 2007: actual update frequency: 25Hz (40ms), not 100Hz
- if (editor_meter && UIConfiguration::instance().get_show_editor_meter()) {
+ if (editor_meter && UIConfiguration::instance().get_show_editor_meter() && editor_meter_peak_display.is_mapped ()) {
float mpeak = editor_meter->update_meters();
if (mpeak > editor_meter_max_peak) {
if (mpeak >= UIConfiguration::instance().get_meter_peak()) {
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"),
- PROGRAM_NAME));
+ _("%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 ();
return false;
session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
open_session_selector.add_filter (session_filter);
+
+ FileFilter archive_filter;
+ archive_filter.add_pattern (X_("*.tar.xz"));
+ archive_filter.set_name (_("Session Archives"));
+
+ open_session_selector.add_filter (archive_filter);
+
open_session_selector.set_filter (session_filter);
int response = open_session_selector.run();
bool isnew;
if (session_path.length() > 0) {
- if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
+ int rv = ARDOUR::inflate_session (session_path,
+ Config->get_default_session_parent_dir(), path, name);
+ if (rv == 0) {
+ _session_is_new = false;
+ load_session (path, name);
+ }
+ else if (rv < 0) {
+ MessageDialog msg (_main_window,
+ string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
+ msg.run ();
+ }
+ else if (ARDOUR::find_session (session_path, path, name, isnew) == 0) {
_session_is_new = isnew;
load_session (path, name);
}
Plugin::PresetRecord* pset,
ARDOUR::PresentationInfo::order_t order)
{
- list<boost::shared_ptr<MidiTrack> > tracks;
-
if (_session == 0) {
warning << _("You cannot add a track without a session already loaded.") << endmsg;
return;
}
+ if (Profile->get_mixbus ()) {
+ strict_io = true;
+ }
+
try {
- tracks = _session->new_midi_track (input, output, instrument, pset, route_group, how_many, name_template, order, ARDOUR::Normal);
+ list<boost::shared_ptr<MidiTrack> > tracks;
+ tracks = _session->new_midi_track (input, output, strict_io, 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;
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
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 {
+ if (Profile->get_mixbus ()) {
+ strict_io = true;
+ }
- routes = _session->new_midi_route (route_group, how_many, name_template, instrument, pset, PresentationInfo::MidiBus, order);
+ try {
+ RouteList routes;
+ routes = _session->new_midi_route (route_group, how_many, name_template, strict_io, 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;
}
display_insufficient_ports_message ();
return;
}
-
- if (strict_io) {
- for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
- (*i)->set_strict_io (true);
- }
- }
}
void
editor->play_with_preroll ();
}
+void
+ARDOUR_UI::transport_rec_preroll ()
+{
+ if (!_session) {
+ return;
+ }
+ editor->rec_with_preroll ();
+}
+
+void
+ARDOUR_UI::transport_rec_count_in ()
+{
+ if (!_session) {
+ return;
+ }
+ editor->rec_with_count_in ();
+}
+
void
ARDOUR_UI::transport_rewind (int option)
{
play_selection_button.unset_active_state ();
roll_button.unset_active_state ();
stop_button.set_active_state (Gtkmm2ext::ExplicitActive);
+ layered_button.set_sensitive (false);
return;
}
- shuttle_box->map_transport_state ();
+ shuttle_box.map_transport_state ();
float sp = _session->transport_speed();
roll_button.set_active (true);
play_selection_button.set_active (true);
}
+ layered_button.set_sensitive (!_session->actively_recording ());
stop_button.set_active (false);
} else {
+ layered_button.set_sensitive (true);
stop_button.set_active (true);
roll_button.set_active (false);
play_selection_button.set_active (false);
ARDOUR_UI::blink_handler (bool blink_on)
{
transport_rec_enable_blink (blink_on);
- solo_blink (blink_on);
sync_blink (blink_on);
+
+ if (!UIConfiguration::instance().get_blink_alert_indicators()) {
+ blink_on = true;
+ }
+ error_blink (blink_on);
+ solo_blink (blink_on);
audition_blink (blink_on);
feedback_blink (blink_on);
- error_blink (blink_on);
}
void
return;
}
+ if (_session->dirty()) {
+ vector<string> actions;
+ actions.push_back (_("Abort save-as"));
+ actions.push_back (_("Don't save now, just save-as"));
+ actions.push_back (_("Save it first"));
+ switch (ask_about_saving_session(actions)) {
+ case -1:
+ return;
+ break;
+ case 1:
+ if (save_state_canfail ("")) {
+ MessageDialog msg (_main_window,
+ string_compose (_("\
+%1 was unable to save your session.\n\n\
+If you still wish to proceeed, please use the\n\n\
+\"Don't save now\" option."), PROGRAM_NAME));
+ pop_back_splash(msg);
+ msg.run ();
+ return;
+ }
+ // no break
+ case 0:
+ _session->remove_pending_capture_state ();
+ break;
+ }
+ }
+
if (!save_as_dialog) {
save_as_dialog = new SaveAsDialog;
}
*/
ArdourDialog progress_dialog (_("Save As"), true);
+ ScopedConnection c;
if (sa.include_media && sa.copy_media) {
- Gtk::Label label;
- Gtk::ProgressBar progress_bar;
+ Gtk::Label* label = manage (new Gtk::Label());
+ Gtk::ProgressBar* progress_bar = manage (new Gtk::ProgressBar ());
- progress_dialog.get_vbox()->pack_start (label);
- progress_dialog.get_vbox()->pack_start (progress_bar);
- label.show ();
- progress_bar.show ();
+ progress_dialog.get_vbox()->pack_start (*label);
+ progress_dialog.get_vbox()->pack_start (*progress_bar);
+ label->show ();
+ progress_bar->show ();
/* this signal will be emitted from within this, the calling thread,
* after every file is copied. It provides information on percentage
* copied so far, and the total number to copy.
*/
- ScopedConnection c;
-
- sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, &label, &progress_bar));
+ sa.Progress.connect_same_thread (c, boost::bind (&ARDOUR_UI::save_as_progress_update, this, _1, _2, _3, label, progress_bar));
progress_dialog.show_all ();
progress_dialog.present ();
msg.run ();
}
- if (!sa.include_media) {
+ /* the logic here may seem odd: why isn't the condition sa.switch_to ?
+ * the trick is this: if the new session was copy with media included,
+ * then Session::save_as() will have already done a neat trick to avoid
+ * us having to unload and load the new state. But if the media was not
+ * included, then this is required (it avoids us having to otherwise
+ * drop all references to media (sources).
+ */
+
+ if (!sa.include_media && sa.switch_to) {
unload_session (false);
load_session (sa.final_session_folder_name, sa.new_name);
}
}
+void
+ARDOUR_UI::archive_session ()
+{
+ if (!_session) {
+ return;
+ }
+
+ time_t n;
+ time (&n);
+ Glib::DateTime gdt (Glib::DateTime::create_now_local (n));
+
+ SessionArchiveDialog sad;
+ sad.set_name (_session->name() + gdt.format ("_%F_%H%M%S"));
+ int response = sad.run ();
+
+ if (response != Gtk::RESPONSE_OK) {
+ sad.hide ();
+ return;
+ }
+
+ if (_session->archive_session (sad.target_folder(), sad.name(), sad.encode_option (), sad.only_used_sources (), &sad)) {
+ MessageDialog msg (_("Session Archiving failed."));
+ msg.run ();
+ }
+}
+
void
ARDOUR_UI::quick_snapshot_session (bool switch_to_it)
{
time (&n);
localtime_r (&n, &local_time);
strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
+ if (switch_to_it && _session->dirty ()) {
+ save_state_canfail ("");
+ }
save_state (timebuf, switch_to_it);
}
bool
-ARDOUR_UI::process_snapshot_session_prompter (ArdourPrompter& prompter, bool switch_to_it)
+ARDOUR_UI::process_snapshot_session_prompter (Prompter& prompter, bool switch_to_it)
{
string snapname;
char illegal = Session::session_name_is_legal(snapname);
if (illegal) {
MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
- "snapshot names may not contain a '%1' character"), illegal));
+ "snapshot names may not contain a '%1' character"), illegal));
msg.run ();
return false;
}
void
ARDOUR_UI::snapshot_session (bool switch_to_it)
{
- ArdourPrompter prompter (true);
+ if (switch_to_it && _session->dirty()) {
+ vector<string> actions;
+ actions.push_back (_("Abort saving snapshot"));
+ actions.push_back (_("Don't save now, just snapshot"));
+ actions.push_back (_("Save it first"));
+ switch (ask_about_saving_session(actions)) {
+ case -1:
+ return;
+ break;
+ case 1:
+ if (save_state_canfail ("")) {
+ MessageDialog msg (_main_window,
+ string_compose (_("\
+%1 was unable to save your session.\n\n\
+If you still wish to proceeed, please use the\n\n\
+\"Don't save now\" option."), PROGRAM_NAME));
+ pop_back_splash(msg);
+ msg.run ();
+ return;
+ }
+ // no break
+ case 0:
+ _session->remove_pending_capture_state ();
+ break;
+ }
+ }
+ Prompter prompter (true);
prompter.set_name ("Prompter");
prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
if (switch_to_it) {
if (switch_to_it) {
prompter.set_initial_text (_session->snap_name());
} else {
- char timebuf[128];
- time_t n;
- struct tm local_time;
-
- time (&n);
- localtime_r (&n, &local_time);
- strftime (timebuf, sizeof(timebuf), "%FT%H.%M.%S", &local_time);
- prompter.set_initial_text (timebuf);
+ Glib::DateTime tm (g_date_time_new_now_local ());
+ prompter.set_initial_text (tm.format ("%FT%H.%M.%S"));
}
bool finished = false;
return;
}
- ArdourPrompter prompter (true);
+ Prompter prompter (true);
string name;
prompter.set_name ("Prompter");
if (illegal) {
MessageDialog msg (string_compose (_("To ensure compatibility with various systems\n"
- "session names may not contain a '%1' character"), illegal));
+ "session names may not contain a '%1' character"), illegal));
msg.run ();
goto again;
}
}
bool
-ARDOUR_UI::process_save_template_prompter (ArdourPrompter& prompter)
+ARDOUR_UI::process_save_template_prompter (Prompter& prompter)
{
string name;
void
ARDOUR_UI::save_template ()
{
- ArdourPrompter prompter (true);
+ Prompter prompter (true);
if (!check_audioengine (_main_window)) {
return;
}
}
+void ARDOUR_UI::manage_templates ()
+{
+ TemplateDialog td;
+ td.run();
+}
+
void
ARDOUR_UI::edit_metadata ()
{
BusProfile bus_profile;
if (nsm) {
-
bus_profile.master_out_channels = 2;
- bus_profile.input_ac = AutoConnectPhysical;
- bus_profile.output_ac = AutoConnectMaster;
- bus_profile.requested_physical_in = 0; // use all available
- bus_profile.requested_physical_out = 0; // use all available
-
} else {
-
/* get settings from advanced section of NSD */
-
- if (sd.create_master_bus()) {
- bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
- } else {
- bus_profile.master_out_channels = 0;
- }
-
- if (sd.connect_inputs()) {
- bus_profile.input_ac = AutoConnectPhysical;
- } else {
- bus_profile.input_ac = AutoConnectOption (0);
- }
-
- bus_profile.output_ac = AutoConnectOption (0);
-
- if (sd.connect_outputs ()) {
- if (sd.connect_outs_to_master()) {
- bus_profile.output_ac = AutoConnectMaster;
- } else if (sd.connect_outs_to_physical()) {
- bus_profile.output_ac = AutoConnectPhysical;
- }
- }
-
- bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count();
- bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count();
+ bus_profile.master_out_channels = (uint32_t) sd.master_channel_count();
}
- if (build_session (session_path, session_name, bus_profile)) {
+ // NULL profile: no master, no monitor
+ if (build_session (session_path, session_name, bus_profile.master_out_channels > 0 ? &bus_profile : NULL)) {
return -1;
}
void
ARDOUR_UI::load_from_application_api (const std::string& path)
{
+ /* OS X El Capitan (and probably later) now somehow passes the command
+ line arguments to an app via the openFile delegate protocol. Ardour
+ already does its own command line processing, and having both
+ pathways active causes crashes. So, if the command line was already
+ set, do nothing here.
+ */
+
+ if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
+ return;
+ }
+
ARDOUR_COMMAND_LINE::session_name = path;
+
/* Cancel SessionDialog if it's visible to make OSX delegates work.
*
* ARDOUR_UI::starting connects app->ShouldLoad signal and then shows a SessionDialog
/* if there is already a session, relabel the button
on the SessionDialog so that we don't Quit directly
*/
- cancel_not_quit = (_session != 0);
+ cancel_not_quit = (_session != 0) && !quit_on_cancel;
if (_session && _session->dirty()) {
if (unload_session (false)) {
break;
default:
if (quit_on_cancel) {
- // JE - Currently (July 2014) this section can only get reached if the
- // user quits from the main 'Session Setup' dialog (i.e. reaching this
- // point does NOT indicate an abnormal termination). Therefore, let's
- // behave gracefully (i.e. let's do some cleanup) before we call exit()
+ ARDOUR_UI::finish ();
+ Gtkmm2ext::Application::instance()->cleanup();
ARDOUR::cleanup ();
pthread_cancel_all ();
-
- exit (1);
+ return -1; // caller is responsible to call exit()
} else {
return ret;
}
session_path = session_dialog.session_folder ();
if (nsm) {
- likely_new = true;
+ likely_new = true;
}
+ if (!likely_new) {
+ int rv = ARDOUR::inflate_session (session_name,
+ Config->get_default_session_parent_dir(), session_path, session_name);
+ if (rv < 0) {
+ MessageDialog msg (session_dialog,
+ string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
+ msg.run ();
+ continue;
+ }
+ else if (rv == 0) {
+ session_dialog.set_provided_session (session_name, session_path);
+ }
+ }
+
+ // XXX check archive, inflate
string::size_type suffix = session_name.find (statefile_suffix);
if (suffix != string::npos) {
if (session_name[0] == G_DIR_SEPARATOR ||
#ifdef PLATFORM_WINDOWS
- (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
+ (session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
#else
- (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
- (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
+ (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
+ (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
#endif
- )
+ )
{
/* absolute path or cwd-relative path specified for session name: infer session folder
if (illegal) {
MessageDialog msg (session_dialog,
- string_compose (_("To ensure compatibility with various systems\n"
- "session names may not contain a '%1' character"),
- illegal));
+ string_compose (_("To ensure compatibility with various systems\n"
+ "session names may not contain a '%1' character"),
+ illegal));
msg.run ();
ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
continue;
if (illegal) {
pop_back_splash (session_dialog);
MessageDialog msg (session_dialog, string_compose(_("To ensure compatibility with various systems\n"
- "session names may not contain a '%1' character"), illegal));
+ "session names may not contain a '%1' character"), illegal));
msg.run ();
ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
continue;
_session_is_new = true;
}
- if (likely_new && template_name.empty()) {
+ if (!template_name.empty() && template_name.substr (0, 11) == "urn:ardour:") {
+
+ ret = build_session_from_dialog (session_dialog, session_path, session_name);
+ meta_session_setup (template_name.substr (11));
+
+ } else if (likely_new && template_name.empty()) {
ret = build_session_from_dialog (session_dialog, session_path, session_name);
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).
int
ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, std::string mix_template)
{
+ /* load_session calls flush_pending() which allows
+ * GUI interaction and potentially loading another session
+ * (that was easy via snapshot sidebar).
+ * Recursing into load_session() from load_session() and recusive
+ * event loops causes all kind of crashes.
+ */
+ assert (!session_load_in_progress);
+ if (session_load_in_progress) {
+ return -1;
+ }
+ PBD::Unwinder<bool> lsu (session_load_in_progress, true);
+
Session *new_session;
int unload_status;
int retval = -1;
}
catch (SessionException e) {
MessageDialog msg (string_compose(
- _("Session \"%1 (snapshot %2)\" did not load successfully: %3"),
+ _("Session \"%1 (snapshot %2)\" did not load successfully:\n%3"),
path, snap_name, e.what()),
true,
Gtk::MESSAGE_INFO,
catch (...) {
MessageDialog msg (string_compose(
- _("Session \"%1 (snapshot %2)\" did not load successfully"),
- path, snap_name),
+ _("Session \"%1 (snapshot %2)\" did not load successfully."),
+ path, snap_name),
true,
Gtk::MESSAGE_INFO,
BUTTONS_OK);
#endif
retval = 0;
+ if (!mix_template.empty ()) {
+ /* if mix_template is given, assume this is a new session */
+ string metascript = Glib::build_filename (mix_template, "template.lua");
+ meta_session_setup (metascript);
+ }
+
+
out:
+ /* For successful session load the splash is hidden by ARDOUR_UI::first_idle,
+ * which is queued by set_session().
+ * If session-loading fails we hide it explicitly.
+ * This covers both cases in a central place.
+ */
+ if (retval) {
+ hide_splash ();
+ }
return retval;
}
int
-ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile& bus_profile)
+ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, BusProfile* bus_profile)
{
Session *new_session;
int x;
_session_is_new = true;
try {
- new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile);
+ new_session = new Session (*AudioEngine::instance(), path, snap_name, bus_profile);
}
catch (SessionException e) {
+ cerr << "Here are the errors associated with this failed session:\n";
dump_errors (cerr);
+ cerr << "---------\n";
MessageDialog msg (string_compose(_("Could not create session in \"%1\": %2"), path, e.what()));
msg.set_title (_("Loading Error"));
msg.set_position (Gtk::WIN_POS_CENTER);
return -1;
}
catch (...) {
+ cerr << "Here are the errors associated with this failed session:\n";
dump_errors (cerr);
+ cerr << "---------\n";
MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
msg.set_title (_("Loading Error"));
msg.set_position (Gtk::WIN_POS_CENTER);
/* Put the playhead at 0 and scroll fully left */
n = new_session->instant_xml (X_("Editor"));
if (n) {
- n->add_property (X_("playhead"), X_("0"));
- n->add_property (X_("left-frame"), X_("0"));
+ n->set_property (X_("playhead"), X_("0"));
+ n->set_property (X_("left-frame"), X_("0"));
}
set_session (new_session);
return 0;
}
+
+static void _lua_print (std::string s) {
+#ifndef NDEBUG
+ std::cout << "LuaInstance: " << s << "\n";
+#endif
+ PBD::info << "LuaInstance: " << s << endmsg;
+}
+
+void
+ARDOUR_UI::meta_session_setup (const std::string& script_path)
+{
+ if (!Glib::file_test (script_path, Glib::FILE_TEST_EXISTS | Glib::FILE_TEST_IS_REGULAR)) {
+ return;
+ }
+
+ LuaState lua;
+ lua.Print.connect (&_lua_print);
+ lua.sandbox (true);
+
+ lua_State* L = lua.getState();
+ LuaInstance::register_classes (L);
+ LuaBindings::set_session (L, _session);
+ luabridge::push <PublicEditor *> (L, &PublicEditor::instance());
+ lua_setglobal (L, "Editor");
+
+ lua.do_command ("function ardour () end");
+ lua.do_file (script_path);
+
+ try {
+ luabridge::LuaRef fn = luabridge::getGlobal (L, "session_setup");
+ if (fn.isFunction()) {
+ fn ();
+ }
+ } catch (luabridge::LuaException const& e) {
+ cerr << "LuaException:" << e.what () << endl;
+ }
+}
+
void
ARDOUR_UI::launch_chat ()
{
void
ARDOUR_UI::hide_splash ()
{
- delete splash;
- splash = 0;
+ delete splash;
+ splash = 0;
}
void
if (removed == 0) {
MessageDialog msgd (_main_window,
- _("No files were ready for clean-up"),
- true,
- Gtk::MESSAGE_INFO,
- Gtk::BUTTONS_OK);
+ _("No files were ready for clean-up"),
+ true,
+ Gtk::MESSAGE_INFO,
+ Gtk::BUTTONS_OK);
msgd.set_title (_("Clean-up"));
- msgd.set_secondary_text (_("If this seems suprising, \n\
+ msgd.set_secondary_text (_("If this seems surprising, \n\
check for any existing snapshots.\n\
These may still include regions that\n\
require some unused files to continue to exist."));
ArdourDialog results (_("Clean-up"), true, false);
struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
- CleanupResultsModelColumns() {
- add (visible_name);
- add (fullpath);
- }
- Gtk::TreeModelColumn<std::string> visible_name;
- Gtk::TreeModelColumn<std::string> fullpath;
+ CleanupResultsModelColumns() {
+ add (visible_name);
+ add (fullpath);
+ }
+ Gtk::TreeModelColumn<std::string> visible_name;
+ Gtk::TreeModelColumn<std::string> fullpath;
};
}
PresentationInfo::order_t
-ARDOUR_UI::translate_order (AddRouteDialog::InsertAt place)
+ARDOUR_UI::translate_order (RouteDialogs::InsertAt place)
{
if (editor->get_selection().tracks.empty()) {
- return PresentationInfo::max_order;
+ return place == RouteDialogs::First ? 0 : PresentationInfo::max_order;
}
PresentationInfo::order_t order_hint = PresentationInfo::max_order;
the highest order key in the selection + 1 (if available).
*/
- if (place == AddRouteDialog::AfterSelection) {
+ if (place == RouteDialogs::AfterSelection) {
RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.back());
if (rtav) {
order_hint = rtav->route()->presentation_info().order();
order_hint++;
}
- } else if (place == AddRouteDialog::BeforeSelection) {
+ } else if (place == RouteDialogs::BeforeSelection) {
RouteTimeAxisView *rtav = dynamic_cast<RouteTimeAxisView*> (editor->get_selection().tracks.front());
if (rtav) {
order_hint = rtav->route()->presentation_info().order();
}
- } else if (place == AddRouteDialog::First) {
+ } else if (place == RouteDialogs::First) {
order_hint = 0;
} else {
/* leave order_hint at max_order */
ARDOUR_UI::add_route ()
{
if (!add_route_dialog.get (false)) {
- add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_finished));
+ add_route_dialog->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::add_route_dialog_response));
}
if (!_session) {
}
void
-ARDOUR_UI::add_route_dialog_finished (int r)
+ARDOUR_UI::add_route_dialog_response (int r)
{
int count;
- add_route_dialog->hide();
-
switch (r) {
- case RESPONSE_ACCEPT:
- break;
- default:
- return;
- break;
+ case AddRouteDialog::Add:
+ break;
+ case AddRouteDialog::AddAndClose:
+ add_route_dialog->ArdourDialog::on_response (r);
+ break;
+ default:
+ add_route_dialog->ArdourDialog::on_response (r);
+ return;
+ }
+
+ std::string template_name = add_route_dialog->get_template_path();
+ if ( !template_name.empty() ) {
+
+ if (!template_name.empty() && template_name.substr (0, 11) == "urn:ardour:") {
+
+ //ret = build_session_from_dialog (session_dialog, session_path, session_name);
+ meta_session_setup (template_name.substr (11));
+
+ } else {
+
+ //could be a user's track template (from file). ToDo
+ }
+
+ return;
}
if ((count = add_route_dialog->count()) <= 0) {
if (!template_path.empty()) {
if (add_route_dialog->name_template_is_default()) {
- _session->new_route_from_template (count, template_path, string());
+ _session->new_route_from_template (count, order, template_path, string());
} else {
- _session->new_route_from_template (count, template_path, add_route_dialog->name_template());
+ _session->new_route_from_template (count, order, template_path, add_route_dialog->name_template());
}
return;
}
/* XXX do something with name template */
+ Session::ProcessorChangeBlocker pcb (_session);
+
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, strict_io, order);
}
}
-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)
{
std::string icsd_exec = video_server_dialog->get_exec_path();
std::string icsd_docroot = video_server_dialog->get_docroot();
- if (icsd_docroot.empty()) {
#ifndef PLATFORM_WINDOWS
- icsd_docroot = X_("/");
-#else
- icsd_docroot = X_("C:\\");
-#endif
+ if (icsd_docroot.empty()) {
+ icsd_docroot = VideoUtils::video_get_docroot (Config);
}
+#endif
GStatBuf sb;
+#ifdef PLATFORM_WINDOWS
+ if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) {
+ /* OK, allow all drive letters */
+ } else
+#endif
if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
warning << _("Specified docroot is not an existing directory.") << endmsg;
continue;
argp[8] = 0;
stop_video_server();
+#ifdef PLATFORM_WINDOWS
+ if (VideoUtils::harvid_version >= 0x000802 && icsd_docroot.empty()) {
+ /* OK, allow all drive letters */
+ } else
+#endif
if (icsd_docroot == X_("/") || icsd_docroot == X_("C:\\")) {
Config->set_video_advanced_setup(false);
} else {
- std::ostringstream osstream;
- osstream << "http://127.0.0.1:" << video_server_dialog->get_listenport() << "/";
- Config->set_video_server_url(osstream.str());
+ std::string url_str = "http://127.0.0.1:" + to_string(video_server_dialog->get_listenport()) + "/";
+ Config->set_video_server_url(url_str);
Config->set_video_server_docroot(icsd_docroot);
Config->set_video_advanced_setup(true);
}
if (video_timeline->video_file_info(path, local_file)) {
XMLNode* node = new XMLNode(X_("Videotimeline"));
- node->add_property (X_("Filename"), path);
- node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
- node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0"));
+ node->set_property (X_("Filename"), path);
+ node->set_property (X_("AutoFPS"), auto_set_session_fps);
+ node->set_property (X_("LocalFile"), local_file);
if (orig_local_file) {
- node->add_property (X_("OriginalVideoFile"), orig_path);
+ node->set_property (X_("OriginalVideoFile"), orig_path);
} else {
node->remove_property (X_("OriginalVideoFile"));
}
ARDOUR_UI::create_xrun_marker (framepos_t where)
{
if (_session) {
- Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark);
+ Location *location = new Location (*_session, where, where, _("xrun"), Location::IsMark, 0);
_session->locations()->add (location);
}
}
void
ARDOUR_UI::halt_on_xrun_message ()
{
- cerr << "HALT on xrun\n";
- MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
+ cerr << "HALT on xrun\n";
+ MessageDialog msg (_main_window, _("Recording was stopped because your system could not keep up."));
msg.run ();
}
case RESPONSE_ACCEPT:
return 0;
default:
- break;
+ break;
}
- return 1;
+ return 1;
}
void
{
ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed);
- if (!_session || !big_clock_window) {
+ if (!_session) {
/* why bother - the clock isn't visible */
return;
}
- if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
- big_clock->set_active (true);
- } else {
- big_clock->set_active (false);
+ ActionManager::set_sensitive (ActionManager::rec_sensitive_actions, !_session->actively_recording());
+
+ if (big_clock_window) {
+ if (_session->record_status () == Session::Recording && _session->have_rec_enabled_track ()) {
+ big_clock->set_active (true);
+ } else {
+ big_clock->set_active (false);
+ }
}
+
}
bool
editor->first_idle();
}
+ /* in 1 second, hide the splash screen
+ *
+ * Consider hiding it *now*. If a user opens opens a dialog
+ * during that one second while the splash is still visible,
+ * the dialog will push-back the splash.
+ * Closing the dialog later will pop it back.
+ */
+ Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
+
Keyboard::set_can_save_keybindings (true);
return false;
}
for (vector<AudioClock*>::iterator x = AudioClock::clocks.begin(); x != AudioClock::clocks.end(); ++x) {
XMLNode* child = new XMLNode (X_("Clock"));
- child->add_property (X_("name"), (*x)->name());
- child->add_property (X_("mode"), enum_2_string ((*x)->mode()));
- child->add_property (X_("on"), ((*x)->off() ? X_("no") : X_("yes")));
+ child->set_property (X_("name"), (*x)->name());
+ child->set_property (X_("mode"), (*x)->mode());
+ child->set_property (X_("on"), (*x)->on());
node->add_child_nocopy (*child);
}
const char* end_mono = "</tt>";
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 backup copy with older versions of %3"),
- xml_path, backup_path, PROGRAM_NAME,
- start_big, end_big,
- start_mono, end_mono), true);
+ "%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 backup copy with older versions of %3"),
+ xml_path, backup_path, PROGRAM_NAME,
+ start_big, end_big,
+ start_mono, end_mono), true);
msg.run ();
}
+void
+ARDOUR_UI::add_editor_meter_type_item (Menu_Helpers::MenuList& items, RadioMenuItem::Group& group, string const & name, MeterType type)
+{
+ using namespace Menu_Helpers;
+
+ items.push_back (RadioMenuElem (group, name, sigc::bind (sigc::mem_fun (editor_meter, &LevelMeterHBox::set_meter_type), type)));
+ RadioMenuItem* i = dynamic_cast<RadioMenuItem *> (&items.back ());
+ i->set_active (editor_meter->meter_type () == type);
+}
+
+void
+ARDOUR_UI::popup_editor_meter_menu (GdkEventButton* ev)
+{
+ using namespace Gtk::Menu_Helpers;
+
+ Gtk::Menu* m = manage (new Menu);
+ MenuList& items = m->items ();
+
+ RadioMenuItem::Group group;
+
+ _suspend_editor_meter_callbacks = true;
+ add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak), MeterPeak);
+ add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterPeak0dB), MeterPeak0dB);
+ add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterKrms), MeterKrms);
+ add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1DIN), MeterIEC1DIN);
+ add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC1NOR), MeterIEC1NOR);
+ add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2BBC), MeterIEC2BBC);
+ add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU);
+ add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK20), MeterK20);
+ add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK14), MeterK14);
+ add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK12), MeterK12);
+ add_editor_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterVU), MeterVU);
+
+ m->popup (ev->button, ev->time);
+ _suspend_editor_meter_callbacks = false;
+}
+
+bool
+ARDOUR_UI::editor_meter_button_press (GdkEventButton* ev)
+{
+ if (ev->button == 3 && editor_meter) {
+ popup_editor_meter_menu (ev);
+ return true;
+ }
+ return false;
+}
void
ARDOUR_UI::reset_peak_display ()
audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
audio_midi_setup->set_position (WIN_POS_CENTER);
- if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
- audio_midi_setup->try_autostart ();
- if (ARDOUR::AudioEngine::instance()->running()) {
- return 0;
+ if (desired_sample_rate != 0) {
+ if (Config->get_try_autostart_engine () || getenv ("TRY_AUTOSTART_ENGINE")) {
+ audio_midi_setup->try_autostart ();
+ if (ARDOUR::AudioEngine::instance()->running()) {
+ return 0;
+ }
}
}
while (true) {
int response = audio_midi_setup->run();
switch (response) {
- case Gtk::RESPONSE_OK:
+ case Gtk::RESPONSE_DELETE_EVENT:
+ // after latency callibration engine may run,
+ // Running() signal was emitted, but dialog will not
+ // have emitted a response. The user needs to close
+ // the dialog -> Gtk::RESPONSE_DELETE_EVENT
+ if (!AudioEngine::instance()->running()) {
+ return -1;
+ }
+ // fall through
+ default:
if (!AudioEngine::instance()->running()) {
continue;
- } else {
- return 0;
}
+ audio_midi_setup->hide ();
return 0;
- default:
- return -1;
}
}
}
void
ARDOUR_UI::hide_application ()
{
- Application::instance ()-> hide ();
+ Application::instance ()-> hide ();
}
void
if (window_icons.empty()) {
Glib::RefPtr<Gdk::Pixbuf> icon;
- if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px")) != 0) {
+ if ((icon = ::get_icon (PROGRAM_NAME "-icon_16px"))) {
window_icons.push_back (icon);
}
- if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px")) != 0) {
+ if ((icon = ::get_icon (PROGRAM_NAME "-icon_22px"))) {
window_icons.push_back (icon);
}
- if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px")) != 0) {
+ if ((icon = ::get_icon (PROGRAM_NAME "-icon_32px"))) {
window_icons.push_back (icon);
}
- if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px")) != 0) {
+ if ((icon = ::get_icon (PROGRAM_NAME "-icon_48px"))) {
window_icons.push_back (icon);
}
}
}
window.set_title (title.get_string());
- window.set_wmclass (string_compose (X_("%1_%1"), downcase (PROGRAM_NAME), downcase (name)), PROGRAM_NAME);
+ window.set_wmclass (string_compose (X_("%1_%1"), downcase (std::string(PROGRAM_NAME)), downcase (name)), PROGRAM_NAME);
window.set_flags (CAN_FOCUS);
window.add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
}
static Gtkmm2ext::Bindings*
-get_bindings_from_widget_heirarchy (GtkWidget* w)
+get_bindings_from_widget_heirarchy (GtkWidget** w)
{
void* p = NULL;
- while (w) {
- if ((p = g_object_get_data (G_OBJECT(w), "ardour-bindings")) != 0) {
+ while (*w) {
+ if ((p = g_object_get_data (G_OBJECT(*w), "ardour-bindings")) != 0) {
break;
}
- w = gtk_widget_get_parent (w);
+ *w = gtk_widget_get_parent (*w);
}
return reinterpret_cast<Gtkmm2ext::Bindings*> (p);
{
GtkWindow* win = window.gobj();
GtkWidget* focus = gtk_window_get_focus (win);
+ GtkWidget* binding_widget = focus;
bool special_handling_of_unmodified_accelerators = false;
const guint mask = (Keyboard::RelevantModifierKeyMask & ~(Gdk::SHIFT_MASK|Gdk::LOCK_MASK));
- if (focus) {
+ if (focus) {
/* some widget has keyboard focus */
} else {
- Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (focus);
+ Gtkmm2ext::Bindings* focus_bindings = get_bindings_from_widget_heirarchy (&binding_widget);
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 [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,
- Gtkmm2ext::show_gdk_event_state (ev->state),
+ 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,
+ Gtkmm2ext::show_gdk_event_state (ev->state),
special_handling_of_unmodified_accelerators,
Keyboard::some_magic_widget_has_focus(),
- focus,
+ focus,
(focus ? gtk_widget_get_name (focus) : "no focus widget"),
((ev->state & mask) ? "yes" : "no"),
window.get_title()));
/* no special handling or there are modifiers in effect: accelerate first */
- DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
+ DEBUG_TRACE (DEBUG::Accelerators, "\tactivate, then propagate\n");
DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tevent send-event:%1 time:%2 length:%3 name %7 string:%4 hardware_keycode:%5 group:%6\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) {
+ while (bindings) {
DEBUG_TRACE (DEBUG::Accelerators, string_compose ("\tusing Ardour bindings %1 @ %2 for this event\n", bindings->name(), bindings));
DEBUG_TRACE (DEBUG::Accelerators, "\t\thandled\n");
return true;
}
+
+ if (binding_widget) {
+ binding_widget = gtk_widget_get_parent (binding_widget);
+ if (binding_widget) {
+ bindings = get_bindings_from_widget_heirarchy (&binding_widget);
+ } else {
+ bindings = 0;
+ }
+ } else {
+ bindings = 0;
+ }
}
DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
return true;
}
- DEBUG_TRACE (DEBUG::Accelerators, "\tnot accelerated, now propagate\n");
+ 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;
- }
+ if (gtk_window_propagate_key_event (win, ev)) {
+ DEBUG_TRACE (DEBUG::Accelerators, "\tpropagate handled\n");
+ return true;
+ }
} else {
DEBUG_TRACE (DEBUG::Accelerators, "\tpropagation didn't handle, so activate\n");
KeyboardKey k (ev->state, ev->keyval);
- if (bindings) {
+ while (bindings) {
DEBUG_TRACE (DEBUG::Accelerators, "\tusing Ardour bindings for this window\n");
return true;
}
+ if (binding_widget) {
+ binding_widget = gtk_widget_get_parent (binding_widget);
+ if (binding_widget) {
+ bindings = get_bindings_from_widget_heirarchy (&binding_widget);
+ } else {
+ bindings = 0;
+ }
+ } else {
+ bindings = 0;
+ }
}
DEBUG_TRACE (DEBUG::Accelerators, "\tnot yet handled, try global bindings\n");
_session->cancel_all_solo ();
}
}
+
+void
+ARDOUR_UI::reset_focus (Gtk::Widget* w)
+{
+ /* this resets focus to the first focusable parent of the given widget,
+ * or, if there is no focusable parent, cancels focus in the toplevel
+ * window that the given widget is packed into (if there is one).
+ */
+
+ if (!w) {
+ return;
+ }
+
+ Gtk::Widget* top = w->get_toplevel();
+
+ if (!top || !top->is_toplevel()) {
+ return;
+ }
+
+ w = w->get_parent ();
+
+ while (w) {
+
+ if (w->is_toplevel()) {
+ /* Setting the focus widget to a Gtk::Window causes all
+ * subsequent calls to ::has_focus() on the nominal
+ * focus widget in that window to return
+ * false. Workaround: never set focus to the toplevel
+ * itself.
+ */
+ break;
+ }
+
+ if (w->get_can_focus ()) {
+ Gtk::Window* win = dynamic_cast<Gtk::Window*> (top);
+ win->set_focus (*w);
+ return;
+ }
+ w = w->get_parent ();
+ }
+
+ if (top == &_main_window) {
+
+ }
+
+ /* no focusable parent found, cancel focus in top level window.
+ C++ API cannot be used for this. Thanks, references.
+ */
+
+ gtk_window_set_focus (GTK_WINDOW(top->gobj()), 0);
+
+}