#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 "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 "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 "speaker_dialog.h"
#include "splash.h"
#include "startup.h"
+#include "template_dialog.h"
#include "time_axis_view_item.h"
#include "time_info_box.h"
#include "timers.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];
, 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)
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 ();
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*
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
BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
- if (splash) {
- // 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;
can_return = false;
}
- if (splash) {
- // 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;
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;
}
if (!sa.include_media && sa.switch_to) {
unload_session (false);
load_session (sa.final_session_folder_name, sa.new_name);
- hide_splash ();
}
}
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) {
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 ()
{
// 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()
+ assert (!_session);
ARDOUR::cleanup ();
pthread_cancel_all ();
session_path = session_dialog.session_folder ();
if (nsm) {
- likely_new = true;
+ likely_new = true;
}
if (!likely_new) {
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).
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;
}
return 0;
}
+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 (&LuaInstance::_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) { }
+}
+
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;
};
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
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;
}
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::hide_application ()
{
- Application::instance ()-> hide ();
+ Application::instance ()-> hide ();
}
void
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 */
}
}
- 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)));
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 {