-#include <pbd/error.h>
-#include <pbd/basename.h>
-#include <pbd/compose.h>
-#include <pbd/failed_constructor.h>
-#include <pbd/enumwriter.h>
-#include <pbd/memento_command.h>
-#include <pbd/file_utils.h>
-
-#include <gtkmm2ext/gtk_ui.h>
-#include <gtkmm2ext/utils.h>
-#include <gtkmm2ext/click_box.h>
-#include <gtkmm2ext/fastmeter.h>
-#include <gtkmm2ext/stop_signal.h>
-#include <gtkmm2ext/popup.h>
-#include <gtkmm2ext/window_title.h>
-
-#include <midi++/manager.h>
-
-#include <ardour/ardour.h>
-#include <ardour/profile.h>
-#include <ardour/session_directory.h>
-#include <ardour/session_route.h>
-#include <ardour/session_state_utils.h>
-#include <ardour/session_utils.h>
-#include <ardour/port.h>
-#include <ardour/audioengine.h>
-#include <ardour/playlist.h>
-#include <ardour/utils.h>
-#include <ardour/audio_diskstream.h>
-#include <ardour/audiofilesource.h>
-#include <ardour/recent_sessions.h>
-#include <ardour/port.h>
-#include <ardour/audio_track.h>
-#include <ardour/midi_track.h>
-#include <ardour/filesystem_paths.h>
-#include <ardour/filename_extensions.h>
+#include "pbd/error.h"
+#include "pbd/basename.h"
+#include "pbd/compose.h"
+#include "pbd/failed_constructor.h"
+#include "pbd/enumwriter.h"
+#include "pbd/memento_command.h"
+#include "pbd/file_utils.h"
+
+#include "gtkmm2ext/gtk_ui.h"
+#include "gtkmm2ext/utils.h"
+#include "gtkmm2ext/click_box.h"
+#include "gtkmm2ext/fastmeter.h"
+#include "gtkmm2ext/stop_signal.h"
+#include "gtkmm2ext/popup.h"
+#include "gtkmm2ext/window_title.h"
+
+#include "midi++/manager.h"
+
+#include "ardour/ardour.h"
+#include "ardour/profile.h"
+#include "ardour/session_directory.h"
+#include "ardour/session_route.h"
+#include "ardour/session_state_utils.h"
+#include "ardour/session_utils.h"
+#include "ardour/port.h"
+#include "ardour/audioengine.h"
+#include "ardour/playlist.h"
+#include "ardour/utils.h"
+#include "ardour/audio_diskstream.h"
+#include "ardour/audiofilesource.h"
+#include "ardour/recent_sessions.h"
+#include "ardour/port.h"
+#include "ardour/audio_track.h"
+#include "ardour/midi_track.h"
+#include "ardour/filesystem_paths.h"
+#include "ardour/filename_extensions.h"
- : Gtkmm2ext::UI (X_("Ardour"), argcp, argvp),
-
- primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, false, true),
- secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, false, true),
- preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, true),
- postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, true),
+ : Gtkmm2ext::UI (X_("gui"), argcp, argvp),
+
+ primary_clock (X_("primary"), false, X_("TransportClockDisplay"), true, true, false, true),
+ secondary_clock (X_("secondary"), false, X_("SecondaryClockDisplay"), true, true, false, true),
+ preroll_clock (X_("preroll"), false, X_("PreRollClock"), true, false, true),
+ postroll_clock (X_("postroll"), false, X_("PostRollClock"), true, false, true),
- engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
- engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
- engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
- engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
+ engine->Stopped.connect (forever_connections, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
+ engine->Running.connect (forever_connections, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
+ engine->Halted.connect (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this), gui_context());
+ engine->SampleRateChanged.connect (forever_connections, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
"This might cause Ardour to run out of memory before your system "
"runs out of memory. \n\n"
"You can view the memory limit with 'ulimit -l', "
"and it is normally controlled by /etc/security/limits.conf"));
MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
"This might cause Ardour to run out of memory before your system "
"runs out of memory. \n\n"
"You can view the memory limit with 'ulimit -l', "
"and it is normally controlled by /etc/security/limits.conf"));
- if (session) {
- snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
- session->playback_load(), session->capture_load());
+ push_buffer_stats (c, p);
+
+ snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
+ _session->playback_load(), _session->capture_load());
- if (session->get_play_loop()) {
- session->request_play_loop (false);
- auto_loop_button.set_visual_state (1);
- roll_button.set_visual_state (1);
- } else if (session->get_play_range ()) {
- session->request_play_range (false);
- play_selection_button.set_visual_state (0);
- } else if (rolling) {
- session->request_locate (session->last_transport_start(), true);
+ map_transport_state ();
+}
+
+void
+ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode)
+{
+
+ if (!_session) {
+ return;
+ }
+
+ if (_session->is_auditioning()) {
+ _session->cancel_audition ();
+ return;
+ }
+
+ if (_session->config.get_external_sync()) {
+ switch (_session->config.get_sync_source()) {
+ case JACK:
+ break;
+ default:
+ /* transport controlled by the master */
+ return;
+ }
+ }
+
+ bool rolling = _session->transport_rolling();
+ bool affect_transport = true;
+
+ if (rolling && roll_out_of_bounded_mode) {
+ /* drop out of loop/range playback but leave transport rolling */
+ if (_session->get_play_loop()) {
+ if (Config->get_seamless_loop()) {
+ /* the disk buffers contain copies of the loop - we can't
+ just keep playing, so stop the transport. the user
+ can restart as they wish.
+ */
+ affect_transport = true;
+ } else {
+ /* disk buffers are normal, so we can keep playing */
+ affect_transport = false;
+ }
+ _session->request_play_loop (false, true);
+ } else if (_session->get_play_range ()) {
+ affect_transport = false;
+ _session->request_play_range (0, true);
+ }
+ }
+
+ if (affect_transport) {
+ if (rolling) {
+ _session->request_stop (with_abort, true);
+ } else {
+ _session->request_transport_speed (1.0f);
+ }
- transport_rolling ();
- } else if (sp < 0.0f) {
- transport_rewinding ();
- } else if (sp > 0.0f) {
- transport_forwarding ();
+ shuttle_fract = SHUTTLE_FRACT_SPEED1; /* speed = 1.0, believe it or not */
+ shuttle_box.queue_draw ();
+ } else if (sp == 0.0f) {
+ shuttle_fract = 0;
+ shuttle_box.queue_draw ();
+ update_disk_space ();
+ }
+
+ if (sp != 0.0) {
+
+ if (_session->get_play_range()) {
+
+ play_selection_button.set_visual_state (1);
+ roll_button.set_visual_state (0);
+ auto_loop_button.set_visual_state (0);
+
+ } else if (_session->get_play_loop ()) {
+
+ auto_loop_button.set_visual_state (1);
+ play_selection_button.set_visual_state (0);
+ roll_button.set_visual_state (0);
+
+ } else {
+
+ roll_button.set_visual_state (1);
+ play_selection_button.set_visual_state (0);
+ auto_loop_button.set_visual_state (0);
+ }
+
+ stop_button.set_visual_state (0);
+
-void
-ARDOUR_UI::name_io_setup (AudioEngine& engine,
- string& buf,
- IO& io,
- bool in)
-{
- vector<string> connections;
-
- if (in) {
- if (io.n_inputs().n_total() == 0) {
- buf = _("none");
- return;
- }
-
- /* XXX we're not handling multiple ports yet. */
-
- if (io.input(0)->get_connections(connections) == 0) {
- buf = _("off");
- } else {
- buf = connections.front();
- }
-
- } else {
-
- if (io.n_outputs().n_total() == 0) {
- buf = _("none");
- return;
- }
-
- /* XXX we're not handling multiple ports yet. */
-
- if (io.output(0)->get_connections(connections) == 0) {
- buf = _("off");
- } else {
- buf = connections.front();
- }
- }
-}
- if (snapname.length()){
+
+ bool do_save = (snapname.length() != 0);
+
+ vector<sys::path> p;
+ get_state_files_in_directory (_session->session_directory().root_path(), p);
+ vector<string> n = get_file_names_no_extension (p);
+ if (find (n.begin(), n.end(), snapname) != n.end()) {
+
+ ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
+ Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
+ confirm.get_vbox()->pack_start (m, true, true);
+ confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
+ confirm.show_all ();
+ switch (confirm.run()) {
+ case RESPONSE_CANCEL:
+ do_save = false;
+ }
+ }
+
+ if (do_save) {
-
- if (new_session_dialog->connect_outs_to_master()) {
- oconnect = AutoConnectMaster;
- } else if (new_session_dialog->connect_outs_to_physical()) {
- oconnect = AutoConnectPhysical;
- } else {
- oconnect = AutoConnectOption (0);
- }
-
- nphysin = (uint32_t) new_session_dialog->input_limit_count();
- nphysout = (uint32_t) new_session_dialog->output_limit_count();
+
+ oconnect = AutoConnectOption (0);
+
+ if (_startup->connect_outputs ()) {
+ if (_startup->connect_outs_to_master()) {
+ oconnect = AutoConnectMaster;
+ } else if (_startup->connect_outs_to_physical()) {
+ oconnect = AutoConnectPhysical;
+ }
+ }
+
+ nphysin = (uint32_t) _startup->input_limit_count();
+ nphysout = (uint32_t) _startup->output_limit_count();
- do {
- new_session_dialog->set_have_engine (backend_audio_is_running);
- new_session_dialog->present ();
- end_loading_messages ();
- response = new_session_dialog->run ();
-
- _session_is_new = false;
-
- /* handle possible negative responses */
+ if (session_name.empty()) {
+ break;
+ }
+ if (_startup->use_session_template()) {
+ template_name = _startup->session_template_name();
+ _session_is_new = true;
+ }
- case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
-
- should_be_new = true;
-
- //XXX This is needed because session constructor wants a
- //non-existant path. hopefully this will be fixed at some point.
-
- session_path = Glib::build_filename (session_path, session_name);
-
- if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
-
- if (ask_about_loading_existing_session (session_path)) {
- goto loadit;
- } else {
- response = RESPONSE_NONE;
- goto try_again;
- }
- }
+ if (likely_new && template_name.empty()) {
- if (removed > 1) {
- txt.set_text (string_compose (msg, removed, _("files were"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
- } else {
- txt.set_text (string_compose (msg, removed, _("file was"), dead_sound_directory, (float) rep.space / 1048576.0f, "mega"));
- }
+ bprefix = X_("giga");
+ }
+
+ if (removed > 1) {
+ txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
+ } else {
+ txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
+void
+ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
+{
+ time_t now;
+ time (&now);
+
+ while (disk_buffer_stats.size() > 60) {
+ disk_buffer_stats.pop_front ();
+ }
+
+ disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
+}
+
+void
+ARDOUR_UI::write_buffer_stats ()
+{
+
+ std::ofstream fout;
+ struct tm tm;
+ char buf[64];
+ char path[PATH_MAX+1]; int fd;
+
+ strcpy (path, "ardourBufferingXXXXXX");
+
+ if ((fd = mkstemp (path )) < 0) {
+ cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
+ return;
+ }
+
+ fout.open (path);
+ close (fd);
+
+ if (!fout) {
+ cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
+ return;
+ }
+
+ for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
+ localtime_r (&(*i).when, &tm);
+ strftime (buf, sizeof (buf), "%T", &tm);
+ fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
+ }
+
+ disk_buffer_stats.clear ();
+
+ fout.close ();
+
+ cerr << "Ardour buffering statistics can be found in: " << path << endl;
+}
+
- Glib::RefPtr<Action> act;
-
- switch (Config->get_native_file_data_format ()) {
- case FormatFloat:
- act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
- break;
- case FormatInt24:
- act = ActionManager::get_action (X_("options"), X_("FileDataFormat24bit"));
- break;
- case FormatInt16:
- act = ActionManager::get_action (X_("options"), X_("FileDataFormat16bit"));
- break;
- }
-
- if (act) {
- Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
- ract->set_active ();
- }
-
- switch (Config->get_native_file_header_format ()) {
- case BWF:
- act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
- break;
- case WAVE:
- act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE"));
- break;
- case WAVE64:
- act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatWAVE64"));
- break;
- case iXML:
- act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatiXML"));
- break;
- case RF64:
- act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatRF64"));
- break;
- case CAF:
- act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatCAF"));
- break;
- case AIFF:
- act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatAIFF"));
- break;
- }
-
- if (act) {
- Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
- ract->set_active ();
- }