#ifdef WAF_BUILD
#include "gtk2ardour-config.h"
+#include "gtk2ardour-version.h"
#endif
#include <algorithm>
#include "pbd/enumwriter.h"
#include "pbd/memento_command.h"
#include "pbd/openuri.h"
+#include "pbd/stl_delete.h"
#include "pbd/file_utils.h"
#include "pbd/localtime_r.h"
+#include "pbd/pthread_utils.h"
#include "gtkmm2ext/application.h"
#include "gtkmm2ext/bindings.h"
#include "ardour/filename_extensions.h"
#include "ardour/filesystem_paths.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/session_state_utils.h"
#include "ardour/session_utils.h"
#include "ardour/slave.h"
+#include "ardour/system_exec.h"
+
+#ifdef WINDOWS_VST_SUPPORT
+#include <fst.h>
+#endif
+#ifdef AUDIOUNIT_SUPPORT
+#include "ardour/audio_unit.h"
+#endif
#include "timecode/time.h"
#include "video_server_dialog.h"
#include "add_video_dialog.h"
#include "transcode_video_dialog.h"
-#include "system_exec.h"
#include "i18n.h"
using namespace ARDOUR;
+using namespace ARDOUR_UI_UTILS;
using namespace PBD;
using namespace Gtkmm2ext;
using namespace Gtk;
using namespace std;
ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
-UIConfiguration *ARDOUR_UI::ui_config = 0;
sigc::signal<void,bool> ARDOUR_UI::Blink;
sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
+sigc::signal<void> ARDOUR_UI::FPSUpdate;
sigc::signal<void, framepos_t, bool, framepos_t> ARDOUR_UI::Clock;
sigc::signal<void> ARDOUR_UI::CloseAllDialogs;
ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
: Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp)
-
+ , ui_config (new UIConfiguration)
, gui_object_state (new GUIObjectState)
, primary_clock (new MainClock (X_("primary"), false, X_("transport"), true, true, true, false, true))
, _was_dirty (false)
, _mixer_on_top (false)
, first_time_engine_run (true)
+ , blink_timeout_tag (-1)
/* transport */
, 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"))
+ , auditioning_alert_button (_("Audition"))
+ , solo_alert_button (_("Solo"))
+ , feedback_alert_button (_("Feedback"))
, editor_meter(0)
, editor_meter_peak_display()
splash = 0;
+ _numpad_locate_happening = false;
+
if (theArdourUI == 0) {
theArdourUI = this;
}
- ui_config = new UIConfiguration();
-
ui_config->ParameterChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::parameter_changed));
boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
ui_config->map_parameters (pc);
rec_button.set_name ("transport recenable button");
midi_panic_button.set_name ("transport button");
- goto_start_button.set_tweaks (ArdourButton::ShowClick);
- goto_end_button.set_tweaks (ArdourButton::ShowClick);
- midi_panic_button.set_tweaks (ArdourButton::ShowClick);
-
last_configure_time= 0;
last_peak_grab = 0;
ARDOUR::FileSource::AmbiguousFileName.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::ambiguous_file, this, _1, _2));
+ /* also plugin scan messages */
+ ARDOUR::PluginScanMessage.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_dialog, this, _1, _2, _3), gui_context());
+ ARDOUR::PluginScanTimeout.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::plugin_scan_timeout, this, _1), gui_context());
+
+ ARDOUR::GUIIdle.connect (forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::gui_idle_handler, this), gui_context());
+
+ Config->ParameterChanged.connect ( forever_connections, MISSING_INVALIDATOR, boost::bind(&ARDOUR_UI::set_flat_buttons, this), gui_context() );
+ set_flat_buttons();
+
/* lets get this party started */
setup_gtk_ardour_enums ();
{
/* Things to be done once (and once ONLY) after we have a backend running in the AudioEngine
*/
+#ifdef AUDIOUNIT_SUPPORT
+ std::string au_msg;
+ if (AUPluginInfo::au_get_crashlog(au_msg)) {
+ popup_error(_("Audio Unit Plugin Scan Failed. Automatic AU scanning has been disabled. Please see the log window for further details."));
+ error << _("Audio Unit Plugin Scan Failed:") << endmsg;
+ info << au_msg << endmsg;
+ }
+#endif
ARDOUR::init_post_engine ();
_tooltips.enable();
- ActionManager::load_menus ();
-
if (setup_windows ()) {
throw failed_constructor ();
}
vector<string>::iterator n;
vector<string>::iterator k;
- for (n = names.begin(), k = keys.begin(); n != names.end(); ++n, ++k) {
- cout << "Action: " << (*n) << " bound to " << (*k) << endl;
+ 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;
}
+ halt_connection.disconnect ();
+ AudioEngine::instance()->stop ();
exit (0);
}
Glib::signal_timeout().connect_seconds (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 1);
#endif
- Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
- boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
- Config->map_parameters (pc);
+ {
+ DisplaySuspender ds;
+ Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
+ boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
+ Config->map_parameters (pc);
+ }
}
ARDOUR_UI::~ARDOUR_UI ()
{
- if (ui_config->dirty()) {
- ui_config->save_state();
- }
-
- delete keyboard;
- delete editor;
- delete mixer;
- delete meterbridge;
+ ui_config->save_state();
stop_video_server();
+
+ 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 gui_object_state;
+ FastMeter::flush_pattern_cache ();
+ }
}
void
try {
audio_midi_setup.get (true);
} catch (...) {
+ std::cerr << "audio-midi engine setup failed."<< std::endl;
return -1;
}
const bool new_session_required = (ARDOUR_COMMAND_LINE::new_session || brand_new_user);
if (get_session_parameters (false, new_session_required, ARDOUR_COMMAND_LINE::load_template)) {
+ std::cerr << "Cannot get session parameters."<< std::endl;
return -1;
}
}
second_connection.disconnect ();
point_one_second_connection.disconnect ();
+#ifndef PLATFORM_WINDOWS
point_zero_something_second_connection.disconnect();
+#endif
+ fps_connection.disconnect();
}
delete ARDOUR_UI::instance()->video_timeline;
close_all_dialogs ();
- loading_message (string_compose (_("Please wait while %1 cleans up..."), PROGRAM_NAME));
-
if (_session) {
// _session->set_deletion_in_progress ();
_session->set_clean ();
halt_connection.disconnect ();
AudioEngine::instance()->stop ();
+#ifdef WINDOWS_VST_SUPPORT
+ fst_stop_threading();
+#endif
quit ();
}
float mpeak = editor_meter->update_meters();
if (mpeak > editor_meter_max_peak) {
if (mpeak >= Config->get_meter_peak()) {
- editor_meter_peak_display.set_name ("meterbridge peakindicator on");
- editor_meter_peak_display.set_elements((ArdourButton::Element) (ArdourButton::Edge|ArdourButton::Body));
+ editor_meter_peak_display.set_active_state ( Gtkmm2ext::ExplicitActive );
}
}
}
return TRUE;
}
+gint
+ARDOUR_UI::every_fps ()
+{
+ FPSUpdate(); /* EMIT_SIGNAL */
+#ifdef PLATFORM_WINDOWS
+ every_point_zero_something_seconds();
+#endif
+ return TRUE;
+}
+
+void
+ARDOUR_UI::set_fps_timeout_connection ()
+{
+ unsigned int interval = 40;
+ if (!_session) return;
+ if (_session->timecode_frames_per_second() != 0) {
+ /* ideally we'll use a select() to sleep and not accumulate
+ * idle time to provide a regular periodic signal.
+ * See linux_vst_gui_support.cc 'elapsed_time_ms'.
+ * However, that'll require a dedicated thread and cross-thread
+ * signals to the GUI Thread..
+ */
+ interval = floor(500. /* update twice per FPS, since Glib::signal_timeout is very irregular */
+ * _session->frame_rate() / _session->nominal_frame_rate()
+ / _session->timecode_frames_per_second()
+ );
+#ifdef PLATFORM_WINDOWS
+ // the smallest windows scheduler time-slice is ~15ms.
+ // periodic GUI timeouts shorter than that will cause
+ // WaitForSingleObject to spinlock (100% of one CPU Core)
+ // and gtk never enters idle mode.
+ // also changing timeBeginPeriod(1) does not affect that in
+ // any beneficial way, so we just limit the max rate for now.
+ interval = std::max(30u, interval); // at most ~33Hz.
+#else
+ interval = std::max(8u, interval); // at most 120Hz.
+#endif
+ }
+ fps_connection.disconnect();
+ fps_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_fps), interval);
+}
+
void
ARDOUR_UI::update_sample_rate (framecnt_t)
{
should also be changed.
*/
- float const c = AudioEngine::instance()->get_dsp_load ();
+ double const c = AudioEngine::instance()->get_dsp_load ();
snprintf (buf, sizeof (buf), _("DSP: <span foreground=\"%s\">%5.1f%%</span>"), c >= 90 ? X_("red") : X_("green"), c);
cpu_load_label.set_markup (buf);
}
get_state_files_in_directory (*i, state_file_paths);
- vector<string*>* states;
+ vector<string> states;
vector<const gchar*> item;
string fullpath = *i;
}
/* now get available states for this session */
+ states = Session::possible_states (fullpath);
- if ((states = Session::possible_states (fullpath)) == 0) {
+ if (states.empty()) {
/* no state file? */
continue;
}
Gtk::TreeModel::Row row = *(recent_session_model->append());
- row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
row[recent_session_columns.fullpath] = fullpath;
row[recent_session_columns.tip] = Glib::Markup::escape_text (fullpath);
if (state_file_names.size() > 1) {
+ // multiple session files in the session directory - show the directory name.
+ row[recent_session_columns.visible_name] = Glib::path_get_basename (fullpath);
// add the children
-
for (std::vector<std::string>::iterator i2 = state_file_names.begin();
i2 != state_file_names.end(); ++i2)
{
child_row[recent_session_columns.fullpath] = fullpath;
child_row[recent_session_columns.tip] = Glib::Markup::escape_text (fullpath);
}
+ } else {
+ // only a single session file in the directory - show its actual name.
+ row[recent_session_columns.visible_name] = state_file_names.front ();
}
}
catch (...) {
MessageDialog msg (*editor,
- string_compose (_("There are insufficient JACK ports available\n\
+ string_compose (_("There are insufficient ports available\n\
to create a new track or bus.\n\
You should save %1, exit and\n\
-restart JACK with more ports."), PROGRAM_NAME));
+restart with more ports."), PROGRAM_NAME));
msg.run ();
}
}
catch (...) {
MessageDialog msg (*editor,
- string_compose (_("There are insufficient JACK ports available\n\
+ string_compose (_("There are insufficient ports available\n\
to create a new track or bus.\n\
You should save %1, exit and\n\
-restart JACK with more ports."), PROGRAM_NAME));
+restart with more ports."), PROGRAM_NAME));
pop_back_splash (msg);
msg.run ();
}
_session->request_stop (false, true);
}
+/** Check if any tracks are record enabled. If none are, record enable all of them.
+ * @return true if track record-enabled status was changed, false otherwise.
+ */
+bool
+ARDOUR_UI::trx_record_enable_all_tracks ()
+{
+ if (!_session) {
+ return false;
+ }
+
+ boost::shared_ptr<RouteList> rl = _session->get_tracks ();
+ bool none_record_enabled = true;
+
+ for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
+ boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*r);
+ assert (t);
+
+ if (t->record_enabled()) {
+ none_record_enabled = false;
+ break;
+ }
+ }
+
+ if (none_record_enabled) {
+ _session->set_record_enabled (rl, true, Session::rt_cleanup);
+ }
+
+ return none_record_enabled;
+}
+
void
ARDOUR_UI::transport_record (bool roll)
{
-
if (_session) {
switch (_session->record_status()) {
case Session::Disabled:
msg.run ();
return;
}
+ if (Profile->get_trx()) {
+ roll = trx_record_enable_all_tracks ();
+ }
_session->maybe_enable_record ();
if (roll) {
transport_roll ();
bool rolling = _session->transport_rolling();
if (_session->get_play_loop()) {
- /* XXX it is not possible to just leave seamless loop and keep
- playing at present (nov 4th 2009)
+
+ /* If loop playback is not a mode, then we should cancel
+ it when this action is requested. If it is a mode
+ we just leave it in place.
*/
- if (!Config->get_seamless_loop()) {
- _session->request_play_loop (false, true);
- }
- } else if (_session->get_play_range () && !Config->get_always_play_range()) {
+
+ if (!Config->get_loop_is_mode()) {
+ /* XXX it is not possible to just leave seamless loop and keep
+ playing at present (nov 4th 2009)
+ */
+ if (!Config->get_seamless_loop()) {
+ /* stop loop playback and stop rolling */
+ _session->request_play_loop (false, true);
+ } else if (rolling) {
+ /* stop loop playback but keep rolling */
+ _session->request_play_loop (false, false);
+ }
+ }
+
+ } else if (_session->get_play_range () ) {
/* stop playing a range if we currently are */
_session->request_play_range (0, true);
}
/* disk buffers are normal, so we can keep playing */
affect_transport = false;
}
- _session->request_play_loop (false, true);
+ _session->request_play_loop (false, affect_transport);
} else if (_session->get_play_range ()) {
affect_transport = false;
_session->request_play_range (0, true);
if (rolling) {
_session->request_stop (with_abort, true);
} else {
- if ( Config->get_always_play_range() ) {
+ if ( Config->get_follow_edits() && ( editor->get_selection().time.front().start == _session->transport_frame() ) ) { //if playhead is exactly at the start of a range, we can assume it was placed there by follow_edits
_session->request_play_range (&editor->get_selection().time, true);
+ _session->set_requested_return_frame( editor->get_selection().time.front().start ); //force an auto-return here
}
-
_session->request_transport_speed (1.0f);
}
}
if (_session->get_play_loop()) {
- if (_session->transport_rolling()) {
+ /* looping enabled, our job is to disable it */
+
+ _session->request_play_loop (false);
+
+ } else {
- _session->request_locate (looploc->start(), true);
- _session->request_play_loop (false);
+ /* looping not enabled, our job is to enable it.
+ loop-is-NOT-mode: this action always starts the transport rolling.
+ loop-IS-mode: this action simply sets the loop play mechanism, but
+ does not start transport.
+ */
+ if (Config->get_loop_is_mode()) {
+ _session->request_play_loop (true, false);
} else {
- _session->request_play_loop (false);
+ _session->request_play_loop (true, true);
}
- } else {
- _session->request_play_loop (true);
}
//show the loop markers
auto_loop_button.set_active (true);
play_selection_button.set_active (false);
- roll_button.set_active (false);
+ if (Config->get_loop_is_mode()) {
+ roll_button.set_active (true);
+ } else {
+ roll_button.set_active (false);
+ }
} else {
auto_loop_button.set_active (false);
}
- if (Config->get_always_play_range()) {
+ if (Config->get_follow_edits()) {
/* light up both roll and play-selection if they are joined */
roll_button.set_active (true);
play_selection_button.set_active (true);
stop_button.set_active (true);
roll_button.set_active (false);
play_selection_button.set_active (false);
- auto_loop_button.set_active (false);
+ if (Config->get_loop_is_mode ()) {
+ auto_loop_button.set_active (_session->get_play_loop());
+ } else {
+ auto_loop_button.set_active (false);
+ }
update_disk_space ();
}
}
void
ARDOUR_UI::update_clocks ()
{
- if (!editor || !editor->dragging_playhead()) {
+ if (editor && !editor->dragging_playhead()) {
Clock (_session->audible_frame(), false, editor->get_preferred_edit_position()); /* EMIT_SIGNAL */
}
}
ARDOUR_UI::start_clocking ()
{
if (Config->get_super_rapid_clock_update()) {
- clock_signal_connection = SuperRapidScreenUpdate.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
+ clock_signal_connection = FPSUpdate.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
} else {
clock_signal_connection = RapidScreenUpdate.connect (sigc::mem_fun(*this, &ARDOUR_UI::update_clocks));
}
if (onoff) {
rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
} else {
- rec_button.set_active_state (Gtkmm2ext::ImplicitActive);
+ rec_button.set_active_state (Gtkmm2ext::Off);
}
} else if (r == Session::Recording && h) {
rec_button.set_active_state (Gtkmm2ext::ExplicitActive);
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::cleanup ();
+ pthread_cancel_all ();
+
exit (1);
} else {
return ret;
}
if (session_name[0] == G_DIR_SEPARATOR ||
+#ifdef PLATFORM_WINDOWS
+ (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() > 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
from what was given.
_session->set_clean ();
}
+#ifdef WINDOWS_VST_SUPPORT
+ fst_stop_threading();
+#endif
+
flush_pending ();
+
+#ifdef WINDOWS_VST_SUPPORT
+ fst_start_threading();
+#endif
retval = 0;
out:
{
#ifdef __APPLE__
open_uri("http://webchat.freenode.net/?channels=ardour-osx");
+#elif defined PLATFORM_WINDOWS
+ open_uri("http://webchat.freenode.net/?channels=ardour-windows");
#else
open_uri("http://webchat.freenode.net/?channels=ardour");
#endif
} else {
for (TrackSelection::iterator s = editor->get_selection().tracks.begin(); s != editor->get_selection().tracks.end(); ++s) {
RouteTimeAxisView* tav = dynamic_cast<RouteTimeAxisView*> (*s);
- if (tav->route()->order_key() > order_hint) {
+ if (tav && tav->route() && tav->route()->order_key() > order_hint) {
order_hint = tav->route()->order_key();
}
}
setup_order_hint();
- PBD::ScopedConnection idle_connection;
-
- if (count > 8) {
- ARDOUR::GUIIdle.connect (idle_connection, MISSING_INVALIDATOR, boost::bind (&Gtkmm2ext::UI::flush_pending, this), gui_context());
- }
-
string template_path = add_route_dialog->track_template();
+ DisplaySuspender ds;
if (!template_path.empty()) {
if (add_route_dialog->name_template_is_default()) {
session_add_audio_bus (input_chan.n_audio(), output_chan.n_audio(), route_group, count, name_template);
break;
}
-
- /* idle connection will end at scope end */
}
void
ARDOUR_UI::stop_video_server (bool ask_confirm)
{
if (!video_server_process && ask_confirm) {
- warning << _("Video-Server was not launched by Ardour. The request to stop it is ignored.") << endmsg;
+ warning << string_compose (_("Video-Server was not launched by %1. The request to stop it is ignored."), PROGRAM_NAME) << endmsg;
}
if (video_server_process) {
if(ask_confirm) {
if (icsd_docroot.empty()) {icsd_docroot = X_("/");}
GStatBuf sb;
- if (!g_lstat (icsd_docroot.c_str(), &sb) == 0 || !S_ISDIR(sb.st_mode)) {
+ if (g_lstat (icsd_docroot.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
warning << _("Specified docroot is not an existing directory.") << endmsg;
continue;
}
#ifndef PLATFORM_WINDOWS
- if ( (!g_lstat (icsd_exec.c_str(), &sb) == 0)
+ if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
|| (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 ) {
warning << _("Given Video Server is not an executable file.") << endmsg;
continue;
}
#else
- if ( (!g_lstat (icsd_exec.c_str(), &sb) == 0)
+ if ( (g_lstat (icsd_exec.c_str(), &sb) != 0)
|| (sb.st_mode & (S_IXUSR)) == 0 ) {
warning << _("Given Video Server is not an executable file.") << endmsg;
continue;
delete video_server_process;
}
- video_server_process = new SystemExec(icsd_exec, argp);
+ video_server_process = new ARDOUR::SystemExec(icsd_exec, argp);
if (video_server_process->start()) {
warning << _("Cannot launch the video-server") << endmsg;
continue;
int timeout = 120; // 6 sec
while (!ARDOUR_UI::instance()->video_timeline->check_server()) {
Glib::usleep (50000);
+ gui_idle_handler();
if (--timeout <= 0 || !video_server_process->is_running()) break;
}
if (timeout <= 0) {
void
ARDOUR_UI::halt_on_xrun_message ()
{
- MessageDialog msg (*editor,
- _("Recording was stopped because your system could not keep up."));
+ cerr << "HALT on xrun\n";
+ MessageDialog msg (*editor, _("Recording was stopped because your system could not keep up."));
msg.run ();
}
}
}
+
+/* TODO: this is getting elaborate enough to warrant being split into a dedicated class */
+static MessageDialog *scan_dlg = NULL;
+static ProgressBar *scan_pbar = NULL;
+static HBox *scan_tbox = NULL;
+
+void
+ARDOUR_UI::cancel_plugin_scan ()
+{
+ PluginManager::instance().cancel_plugin_scan();
+}
+
+void
+ARDOUR_UI::cancel_plugin_timeout ()
+{
+ PluginManager::instance().cancel_plugin_timeout();
+ scan_tbox->hide();
+}
+
+void
+ARDOUR_UI::plugin_scan_timeout (int timeout)
+{
+ if (!scan_dlg || !scan_dlg->is_mapped() || !scan_pbar) {
+ return;
+ }
+ if (timeout > 0) {
+ scan_pbar->set_fraction ((float) timeout / (float) Config->get_vst_scan_timeout());
+ scan_tbox->show();
+ } else {
+ scan_tbox->hide();
+ }
+ gui_idle_handler();
+}
+
+void
+ARDOUR_UI::plugin_scan_dialog (std::string type, std::string plugin, bool can_cancel)
+{
+ if (type == X_("closeme") && !(scan_dlg && scan_dlg->is_mapped())) {
+ return;
+ }
+
+ const bool cancelled = PluginManager::instance().cancelled();
+ if (type != X_("closeme") && !Config->get_show_plugin_scan_window()) {
+ if (cancelled && scan_dlg->is_mapped()) {
+ scan_dlg->hide();
+ gui_idle_handler();
+ return;
+ }
+ if (cancelled || !can_cancel) {
+ return;
+ }
+ }
+
+ static Gtk::Button *cancel_button;
+ static Gtk::Button *timeout_button;
+ if (!scan_dlg) {
+ scan_dlg = new MessageDialog("", false, MESSAGE_INFO, BUTTONS_NONE); // TODO manage
+ VBox* vbox = scan_dlg->get_vbox();
+ vbox->set_size_request(400,-1);
+ scan_dlg->set_title (_("Scanning for plugins"));
+
+ cancel_button = manage(new Gtk::Button(_("Cancel plugin scan")));
+ cancel_button->set_name ("EditorGTKButton");
+ cancel_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_scan) );
+ cancel_button->show();
+
+ scan_dlg->get_vbox()->pack_start ( *cancel_button, PACK_SHRINK);
+
+ scan_tbox = manage( new HBox() );
+
+ timeout_button = manage(new Gtk::Button(_("Stop Timeout")));
+ timeout_button->set_name ("EditorGTKButton");
+ timeout_button->signal_clicked().connect ( mem_fun (*this, &ARDOUR_UI::cancel_plugin_timeout) );
+ timeout_button->show();
+
+ scan_pbar = manage(new ProgressBar());
+ scan_pbar->set_orientation(Gtk::PROGRESS_RIGHT_TO_LEFT);
+ scan_pbar->set_text(_("Scan Timeout"));
+ scan_pbar->show();
+
+ scan_tbox->pack_start (*scan_pbar, PACK_EXPAND_WIDGET, 4);
+ scan_tbox->pack_start (*timeout_button, PACK_SHRINK, 4);
+
+ scan_dlg->get_vbox()->pack_start (*scan_tbox, PACK_SHRINK, 4);
+ }
+
+ assert(scan_dlg && scan_tbox && cancel_button);
+
+ if (type == X_("closeme")) {
+ scan_dlg->hide();
+ } else {
+ scan_dlg->set_message(type + ": " + Glib::path_get_basename(plugin));
+ scan_dlg->show();
+ }
+ if (!can_cancel || !cancelled) {
+ scan_tbox->hide();
+ }
+ cancel_button->set_sensitive(can_cancel && !cancelled);
+
+ gui_idle_handler();
+}
+
+void
+ARDOUR_UI::gui_idle_handler ()
+{
+ int timeout = 30;
+ /* due to idle calls, gtk_events_pending() may always return true */
+ while (gtk_events_pending() && --timeout) {
+ gtk_main_iteration ();
+ }
+}
+
void
ARDOUR_UI::disk_underrun_handler ()
{
Profile->set_small_screen ();
}
- if (getenv ("ARDOUR_SAE")) {
+ if (g_getenv ("ARDOUR_SAE")) {
Profile->set_sae ();
Profile->set_single_package ();
}
+
+ if (g_getenv ("TRX")) {
+ Profile->set_trx ();
+ }
+
+ if (g_getenv ("MIXBUS")) {
+ Profile->set_mixbus ();
+ }
}
int
if (!_session || !_session->master_out() || !editor_meter) return;
editor_meter->clear_meters();
editor_meter_max_peak = -INFINITY;
- editor_meter_peak_display.set_name ("meterbridge peakindicator");
- editor_meter_peak_display.set_elements((ArdourButton::Element) (ArdourButton::Edge|ArdourButton::Body));
+ editor_meter_peak_display.set_active_state ( Gtkmm2ext::Off );
}
void
}
+gint
+ARDOUR_UI::transport_numpad_timeout ()
+{
+ _numpad_locate_happening = false;
+ if (_numpad_timeout_connection.connected() )
+ _numpad_timeout_connection.disconnect();
+ return 1;
+}
+
+void
+ARDOUR_UI::transport_numpad_decimal ()
+{
+ _numpad_timeout_connection.disconnect();
+
+ if (_numpad_locate_happening) {
+ if (editor) editor->goto_nth_marker(_pending_locate_num - 1);
+ _numpad_locate_happening = false;
+ } else {
+ _pending_locate_num = 0;
+ _numpad_locate_happening = true;
+ _numpad_timeout_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::transport_numpad_timeout), 2*1000);
+ }
+}
+
+void
+ARDOUR_UI::transport_numpad_event (int num)
+{
+ if ( _numpad_locate_happening ) {
+ _pending_locate_num = _pending_locate_num*10 + num;
+ } else {
+ switch (num) {
+ case 0: toggle_roll(false, false); break;
+ case 1: transport_rewind(1); break;
+ case 2: transport_forward(1); break;
+ case 3: transport_record(true); break;
+ case 4: toggle_session_auto_loop(); break;
+ case 5: transport_record(false); toggle_session_auto_loop(); break;
+ case 6: toggle_punch(); break;
+ case 7: toggle_click(); break;
+ case 8: toggle_auto_return(); break;
+ case 9: toggle_follow_edits(); break;
+ }
+ }
+}
+
+void
+ARDOUR_UI::set_flat_buttons ()
+{
+ CairoWidget::set_flat_buttons( config()->get_flat_buttons() );
+}