(1) VST SUPPORT
-You may not distribute binaries of Ardour with VST support. Doing so
-is a violation of the license agreement for the Steinberg VST SDK. If
-you are found to be distributing such binaries, you risk both
-prosecution by Steinberg and public humiliation by me.
-
-This is not my choice, and as soon as Steinberg change their
-licensing, which they have indicated they will do, this policy (and
-file) will be removed.
+Please do not distribution Ardour with VST support under the package
+name "ardour" (or any case-variant on that). Use some other name such
+as "ardourvst", "ArdourVST", "ardour-vst" etc. In the near future,
+work will be done to make it possible to share as much as possible of
+the packaging.
(2) STANDARD TEMPLATES
The templates in ./templates are intended for installation in
-$prefix/share/ardour3/templates.
+$prefix/share/ardour2/templates.
Please see the Ardour web site at http://ardour.org/ for all documentation..
-
+For information on building ardour: http://ardour.org/building.
N_("Nimal Ratnayake"),
N_("Dave Robillard"),
N_("Taybin Rutkin"),
+ N_("Andreas Ruge"),
N_("Sampo Savolainen"),
N_("Per Sigmond"),
N_("Lincoln Spiteri"),
};
static const char* translators[] = {
- N_("French:\n\tAlain Fréhel <alain.frehel@free.fr>\n\tChristophe Combelles <ccomb@free.fr>\n"),
+ N_("French:\n\tAlain Fréhel <alain.frehel@free.fr>\n\tChristophe Combelles <ccomb@free.fr>\n\tMartin Blanchard\n"),
N_("German:\n\tKarsten Petersen <kapet@kapet.de>\
\n\tSebastian Arnold <mail@sebastian-arnold.net>\
\n\tRobert Schwede<schwede@ironshark.com>\n"),
N_("Greek:\n\t Klearchos Gourgourinis <muadib@in.gr>\n"),
N_("Swedish:\n\t Petter Sundlöf <petter.sundlof@gmail.com>\n"),
N_("Polish:\n\t Piotr Zaryk <pzaryk@gmail.com>\n"),
+ N_("Czech:\n\t Pavel Frich\n"),
+ N_("Norwegian:\n\t Eivind Ødegård\n"),
0
};
}
set_translator_credits (t);
- set_copyright (_("Copyright (C) 1999-2009 Paul Davis\n"));
+ set_copyright (_("Copyright (C) 1999-2010 Paul Davis\n"));
set_license (gpl);
set_name (X_("ardour"));
set_website (X_("http://ardour.org/"));
<menuitem action='track-height-smaller'/>
<menuitem action='track-height-small'/>
</menu>
+ <menuitem action='track-record-enable-toggle'/>
<menuitem action='toggle-track-active'/>
<menuitem action='remove-track'/>
</menu>
<separator/>
</menu>
<menu name='Help' action='Help'>
+#ifndef GTKOSX
<menuitem action='About'/>
+#endif
+ <menuitem action='Chat'/>
</menu>
</menubar>
#include "pbd/failed_constructor.h"
#include "pbd/enumwriter.h"
#include "pbd/memento_command.h"
+#include "pbd/openuri.h"
#include "pbd/file_utils.h"
#include "gtkmm2ext/gtk_ui.h"
prompter.set_prompt (_("Name of New Snapshot"));
prompter.set_initial_text (timebuf);
+ again:
switch (prompter.run()) {
case RESPONSE_ACCEPT:
{
bool do_save = (snapname.length() != 0);
+ if (do_save) {
+ if (snapname.find ('/') != string::npos) {
+ MessageDialog msg (_("To ensure compatibility with various systems\n"
+ "snapshot names may not contain a '/' character"));
+ msg.run ();
+ goto again;
+ }
+ if (snapname.find ('\\') != string::npos) {
+ MessageDialog msg (_("To ensure compatibility with various systems\n"
+ "snapshot names may not contain a '\\' character"));
+ msg.run ();
+ goto again;
+ }
+ }
+
vector<sys::path> p;
get_state_files_in_directory (_session->session_directory().root_path(), p);
vector<string> n = get_file_names_no_extension (p);
(session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
(session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
+ /* absolute path or cwd-relative path specified for session name: infer session folder
+ from what was given.
+ */
+
session_path = Glib::path_get_dirname (session_name);
session_name = Glib::path_get_basename (session_name);
continue;
}
+ if (session_name.find ('/') != Glib::ustring::npos) {
+ MessageDialog msg (*_startup, _("To ensure compatibility with various systems\n"
+ "session names may not contain a '/' character"));
+ msg.run ();
+ ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
+ continue;
+ }
+
+ if (session_name.find ('\\') != Glib::ustring::npos) {
+ MessageDialog msg (*_startup, _("To ensure compatibility with various systems\n"
+ "session names may not contain a '\\' character"));
+ msg.run ();
+ ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
+ continue;
+ }
+
_session_is_new = true;
}
return;
}
- unload_session (true);
+ if (unload_session (true)) {
+ return;
+ }
ARDOUR_COMMAND_LINE::session_name = "";
get_session_parameters (true, false);
}
}
+void
+ARDOUR_UI::launch_chat ()
+{
+#ifdef __APPLE__
+ open_uri("http://webchat.freenode.net/?channels=ardour-osx");
+#else
+ open_uri("http://webchat.freenode.net/?channels=ardour");
+#endif
+}
+
void
ARDOUR_UI::show_about ()
{
about->signal_response().connect(sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response) );
}
+ about->set_transient_for(*editor);
about->show_all ();
}
const string dead_sound_directory = _session->session_directory().dead_sound_path().to_string();
-
-
-
/* subst:
%1 - number of files removed
%2 - location of "dead_sounds"
*/
const char* bprefix;
+ double space_adjusted = 0;
- if (rep.space < 1048576.0f) {
+ if (rep.space < 100000.0f) {
bprefix = X_("kilo");
- } else if (rep.space < 1048576.0f * 1000) {
+ } else if (rep.space < 1000000.0f * 1000) {
bprefix = X_("mega");
+ space_adjusted = truncf((float)rep.space / 1000.0);
} else {
bprefix = X_("giga");
+ space_adjusted = truncf((float)rep.space / (1000000.0 * 1000));
}
if (removed > 1) {
- txt.set_text (string_compose (plural_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
+ txt.set_text (string_compose (plural_msg, removed, _session->path() + "dead_sounds", space_adjusted, bprefix));
} else {
- txt.set_text (string_compose (singular_msg, removed, dead_sound_directory, (float) rep.space / 1024.0f, bprefix));
+ txt.set_text (string_compose (singular_msg, removed, _session->path() + "dead_sounds", space_adjusted, bprefix));
}
dhbox.pack_start (*dimage, true, false, 5);
void show_splash ();
void hide_splash ();
+ void launch_chat ();
void show_about ();
void hide_about ();
act = ActionManager::register_toggle_action (common_actions, X_("ToggleBigClock"), _("Big Clock"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_big_clock_window));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::register_action (common_actions, X_("About"), _("About"), sigc::mem_fun(*this, &ARDOUR_UI::show_about));
+ ActionManager::register_action (common_actions, X_("Chat"), _("Chat"), sigc::mem_fun(*this, &ARDOUR_UI::launch_chat));
ActionManager::register_toggle_action (common_actions, X_("ToggleThemeManager"), _("Theme Manager"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_theme_manager));
ActionManager::register_toggle_action (common_actions, X_("ToggleKeyEditor"), _("Key Bindings"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_key_editor));
ActionManager::register_toggle_action (common_actions, X_("ToggleBundleManager"), _("Bundle Manager"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_bundle_manager));
// FIXME: ick
height -= 2;
- _height = height;
-
for (uint32_t n=0; n < wcnt; ++n) {
gdouble ht;
manage_zero_line ();
reset_fade_shapes ();
-
- if (name_pixbuf) {
- name_pixbuf->raise_to_top();
- }
-
}
void
void
CrossfadeEditor::Point::move_to (double nx, double ny, double xfract, double yfract)
{
+ if ( xfract < 0.0 ) {
+ xfract = 0.0;
+ } else if ( xfract > 1.0 ) {
+ xfract = 1.0;
+ }
+
+ if ( yfract < 0.0 ) {
+ yfract = 0.0;
+ } else if ( yfract > 1.0 ) {
+ yfract = 1.0;
+ }
+
const double half_size = rint(size/2.0);
double x1 = nx - half_size;
double x2 = nx + half_size;
have_pending_keyboard_selection = false;
_follow_playhead = true;
+ _stationary_playhead = false;
_xfade_visibility = true;
editor_ruler_menu = 0;
no_ruler_shown_update = false;
region_mute_item->set_active();
fooc.block (false);
}
+
+ items.push_back (MenuElem (_("Transpose"), mem_fun(*this, &Editor::pitch_shift_regions)));
if (!Profile->get_sae()) {
items.push_back (CheckMenuElem (_("Opaque")));
move (x, y);
if (_session && (prop = node.property ("playhead"))) {
- nframes64_t pos = atol (prop->value().c_str());
+ nframes64_t pos;
+ sscanf (prop->value().c_str(), "%" PRIi64, &pos);
playhead_cursor->set_position (pos);
} else {
playhead_cursor->set_position (0);
}
}
+ if ((prop = node.property ("stationary-playhead"))) {
+ bool yn = (prop->value() == "yes");
+ set_stationary_playhead (yn);
+ RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
+ if (act) {
+ RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
+ if (tact->get_active() != yn) {
+ tact->set_active (yn);
+ }
+ }
+ }
+
if ((prop = node.property ("region-list-sort-type"))) {
RegionListSortType st;
_regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
node->add_property ("show-measures", _show_measures ? "yes" : "no");
node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
+ node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
node->add_property ("mouse-mode", enum2str(mouse_mode));
}
}
+void
+Editor::toggle_stationary_playhead ()
+{
+ RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
+ if (act) {
+ RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
+ set_stationary_playhead (tact->get_active());
+ }
+}
+
+void
+Editor::set_stationary_playhead (bool yn)
+{
+ if (_stationary_playhead != yn) {
+ if ((_stationary_playhead = yn) == true) {
+ /* catch up */
+ // FIXME need a 3.0 equivalent of this 2.X call
+ // update_current_screen ();
+ }
+ instant_save ();
+ }
+}
+
void
Editor::toggle_xfade_active (boost::weak_ptr<Crossfade> wxfade)
{
return;
}
+ redo_visual_stack.push_back (current_visual_state());
+
VisualState* vs = undo_visual_stack.back();
undo_visual_stack.pop_back();
use_visual_state (*vs);
- redo_visual_stack.push_back (vs);
}
void
return;
}
+ undo_visual_stack.push_back (current_visual_state());
+
VisualState* vs = redo_visual_stack.back();
redo_visual_stack.pop_back();
use_visual_state (*vs);
- undo_visual_stack.push_back (vs);
}
void
void
Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
{
+ cerr << "add tav " << view << " with hdelta = " << h << endl;
+
if (resize_idle_id < 0) {
resize_idle_id = g_idle_add (_idle_resizer, this);
_pending_resize_amount = 0;
_pending_resize_amount += h;
_pending_resize_view = view;
+ cerr << "Pending resize amount initially set at " << _pending_resize_amount << endl;
+
min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
if (selection->tracks.contains (_pending_resize_view)) {
/* clamp */
if (uint32_t (min_resulting) < TimeAxisView::hSmall) {
_pending_resize_amount += TimeAxisView::hSmall - min_resulting;
+ cerr << "pending resize amount = " << _pending_resize_amount << endl;
}
}
bool
Editor::idle_resize ()
{
+ cerr << "Idle resize, pra = " << _pending_resize_amount
+ << " set height to " << _pending_resize_view->current_height() << " + " << _pending_resize_amount << endl;
+
_pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
}
}
+ _pending_resize_amount = 0;
flush_canvas ();
_group_tabs->set_dirty ();
resize_idle_id = -1;
playhead_cursor->set_position (frame);
}
-#undef CONTINUOUS_SCROLL
-#ifndef CONTINUOUS_SCROLL
+ if (!_stationary_playhead) {
- if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0) {
- reset_x_origin_to_follow_playhead ();
- }
+ if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0) {
+ reset_x_origin_to_follow_playhead ();
+ }
-#else // CONTINUOUS_SCROLL
-
- /* don't do continuous scroll till the new position is in the rightmost quarter of the
- editor canvas
- */
-
- double target = ((double)frame - (double)current_page_frames()/2.0) / frames_per_unit;
- if (target <= 0.0) {
- target = 0.0;
- }
- if (fabs(target - current) < current_page_frames() / frames_per_unit) {
- target = (target * 0.15) + (current * 0.85);
- } else {
- /* relax */
- }
-
- current = target;
- horizontal_adjustment.set_value (current);
-
-#endif // CONTINUOUS_SCROLL
+ } else {
+
+ /* don't do continuous scroll till the new position is in the rightmost quarter of the
+ editor canvas
+ */
+#if 0
+ // FIXME DO SOMETHING THAT WORKS HERE - this is 2.X code
+ double target = ((double)frame - (double)current_page_frames()/2.0) / frames_per_unit;
+ if (target <= 0.0) {
+ target = 0.0;
+ }
+ if (fabs(target - current) < current_page_frames() / frames_per_unit) {
+ target = (target * 0.15) + (current * 0.85);
+ } else {
+ /* relax */
+ }
+
+ current = target;
+ horizontal_adjustment.set_value (current);
+#endif
+ }
}
}
/* playhead/screen stuff */
+ void set_stationary_playhead (bool yn);
+ void toggle_stationary_playhead ();
+ bool stationary_playhead() const { return _stationary_playhead; }
+
void set_follow_playhead (bool yn);
void toggle_follow_playhead ();
bool follow_playhead() const { return _follow_playhead; }
void goto_visual_state (uint32_t);
void save_visual_state (uint32_t);
+ void queue_draw_resize_line (int at);
+ void start_resize_line_ops ();
+ void end_resize_line_ops ();
+
TrackViewList const & get_track_views () {
return track_views;
}
bool _show_measures;
/// true if the editor should follow the playhead, otherwise false
bool _follow_playhead;
+ /// true if we scroll the tracks rather than the playhead
+ bool _stationary_playhead;
/// true if waveforms should be shown while recording audio tracks, otherwise false
bool _show_waveforms_recording;
act = ActionManager::register_action (editor_actions, "track-record-enable-toggle", _("Toggle Record Enable"), sigc::mem_fun(*this, &Editor::toggle_record_enable));
ActionManager::session_sensitive_actions.push_back (act);
+ ActionManager::track_selection_sensitive_actions.push_back (act);
for (int i = 1; i <= 12; ++i) {
string const a = string_compose (X_("save-visual-state-%1"), i);
act = ActionManager::register_action (editor_actions, "move-selected-tracks-up", _("Move Selected Tracks Up"), sigc::bind (sigc::mem_fun(*_routes, &EditorRoutes::move_selected_tracks), true));
ActionManager::session_sensitive_actions.push_back (act);
+ ActionManager::track_selection_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "move-selected-tracks-down", _("Move Selected Tracks Down"), sigc::bind (sigc::mem_fun(*_routes, &EditorRoutes::move_selected_tracks), false));
ActionManager::session_sensitive_actions.push_back (act);
+ ActionManager::track_selection_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "scroll-tracks-up", _("Scroll Tracks Up"), sigc::mem_fun(*this, &Editor::scroll_tracks_up));
ActionManager::session_sensitive_actions.push_back (act);
+ ActionManager::track_selection_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "scroll-tracks-down", _("Scroll Tracks Down"), sigc::mem_fun(*this, &Editor::scroll_tracks_down));
+ ActionManager::track_selection_sensitive_actions.push_back (act);
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "step-tracks-up", _("Step Tracks Up"), sigc::mem_fun(*this, &Editor::scroll_tracks_up_line));
+ ActionManager::track_selection_sensitive_actions.push_back (act);
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "step-tracks-down", _("Step Tracks Down"), sigc::mem_fun(*this, &Editor::scroll_tracks_down_line));
ActionManager::session_sensitive_actions.push_back (act);
+ ActionManager::track_selection_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "scroll-backward", _("Scroll Backward"), sigc::bind (sigc::mem_fun(*this, &Editor::scroll_backward), 0.8f));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "remove-last-capture", _("Remove Last Capture"), (sigc::mem_fun(*this, &Editor::remove_last_capture)));
ActionManager::session_sensitive_actions.push_back (act);
+ ActionManager::register_toggle_action (editor_actions, "toggle-stationary-playhead", _("Stationary Playhead"), (mem_fun(*this, &Editor::toggle_stationary_playhead)));
+
act = ActionManager::register_action (editor_actions, "insert-time", _("Insert Time"), (sigc::mem_fun(*this, &Editor::do_insert_time)));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::track_selection_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "fit-tracks", _("Fit Selected Tracks"), sigc::mem_fun(*this, &Editor::fit_selected_tracks));
ActionManager::session_sensitive_actions.push_back (act);
+ ActionManager::track_selection_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "track-height-largest", _("Largest"), sigc::bind (
sigc::mem_fun(*this, &Editor::set_track_height), TimeAxisView::hLargest));
ActionManager::session_sensitive_actions.push_back (act);
}
#ifndef GTKOSX
- if (!autoscroll_active) {
+ if (!autoscroll_active && !_stationary_playhead) {
/* force rulers and canvas to move in lock step */
while (gtk_events_pending ()) {
gtk_main_iteration ();
/* XXX this limit is also in ::set_frames_per_unit() */
- if (frames_per_unit <= 2.0 && fpu <= frames_per_unit) {
+ if (frames_per_unit <= 1.0 && fpu <= frames_per_unit) {
return;
}
d.get_vbox()->set_border_width (12);
d.get_vbox()->pack_start (hbox, false, false);
- d.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
d.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ d.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
d.set_size_request (300, -1);
d.set_position (Gtk::WIN_POS_MOUSE);
} else if (child->name() == "periodsize") {
period_size_combo.set_active_text(strval);
} else if (child->name() == "serverpath") {
- /* do not allow us to use a server path that doesn't
- exist on this system. this handles cases where
- the user has an RC file listing a serverpath
- from some other machine.
- */
- vector<string>::iterator x;
- for (x = server_strings.begin(); x != server_strings.end(); ++x) {
- if (*x == strval) {
- break;
- }
- }
- if (x != server_strings.end()) {
- serverpath_combo.set_active_text (strval);
- } else {
- warning << string_compose (_("configuration files contain a JACK server path that doesn't exist (%1)"),
- strval)
- << endmsg;
- }
+
+ /* only attempt to set this if we have bothered to look
+ up server names already. otherwise this is all
+ redundant (actually, all of this dialog/widget
+ is redundant in that case ...)
+ */
+
+ if (!server_strings.empty()) {
+ /* do not allow us to use a server path that doesn't
+ exist on this system. this handles cases where
+ the user has an RC file listing a serverpath
+ from some other machine.
+ */
+ vector<string>::iterator x;
+ for (x = server_strings.begin(); x != server_strings.end(); ++x) {
+ if (*x == strval) {
+ break;
+ }
+ }
+ if (x != server_strings.end()) {
+ serverpath_combo.set_active_text (strval);
+ } else {
+ warning << string_compose (_("configuration files contain a JACK server path that doesn't exist (%1)"),
+ strval)
+ << endmsg;
+ }
+ }
+
} else if (child->name() == "driver") {
driver_combo.set_active_text(strval);
} else if (child->name() == "interface") {
below). be sure to include a descender.
*/
- set_size_request_to_display_given_text (*automate_button.get_child(), _("Mgnual"), 5, 5);
+ set_size_request_to_display_given_text (automate_button, _("Mgnual"), 15, 10);
ignore_change = 0;
display = 0;
#include "ardour/track.h"
#include "ardour/audio_track.h"
#include "ardour/midi_track.h"
+#include "ardour/mtdm.h"
#include "ardour/data_type.h"
#include "ardour/port.h"
#include "ardour/bundle.h"
}
PortInsertUI::PortInsertUI (Gtk::Window* parent, ARDOUR::Session* sess, boost::shared_ptr<ARDOUR::PortInsert> pi)
- : input_selector (parent, sess, pi->input())
- , output_selector (parent, sess, pi->output())
+ : _pi (pi)
+ , latency_button (_("Measure Latency"))
+ , input_selector (parent, sess, pi->input())
+ , output_selector (parent, sess, pi->output())
{
+ latency_hbox.pack_start (latency_button, false, false);
+ latency_hbox.pack_start (latency_display, false, false);
+ latency_frame.add (latency_hbox);
+
output_selector.set_min_height_divisor (2);
input_selector.set_min_height_divisor (2);
-
+
+ pack_start (latency_frame);
pack_start (output_selector, true, true);
pack_start (input_selector, true, true);
+
+ latency_button.signal_toggled().connect (mem_fun (*this, &PortInsertUI::latency_button_toggled));
}
+bool
+PortInsertUI::check_latency_measurement ()
+{
+ MTDM* mtdm = _pi->mtdm ();
+
+ if (mtdm->resolve () < 0) {
+ latency_display.set_text (_("No signal detected"));
+ return true;
+ }
+
+ if (mtdm->err () > 0.3) {
+ mtdm->invert ();
+ mtdm->resolve ();
+ }
+
+ char buf[64];
+ nframes_t sample_rate = AudioEngine::instance()->frame_rate();
+
+ if (sample_rate == 0) {
+ latency_display.set_text (_("Disconnected from audio engine"));
+ _pi->stop_latency_detection ();
+ return false;
+ }
+
+ snprintf (buf, sizeof (buf), "%10.3lf frames %10.3lf ms", mtdm->del (), mtdm->del () * 1000.0f/sample_rate);
+
+ bool solid = true;
+
+ if (mtdm->err () > 0.2) {
+ strcat (buf, " ??");
+ solid = false;
+ }
+
+ if (mtdm->inv ()) {
+ strcat (buf, " (Inv)");
+ solid = false;
+ }
+
+ if (solid) {
+ _pi->set_measured_latency ((nframes_t) rint (mtdm->del()));
+ strcat (buf, " (set)");
+ }
+
+ latency_display.set_text (buf);
+ return true;
+}
+
+void
+PortInsertUI::latency_button_toggled ()
+{
+ if (latency_button.get_active ()) {
+
+ _pi->start_latency_detection ();
+ latency_display.set_text (_("Detecting ..."));
+ latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &PortInsertUI::check_latency_measurement), 250);
+
+ } else {
+ _pi->stop_latency_detection ();
+ latency_timeout.disconnect ();
+ }
+}
+
+
void
PortInsertUI::redisplay ()
{
void finished (IOSelector::Result);
private:
+ boost::shared_ptr<ARDOUR::PortInsert> _pi;
+
+ Gtk::ToggleButton latency_button;
IOSelector input_selector;
IOSelector output_selector;
+ Gtk::Label latency_display;
+ Gtk::Frame latency_frame;
+ Gtk::HBox latency_hbox;
+ sigc::connection latency_timeout;
+
+ bool check_latency_measurement ();
+ void latency_button_toggled ();
};
class PortInsertWindow : public ArdourDialog
#endif
+static gboolean
+tell_about_jack_death (void* /* ignored */)
+{
+ if (AudioEngine::instance()->processed_frames() == 0) {
+ /* died during startup */
+ MessageDialog msg (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK);
+ msg.set_position (Gtk::WIN_POS_CENTER);
+ msg.set_secondary_text (_(
+"JACK exited unexpectedly, and without notifying Ardour.\n\
+\n\
+This could be due to misconfiguration or to an error inside JACK.\n\
+\n\
+Click OK to exit Ardour."));
+
+ msg.run ();
+ _exit (0);
+
+ } else {
+
+ /* engine has already run, so this is a mid-session JACK death */
+
+ MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE));
+ msg->set_secondary_text (_(
+"JACK exited unexpectedly, and without notifying Ardour.\n\
+\n\
+This is probably due to an error inside JACK. You should restart JACK\n\
+and reconnect Ardour to it, or exit Ardour now. You cannot save your\n\
+session at this time, because we would lose your connection information.\n"));
+ msg->present ();
+ }
+ return false; /* do not call again */
+}
+
static void
-sigpipe_handler (int /*sig*/)
+sigpipe_handler (int sig)
{
- cerr << _("SIGPIPE received - JACK has probably died") << endl;
+ /* XXX fix this so that we do this again after a reconnect to JACK
+ */
+
+ static bool done_the_jack_thing = false;
+
+ if (!done_the_jack_thing) {
+ AudioEngine::instance()->died ();
+ g_idle_add (tell_about_jack_death, 0);
+ done_the_jack_thing = true;
+ }
}
#ifdef HAVE_LV2
/* setup name pixbuf sizes */
name_font = get_font_for_style (N_("MarkerText"));
- Gtk::Window win;
Gtk::Label foo;
- win.add (foo);
Glib::RefPtr<Pango::Layout> layout = foo.create_pango_layout (X_("Hg")); /* ascender + descender */
int width;
- int height;
layout->set_font_description (*name_font);
- Gtkmm2ext::get_ink_pixel_size (layout, width, height);
- name_height = height + 6;
+ Gtkmm2ext::get_ink_pixel_size (layout, width, name_height);
name_pixbuf = new ArdourCanvas::Pixbuf(*group);
name_pixbuf->property_x() = label_offset;
+ name_pixbuf->property_y() = (13/2) - (name_height/2);
set_name (annotation.c_str());
ARDOUR_UI::instance()->set_tip (&group_button, _("Mix group"), "");
group_button.add (group_label);
group_button.set_name ("MixerGroupButton");
+ Gtkmm2ext::set_size_request_to_display_given_text (group_button, "Group", 2, 2);
group_label.set_name ("MixerGroupButtonLabel");
comment_button.set_name ("MixerCommentButton");
RouteGroup *rg = _route->route_group();
if (rg) {
- /* XXX: this needs a better algorithm */
- string truncated = rg->name ();
- if (truncated.length () > 5) {
- truncated = truncated.substr (0, 5);
- }
- group_label.set_text (truncated);
+ group_label.set_text (PBD::short_version (rg->name(), 5));
} else {
switch (_width) {
case Wide:
#include <fstream>
#include <gtkmm/stock.h>
+#include "pbd/openuri.h"
+
#include "ardour/ardour.h"
#include "ardour/filesystem_paths.h"
/* we don't care if it fails */
- open_uri (uri);
+ PBD::open_uri (uri);
}
void
NagScreen::offer_to_subscribe ()
{
const char* uri = "http://ardour.org/subscribe";
-
- if (open_uri (uri)) {
+
+ if (PBD::open_uri (uri)) {
mark_subscriber ();
}
}
-bool
-NagScreen::open_uri (const char* uri)
-{
-#ifdef HAVE_GTK_OPEN_URI
- GError* err;
- return gtk_open_uri (0, uri, GDK_CURRENT_TIME, &err);
-#else
-#ifdef GTKOSX
- extern bool cocoa_open_url (const char*);
- return cocoa_open_url (uri);
-#else
- std::string command = "xdg-open ";
- command += uri;
- spawn_command_line_async (command);
-
- return true;
-#endif
-#endif
-}
void mark_affirmed_subscriber ();
void offer_to_donate ();
void offer_to_subscribe ();
- bool open_uri (const char*);
static bool is_subscribed (bool& really);
};
ProcessorBox* ProcessorBox::_current_processor_box = 0;
RefPtr<Action> ProcessorBox::paste_action;
+RefPtr<Action> ProcessorBox::cut_action;
Glib::RefPtr<Gdk::Pixbuf> SendProcessorEntry::_slider;
ProcessorEntry::ProcessorEntry (boost::shared_ptr<Processor> p, Width w)
}
}
+ cut_action->set_sensitive (can_cut());
paste_action->set_sensitive (!_rr_selection.processors.empty());
processor_menu->popup (1, arg);
}
}
+bool
+ProcessorBox::can_cut () const
+{
+ vector<boost::shared_ptr<Processor> > sel;
+
+ get_selected_processors (sel);
+
+ /* cut_processors () does not cut inserts */
+
+ for (vector<boost::shared_ptr<Processor> >::const_iterator i = sel.begin (); i != sel.end (); ++i) {
+
+ if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
+ (boost::dynamic_pointer_cast<Send>((*i)) != 0) ||
+ (boost::dynamic_pointer_cast<Return>((*i)) != 0)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void
ProcessorBox::cut_processors ()
{
}
void
-ProcessorBox::get_selected_processors (ProcSelection& processors)
+ProcessorBox::get_selected_processors (ProcSelection& processors) const
{
- list<ProcessorEntry*> selection = processor_display.selection ();
- for (list<ProcessorEntry*>::iterator i = selection.begin(); i != selection.end(); ++i) {
+ const list<ProcessorEntry*> selection = processor_display.selection ();
+ for (list<ProcessorEntry*>::const_iterator i = selection.begin(); i != selection.end(); ++i) {
processors.push_back ((*i)->processor ());
}
}
sigc::ptr_fun (ProcessorBox::rb_clear_post));
/* standard editing stuff */
- act = ActionManager::register_action (popup_act_grp, X_("cut"), _("Cut"),
- sigc::ptr_fun (ProcessorBox::rb_cut));
- ActionManager::plugin_selection_sensitive_actions.push_back(act);
+ cut_action = ActionManager::register_action (popup_act_grp, X_("cut"), _("Cut"),
+ sigc::ptr_fun (ProcessorBox::rb_cut));
+ ActionManager::plugin_selection_sensitive_actions.push_back(cut_action);
act = ActionManager::register_action (popup_act_grp, X_("copy"), _("Copy"),
sigc::ptr_fun (ProcessorBox::rb_copy));
ActionManager::plugin_selection_sensitive_actions.push_back(act);
void rename_processors ();
void for_selected_processors (void (ProcessorBox::*pmf)(boost::shared_ptr<ARDOUR::Processor>));
- void get_selected_processors (ProcSelection&);
+ void get_selected_processors (ProcSelection&) const;
+ bool can_cut() const;
+
+ static Glib::RefPtr<Gtk::Action> cut_action;
static Glib::RefPtr<Gtk::Action> paste_action;
void paste_processor_state (const XMLNodeList&, boost::shared_ptr<ARDOUR::Processor>);
virtual void set_selected_mixer_strip (TimeAxisView&) = 0;
virtual void hide_track_in_display (TimeAxisView& tv, bool temporary = false) = 0;
+ virtual void set_stationary_playhead (bool yn) = 0;
+ virtual void toggle_stationary_playhead () = 0;
+ virtual bool stationary_playhead() const = 0;
+
/** Set whether the editor should follow the playhead.
* @param yn true to follow playhead, otherwise false.
*/
current_visible_sync_position = other.current_visible_sync_position;
valid = false;
_pixel_width = other._pixel_width;
- _height = other._height;
GhostRegion::CatchDeletion.connect (*this, ui_bind (&RegionView::remove_ghost, this, _1), gui_context());
}
current_visible_sync_position = other.current_visible_sync_position;
valid = false;
_pixel_width = other._pixel_width;
- _height = other._height;
GhostRegion::CatchDeletion.connect (*this, ui_bind (&RegionView::remove_ghost, this, _1), gui_context());
}
editor = 0;
valid = true;
in_destructor = false;
- _height = 0;
wait_for_data = wfd;
sync_mark = 0;
sync_line = 0;
bool valid; ///< see StreamView::redisplay_diskstream()
bool _enable_display; ///< see StreamView::redisplay_diskstream()
double _pixel_width;
- double _height;
bool in_destructor;
bool wait_for_data;
}
+struct PlaylistSorter {
+ bool operator() (boost::shared_ptr<Playlist> a, boost::shared_ptr<Playlist> b) const {
+ return a->sort_id() < b->sort_id();
+ }
+};
+
void
RouteTimeAxisView::build_playlist_menu (Gtk::Menu * menu)
{
delete playlist_menu;
- playlist_menu = new Menu;
- playlist_menu->set_name ("ArdourContextMenu");
- vector<boost::shared_ptr<Playlist> > playlists;
+ vector<boost::shared_ptr<Playlist> > playlists, playlists_ds;
boost::shared_ptr<Diskstream> ds = get_diskstream();
RadioMenuItem::Group playlist_group;
_session->playlists->get (playlists);
- for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
-
- if ((*i)->get_orig_diskstream_id() == ds->id()) {
- playlist_items.push_back (RadioMenuElem (playlist_group, (*i)->name(), sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::use_playlist),
- boost::weak_ptr<Playlist> (*i))));
-
- if (ds->playlist()->id() == (*i)->id()) {
- static_cast<RadioMenuItem*>(&playlist_items.back())->set_active();
- }
- } else if (ds->playlist()->id() == (*i)->id()) {
- playlist_items.push_back (RadioMenuElem (playlist_group, (*i)->name(), sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::use_playlist),
- boost::weak_ptr<Playlist>(*i))));
- static_cast<RadioMenuItem*>(&playlist_items.back())->set_active();
-
+ /* find the playlists for this diskstream */
+ for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
+ if (((*i)->get_orig_diskstream_id() == ds->id()) || (ds->playlist()->id() == (*i)->id())) {
+ playlists_ds.push_back(*i);
+ }
+ }
+
+ /* sort the playlists */
+ PlaylistSorter cmp;
+ sort(playlists_ds.begin(), playlists_ds.end(), cmp);
+
+ /* add the playlists to the menu */
+ for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists_ds.begin(); i != playlists_ds.end(); ++i) {
+ playlist_items.push_back (RadioMenuElem (playlist_group, (*i)->name()));
+ RadioMenuItem *item = static_cast<RadioMenuItem*>(&playlist_items.back());
+ item->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::use_playlist), item, boost::weak_ptr<Playlist> (*i)));
+
+ if (ds->playlist()->id() == (*i)->id()) {
+ item->set_active();
+
}
}
-
+
playlist_items.push_back (SeparatorElem());
playlist_items.push_back (MenuElem (_("Rename"), sigc::mem_fun(*this, &RouteTimeAxisView::rename_current_playlist)));
playlist_items.push_back (SeparatorElem());
}
void
-RouteTimeAxisView::use_playlist (boost::weak_ptr<Playlist> wpl)
+RouteTimeAxisView::use_playlist (RadioMenuItem *item, boost::weak_ptr<Playlist> wpl)
{
assert (is_track());
+ // exit if we were triggered by deactivating the old playlist
+ if (!item->get_active()) {
+ return;
+ }
+
boost::shared_ptr<Playlist> pl (wpl.lock());
if (!pl) {
if (apl) {
if (get_diskstream()->playlist() == apl) {
- // radio button cotnrols mean this function is called for both the
- // old and new playlist
+ // exit when use_playlist is called by the creation of the playlist menu
+ // or the playlist choice is unchanged
return;
}
get_diskstream()->use_playlist (apl);
virtual Gtk::Menu* build_mode_menu() { return 0; }
virtual Gtk::Menu* build_color_mode_menu() { return 0; }
- void use_playlist (boost::weak_ptr<ARDOUR::Playlist>);
+ void use_playlist (Gtk::RadioMenuItem *item, boost::weak_ptr<ARDOUR::Playlist> wpl);
ArdourCanvas::SimpleRect* timestretch_rect;
// Primary-button2 click is the midi binding click
// button2-click is "momentary"
- if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
- return false;
- }
+
+ if (mute_button->on_button_press_event (ev)) {
+ return true;
+ }
_mute_release = new SoloMuteRelease (_route->muted ());
}
// Primary-button2 click is the midi binding click
// button2-click is "momentary"
- if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
- return false;
- }
+ if (solo_button->on_button_press_event (ev)) {
+ return true;
+ }
_solo_release = new SoloMuteRelease (_route->soloed());
}
if (!ignore_toggle && is_track() && rec_enable_button) {
- if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
+ if (Keyboard::is_button2_event (ev)) {
// do nothing on midi sigc::bind event
- return false;
+ return rec_enable_button->on_button_press_event (ev);
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
chooser.set_select_multiple (true);
chooser.signal_update_preview().connect(sigc::mem_fun(*this, &SoundFileBrowser::update_preview));
chooser.signal_file_activated().connect (sigc::mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
+#ifdef GTKOSX
+ /* some broken redraw behaviour - this is a bandaid */
+ chooser.signal_selection_changed().connect (mem_fun (chooser, &Widget::queue_draw));
+#endif
if (!persistent_folder.empty()) {
chooser.set_current_folder (persistent_folder);
channel_strings.push_back (_("sequence files"));
}
if (same_size) {
- channel_strings.push_back (_("all files in one region"));
+ channel_strings.push_back (_("all files in one track"));
}
}
resizer.signal_button_press_event().connect (sigc::mem_fun (*this, &TimeAxisView::resizer_button_press));
resizer.signal_button_release_event().connect (sigc::mem_fun (*this, &TimeAxisView::resizer_button_release));
resizer.signal_motion_notify_event().connect (sigc::mem_fun (*this, &TimeAxisView::resizer_motion));
+
resizer.set_events (Gdk::BUTTON_PRESS_MASK|
Gdk::BUTTON_RELEASE_MASK|
Gdk::POINTER_MOTION_MASK|
bool
TimeAxisView::resizer_motion (GdkEventMotion* ev)
{
- if (_resize_drag_start < 0) {
- return true;
- }
-
- int32_t const delta = (int32_t) floor (ev->y_root - _resize_drag_start);
- _editor.add_to_idle_resize (this, delta);
- _resize_drag_start = ev->y_root;
+ if (_resize_drag_start >= 0) {
+ int32_t const delta = (int32_t) floor (ev->y_root - _resize_drag_start);
+ _editor.add_to_idle_resize (this, delta);
+ _resize_drag_start = ev->y_root;
+ }
return true;
}
TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group& parent, TimeAxisView& tv, double spu, Gdk::Color const & base_color,
nframes64_t start, nframes64_t duration, bool recording,
Visibility vis)
- : trackview (tv), _recregion(recording)
+ : trackview (tv), _height (1.0), _recregion(recording)
{
if (!have_name_font) {
void
TimeAxisViewItem::set_height (double height)
{
+ _height = height;
+
if (name_highlight) {
if (height < NAME_HIGHLIGHT_THRESH) {
name_highlight->hide ();
if (name_highlight) {
- double height = name_highlight->property_y2 ();
-
- if (height < NAME_HIGHLIGHT_THRESH) {
+ if (_height < NAME_HIGHLIGHT_THRESH) {
name_highlight->hide();
high_enough_for_name = false;
} else {
}
high_enough_for_name = true;
}
-
+
if (visibility & FullWidthNameHighlight) {
name_highlight->property_x2() = pixel_width;
} else {
frame_handle_end->property_x2() = pixel_width;
}
}
+
+ update_name_pixbuf_visibility ();
}
void
ArdourCanvas::SimpleRect* frame_handle_start;
ArdourCanvas::SimpleRect* frame_handle_end;
+ double _height;
Visibility visibility;
bool _recregion;
nframes_t _processed_frames;
bool _freewheeling;
bool _freewheel_pending;
- bool _freewheel_thread_registered;
boost::function<int(nframes_t)> freewheel_action;
bool reconnect_on_halt;
int _usecs_per_cycle;
bool used () const { return _refcnt != 0; }
bool set_name (const std::string& str);
+ int sort_id() { return _sort_id; }
const DataType& data_type() const { return _type; }
std::set<boost::shared_ptr<Region> > all_regions; /* all regions ever added to this playlist */
PBD::ScopedConnectionList region_state_changed_connections;
DataType _type;
+ int _sort_id;
mutable gint block_notifications;
mutable gint ignore_state_changes;
mutable Glib::RecMutex region_lock;
virtual void flush_notifications ();
void clear_pending ();
+ void _set_sort_id ();
+
void notify_region_removed (boost::shared_ptr<Region>);
void notify_region_added (boost::shared_ptr<Region>);
void notify_length_changed ();
#include "ardour/types.h"
class XMLNode;
+class MTDM;
namespace ARDOUR {
uint32_t bit_slot() const { return bitslot; }
+ void start_latency_detection ();
+ void stop_latency_detection ();
+
+ MTDM* mtdm () const { return _mtdm; }
+ void set_measured_latency (nframes_t);
+
private:
/* disallow copy construction */
PortInsert (const PortInsert&);
boost::shared_ptr<Delivery> _out;
uint32_t bitslot;
-};
+ MTDM* _mtdm;
+ bool _latency_detect;
+ nframes_t _latency_flush_frames;
+ nframes_t _measured_latency;};
} // namespace ARDOUR
CONFIG_VARIABLE (uint32_t, periodic_safety_backup_interval, "periodic-safety-backup-interval", 120)
CONFIG_VARIABLE (float, automation_interval, "automation-interval", 50)
CONFIG_VARIABLE (bool, sync_all_route_ordering, "sync-all-route-ordering", true)
-CONFIG_VARIABLE (bool, only_copy_imported_files, "only-copy-imported-files", true)
+CONFIG_VARIABLE (bool, only_copy_imported_files, "only-copy-imported-files", false)
CONFIG_VARIABLE (bool, new_plugins_active, "new-plugins-active", true)
CONFIG_VARIABLE (std::string, keyboard_layout, "keyboard-layout", "ansi")
CONFIG_VARIABLE (std::string, default_bindings, "default-bindings", "ardour")
_jack = 0;
_frame_rate = 0;
_buffer_size = 0;
- _freewheel_thread_registered = false;
_freewheeling = false;
m_meter_thread = 0;
GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
if (onoff != _freewheeling) {
-
- if (onoff) {
- _freewheel_thread_registered = false;
- }
-
- return jack_set_freewheel (_priv_jack, onoff);
-
+ return jack_set_freewheel (_priv_jack, onoff);
+
} else {
- /* already doing what has been asked for */
- return 0;
+ /* already doing what has been asked for */
+ return 0;
}
}
/* no existing/complete transient info */
+ static bool analyse_dialog_shown = false; /* global per instance of Ardour */
+
if (!Config->get_auto_analyse_audio()) {
- pl->session().Dialog (_("\
-You have requested an operation that requires audio analysis.\n\n\
+ if (!analyse_dialog_shown) {
+ pl->session().Dialog (_("\
+You have requested an operation that requires audio analysis.\n\n \
You currently have \"auto-analyse-audio\" disabled, which means\n\
that transient data must be generated every time it is required.\n\n\
If you are doing work that will require transient data on a\n\
regular basis, you should probably enable \"auto-analyse-audio\"\n\
-then quit ardour and restart."));
++then quit ardour and restart.\n\n\
++This dialog will not display again. But you may notice a slight delay\n\
++in this and future transient-detection operations.\n\
++"));
+ analyse_dialog_shown = true;
+ }
}
TransientDetector t (pl->session().frame_rate());
_out = out;
_anchor_point = ap;
_fixed = true;
+ _follow_overlap = false;
initialize ();
}
static bool
create_mono_sources_for_writing (const vector<string>& new_paths, Session& sess,
uint samplerate, vector<boost::shared_ptr<Source> >& newfiles,
- nframes64_t /*timeline_position*/)
+ framepos_t timeline_position)
{
for (vector<string>::const_iterator i = new_paths.begin(); i != new_paths.end(); ++i)
{
}
newfiles.push_back(boost::dynamic_pointer_cast<Source>(source));
+
+ /* for audio files, reset the timeline position so that any BWF-ish
+ information in the original files we are importing from is maintained.
+ */
+
+ boost::shared_ptr<AudioFileSource> afs;
+ afs = boost::dynamic_pointer_cast<AudioFileSource>(source);
+ afs->set_timeline_position(timeline_position);
}
return true;
}
get_best_session_directory_for_new_source (),
channels);
Sources newfiles;
- nframes64_t natural_position = source ? source->natural_position() : 0;
+ framepos_t natural_position = source ? source->natural_position() : 0;
if (status.replace_existing_source) {
fatal << "THIS IS NOT IMPLEMENTED YET, IT SHOULD NEVER GET CALLED!!! DYING!" << endmsg;
status.cancel = !map_existing_mono_sources (new_paths, *this, frame_rate(), newfiles, this);
} else {
- status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles, natural_position);
+ status.cancel = !create_mono_sources_for_writing (new_paths, *this, frame_rate(), newfiles, natural_position);
}
// copy on cancel/failure so that any files that were created will be removed below
for (Sources::iterator x = all_new_sources.begin(); x != all_new_sources.end(); ) {
if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(*x)) != 0) {
- afs->update_header(0, *now, xnow);
+ afs->update_header((*x)->natural_position(), *now, xnow);
afs->done_with_peakfile_writes ();
/* now that there is data there, requeue the file for analysis */
sr_scaling = true;
}
- /* FIXME: add support for logarithmic defaults */
-
else if (LADSPA_IS_HINT_DEFAULT_LOW(prh[port].HintDescriptor)) {
if (LADSPA_IS_HINT_LOGARITHMIC(prh[port].HintDescriptor)) {
ret = exp(log(prh[port].LowerBound) * 0.75f + log(prh[port].UpperBound) * 0.25f);
#include <string>
#include <climits>
+#include <boost/lexical_cast.hpp>
+
#include "pbd/failed_constructor.h"
#include "pbd/stateful_diff_command.h"
#include "pbd/xml++.h"
init (hide);
first_set_state = false;
_name = nom;
+ _set_sort_id ();
}
init (hide);
_name = "unnamed"; /* reset by set_state */
+ _set_sort_id ();
/* set state called by derived class */
}
/* GoingAway must be emitted by derived classes */
}
+void
+Playlist::_set_sort_id ()
+{
+ /*
+ Playlists are given names like <track name>.<id>
+ or <track name>.<edit group name>.<id> where id
+ is an integer. We extract the id and sort by that.
+ */
+
+ size_t dot_position = _name.val().find_last_of(".");
+
+ if (dot_position == string::npos) {
+ _sort_id = 0;
+ } else {
+ string t = _name.val().substr(dot_position + 1);
+
+ try {
+ _sort_id = boost::lexical_cast<int>(t);
+ }
+
+ catch (boost::bad_lexical_cast e) {
+ _sort_id = 0;
+ }
+ }
+}
+
bool
Playlist::set_name (const string& str)
{
if (_refcnt > 2) {
return false;
- } else {
- return SessionObject::set_name(str);
- }
+ }
+
+ bool ret = SessionObject::set_name(str);
+ if (ret) {
+ _set_sort_id ();
+ }
+ return ret;
}
/***********************************************************************
if (prop->name() == X_("name")) {
_name = prop->value();
+ _set_sort_id ();
} else if (prop->name() == X_("id")) {
_id = prop->value();
} else if (prop->name() == X_("orig_diskstream_id")) {
#include "pbd/failed_constructor.h"
#include "pbd/xml++.h"
+#include "ardour/audioengine.h"
+#include "ardour/audio_port.h"
+#include "ardour/buffer_set.h"
#include "ardour/delivery.h"
-#include "ardour/port_insert.h"
+#include "ardour/mtdm.h"
#include "ardour/plugin.h"
#include "ardour/port.h"
+#include "ardour/port_insert.h"
#include "ardour/route.h"
-#include "ardour/buffer_set.h"
-
-#include "ardour/audioengine.h"
#include "ardour/session.h"
#include "ardour/types.h"
: IOProcessor (s, true, true, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), "")
, _out (new Delivery (s, _output, mm, _name, Delivery::Insert))
{
+ _mtdm = 0;
+ _latency_detect = false;
+ _latency_flush_frames = false;
+ _measured_latency = 0;
+
ProcessorCreated (this); /* EMIT SIGNAL */
}
, _out (new Delivery (s, _output, mm, _name, Delivery::Insert))
{
+ _mtdm = 0;
+ _latency_detect = false;
+ _latency_flush_frames = false;
+ _measured_latency = 0;
+
if (set_state (node, Stateful::loading_state_version)) {
throw failed_constructor();
}
PortInsert::~PortInsert ()
{
+ delete _mtdm;
+}
+
+void
+PortInsert::start_latency_detection ()
+{
+ if (_mtdm != 0) {
+ delete _mtdm;
+ }
+
+ _mtdm = new MTDM;
+ _latency_flush_frames = false;
+ _latency_detect = true;
+ _measured_latency = 0;
+}
+
+void
+PortInsert::stop_latency_detection ()
+{
+ _latency_flush_frames = signal_latency() + _session.engine().frames_per_cycle();
+ _latency_detect = false;
+}
+
+void
+PortInsert::set_measured_latency (nframes_t n)
+{
+ _measured_latency = n;
}
void
return;
}
+ if (_latency_detect) {
+
+ if (_input->n_ports().n_audio() != 0) {
+
+ AudioBuffer& outbuf (_output->ports().nth_audio_port(0)->get_audio_buffer (nframes));
+ Sample* in = _input->ports().nth_audio_port(0)->get_audio_buffer (nframes).data();
+ Sample* out = outbuf.data();
+
+ _mtdm->process (nframes, in, out);
+
+ outbuf.is_silent (false);
+ }
+
+ return;
+
+ } else if (_latency_flush_frames) {
+
+ /* wait for the entire input buffer to drain before picking up input again so that we can't
+ hear the remnants of whatever MTDM pumped into the pipeline.
+ */
+
+ silence (nframes);
+
+ if (_latency_flush_frames > nframes) {
+ _latency_flush_frames -= nframes;
+ } else {
+ _latency_flush_frames = 0;
+ }
+
+ return;
+ }
+
if (!_active && !_pending_active) {
/* deliver silence */
silence (nframes);
need to take that into account too.
*/
- return _session.engine().frames_per_cycle() + _input->signal_latency();
+ if (_measured_latency == 0) {
+ return _session.engine().frames_per_cycle() + _input->signal_latency();
+ } else {
+ return _measured_latency;
+ }
}
bool
675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <glibmm/ustring.h>
+
#include "ardour/port_set.h"
#include "ardour/midi_port.h"
#include "ardour/audio_port.h"
static bool sort_ports_by_name (Port* a, Port* b)
{
- return (a->name() < b->name());
+ Glib::ustring aname (a->name());
+ Glib::ustring bname (b->name());
+
+ Glib::ustring::size_type last_digit_position_a = aname.size();
+ Glib::ustring::const_reverse_iterator r_iterator = aname.rbegin();
+
+ while (r_iterator!= aname.rend() && Glib::Unicode::isdigit(*r_iterator)) {
+ r_iterator++;
+ last_digit_position_a--;
+ }
+
+ Glib::ustring::size_type last_digit_position_b = bname.size();
+ r_iterator = bname.rbegin();
+
+ while (r_iterator != bname.rend() && Glib::Unicode::isdigit(*r_iterator)) {
+ r_iterator++;
+ last_digit_position_b--;
+ }
+
+ // if some of the names don't have a number as posfix, compare as strings
+
+ if (last_digit_position_a == aname.size() or last_digit_position_b == bname.size()) {
+ return aname < bname;
+ }
+
+ const std::string prefix_a = aname.substr(0, last_digit_position_a - 1);
+ const unsigned int posfix_a = std::atoi(aname.substr(last_digit_position_a, aname.size() - last_digit_position_a).c_str());
+ const std::string prefix_b = bname.substr(0, last_digit_position_b - 1);
+ const unsigned int posfix_b = std::atoi(bname.substr(last_digit_position_b, bname.size() - last_digit_position_b).c_str());
+
+ if (prefix_a != prefix_b) {
+ return aname < bname;
+ } else {
+ return posfix_a < posfix_b;
+ }
}
void
'focus_entry.cc',
'grouped_buttons.cc',
'gtk_ui.cc',
+ 'gtkapplication.c',
'idle_adjustment.cc',
'keyboard.cc',
'motionfeedback.cc',
'-DLOCALEDIR="' + os.path.join(
os.path.normpath(bld.env['DATADIRNAME']), 'locale') + '"']
if bld.env['GTKOSX']:
- obj.source += ['sync-menu.c']
+ obj.source += ['gtkapplication_quartz.mm']
+ else:
+ obj.source += ['gtkapplication_x11.c']
def shutdown():
autowaf.shutdown()
--- /dev/null
+#ifdef WAF_BUILD
+#include "libpbd-config.h"
+#endif
+
+#include <string>
+#include <glibmm/spawn.h>
+
+#include "pbd/openuri.h"
+
+bool
+PBD::open_uri (const char* uri)
+{
+#ifdef HAVE_GTK_OPEN_URI
+ GError* err;
+ return gtk_open_uri (0, uri, GDK_CURRENT_TIME, &err);
+#else
+#ifdef __APPLE__
+ extern bool cocoa_open_url (const char*);
+ return cocoa_open_url (uri);
+#else
+ std::string command = "xdg-open ";
+ command += uri;
+ Glib::spawn_command_line_async (command);
+
+ return true;
+#endif
+#endif
+}
--- /dev/null
+#ifndef __libpbd_openuri_h__
+#define __libpbd_openuri_h__
+
+namespace PBD {
+ bool open_uri (const char*);
+}
+
+#endif
locale_guard.cc
malign.cc
mountpoint.cc
+ openuri.cc
pathscanner.cc
pool.cc
property_list.cc
REGISTER_CALLBACK (serv, "/ardour/transport_stop", "", transport_stop);
REGISTER_CALLBACK (serv, "/ardour/transport_play", "", transport_play);
REGISTER_CALLBACK (serv, "/ardour/set_transport_speed", "f", set_transport_speed);
+ REGISTER_CALLBACK (serv, "/ardour/locate", "ii", locate);
REGISTER_CALLBACK (serv, "/ardour/save_state", "", save_state);
REGISTER_CALLBACK (serv, "/ardour/prev_marker", "", prev_marker);
REGISTER_CALLBACK (serv, "/ardour/next_marker", "", next_marker);
return 0; \
}
+ PATH_CALLBACK2(locate,i,i);
PATH_CALLBACK2(route_mute,i,i);
PATH_CALLBACK2(route_solo,i,i);
PATH_CALLBACK2(route_recenable,i,i);
"-t", "raw", # /dev/zero is raw :)
"-r", $samplerate, # set sample rate
"-c", "1", # 1 channel
- "-b", # input in bytes
+ "-b", "8" # input in 8 bit chunks
"-s", # signed
"/dev/zero", # input signal
- "-w", # output 16 bit
+ "-b", "16" # input in 16 bit chunks
"-t", "wav", # format wav
$audioFileDirectory."/".$sources{$tmp}->{name}, # filename
"trim", "0", $sources{$tmp}->{calculated_length}."s" # trim silence to wanted sample amount