#ifdef WAF_BUILD
#include "gtk2ardour-config.h"
+#include "gtk2ardour-version.h"
#endif
#include <algorithm>
#ifdef WINDOWS_VST_SUPPORT
#include <fst.h>
#endif
+#ifdef AUDIOUNIT_SUPPORT
+#include "ardour/audio_unit.h"
+#endif
#include "timecode/time.h"
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))
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::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 ();
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();
- }
+ 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
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;
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);
}
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);
}
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.
{
#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
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;
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 ();
}
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 {
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
case 1: transport_rewind(1); break;
case 2: transport_forward(1); break;
case 3: transport_record(true); break;
- case 4: if (_session) _session->request_play_loop(true); break;
- case 5: if (_session) _session->request_play_loop(true); transport_record(false); break;
- case 6: toggle_punch(); 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() );
+}