summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PACKAGER_README15
-rw-r--r--README2
-rw-r--r--gtk2_ardour/about.cc7
-rw-r--r--gtk2_ardour/ardour.menus.in4
-rw-r--r--gtk2_ardour/ardour_ui.cc66
-rw-r--r--gtk2_ardour/ardour_ui.h1
-rw-r--r--gtk2_ardour/ardour_ui_ed.cc1
-rw-r--r--gtk2_ardour/audio_region_view.cc7
-rw-r--r--gtk2_ardour/crossfade_edit.cc12
-rw-r--r--gtk2_ardour/editor.cc107
-rw-r--r--gtk2_ardour/editor.h10
-rw-r--r--gtk2_ardour/editor_actions.cc10
-rw-r--r--gtk2_ardour/editor_canvas.cc2
-rw-r--r--gtk2_ardour/editor_ops.cc4
-rw-r--r--gtk2_ardour/engine_dialog.cc46
-rw-r--r--gtk2_ardour/generic_pluginui.cc2
-rw-r--r--gtk2_ardour/io_selector.cc79
-rw-r--r--gtk2_ardour/io_selector.h10
-rw-r--r--gtk2_ardour/main.cc46
-rw-r--r--gtk2_ardour/marker.cc7
-rw-r--r--gtk2_ardour/mixer_strip.cc8
-rw-r--r--gtk2_ardour/nag.cc27
-rw-r--r--gtk2_ardour/nag.h1
-rw-r--r--gtk2_ardour/processor_box.cc35
-rw-r--r--gtk2_ardour/processor_box.h5
-rw-r--r--gtk2_ardour/public_editor.h4
-rw-r--r--gtk2_ardour/region_view.cc3
-rw-r--r--gtk2_ardour/region_view.h1
-rw-r--r--gtk2_ardour/route_time_axis.cc57
-rw-r--r--gtk2_ardour/route_time_axis.h2
-rw-r--r--gtk2_ardour/route_ui.cc17
-rw-r--r--gtk2_ardour/sfdb_ui.cc6
-rw-r--r--gtk2_ardour/time_axis_view.cc13
-rw-r--r--gtk2_ardour/time_axis_view_item.cc12
-rw-r--r--gtk2_ardour/time_axis_view_item.h1
-rw-r--r--libs/ardour/ardour/audioengine.h1
-rw-r--r--libs/ardour/ardour/playlist.h4
-rw-r--r--libs/ardour/ardour/port_insert.h12
-rw-r--r--libs/ardour/ardour/rc_configuration_vars.h2
-rw-r--r--libs/ardour/audioengine.cc14
-rw-r--r--libs/ardour/audioregion.cc14
-rw-r--r--libs/ardour/crossfade.cc1
-rw-r--r--libs/ardour/import.cc16
-rw-r--r--libs/ardour/ladspa_plugin.cc2
-rw-r--r--libs/ardour/playlist.cc41
-rw-r--r--libs/ardour/port_insert.cc84
-rw-r--r--libs/ardour/port_set.cc38
-rw-r--r--libs/gtkmm2ext/wscript5
-rw-r--r--libs/pbd/openuri.cc28
-rw-r--r--libs/pbd/pbd/openuri.h8
-rw-r--r--libs/pbd/wscript1
-rw-r--r--libs/surfaces/osc/osc.cc1
-rw-r--r--libs/surfaces/osc/osc.h1
-rwxr-xr-xtools/synthesize_sources.pl4
54 files changed, 703 insertions, 204 deletions
diff --git a/PACKAGER_README b/PACKAGER_README
index dd5be31c6d..3b797d3c58 100644
--- a/PACKAGER_README
+++ b/PACKAGER_README
@@ -1,15 +1,12 @@
(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.
diff --git a/README b/README
index ababed7471..9f70698de9 100644
--- a/README
+++ b/README
@@ -1,3 +1,3 @@
Please see the Ardour web site at http://ardour.org/ for all documentation..
-
+For information on building ardour: http://ardour.org/building.
diff --git a/gtk2_ardour/about.cc b/gtk2_ardour/about.cc
index e3734ec6ce..317be6f403 100644
--- a/gtk2_ardour/about.cc
+++ b/gtk2_ardour/about.cc
@@ -156,6 +156,7 @@ static const char* authors[] = {
N_("Nimal Ratnayake"),
N_("Dave Robillard"),
N_("Taybin Rutkin"),
+ N_("Andreas Ruge"),
N_("Sampo Savolainen"),
N_("Per Sigmond"),
N_("Lincoln Spiteri"),
@@ -168,7 +169,7 @@ static const char* authors[] = {
};
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"),
@@ -181,6 +182,8 @@ static const char* translators[] = {
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
};
@@ -559,7 +562,7 @@ About::About ()
}
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/"));
diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in
index d5bb7b797c..26ce7c5323 100644
--- a/gtk2_ardour/ardour.menus.in
+++ b/gtk2_ardour/ardour.menus.in
@@ -286,6 +286,7 @@
<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>
@@ -433,7 +434,10 @@
<separator/>
</menu>
<menu name='Help' action='Help'>
+#ifndef GTKOSX
<menuitem action='About'/>
+#endif
+ <menuitem action='Chat'/>
</menu>
</menubar>
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 73b4e060fb..786e14aa69 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -42,6 +42,7 @@
#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"
@@ -2036,6 +2037,7 @@ ARDOUR_UI::snapshot_session ()
prompter.set_prompt (_("Name of New Snapshot"));
prompter.set_initial_text (timebuf);
+ again:
switch (prompter.run()) {
case RESPONSE_ACCEPT:
{
@@ -2043,6 +2045,21 @@ ARDOUR_UI::snapshot_session ()
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);
@@ -2493,6 +2510,10 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
(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);
@@ -2529,6 +2550,22 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
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;
}
@@ -2556,7 +2593,9 @@ ARDOUR_UI::close_session()
return;
}
- unload_session (true);
+ if (unload_session (true)) {
+ return;
+ }
ARDOUR_COMMAND_LINE::session_name = "";
get_session_parameters (true, false);
@@ -2727,6 +2766,16 @@ ARDOUR_UI::show ()
}
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 ()
{
if (about == 0) {
@@ -2734,6 +2783,7 @@ 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 ();
}
@@ -2837,9 +2887,6 @@ require some unused files to continue to exist."));
const string dead_sound_directory = _session->session_directory().dead_sound_path().to_string();
-
-
-
/* subst:
%1 - number of files removed
%2 - location of "dead_sounds"
@@ -2848,19 +2895,22 @@ require some unused files to continue to exist."));
*/
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);
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index 25bd74b55c..e131cf5431 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -115,6 +115,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
void show_splash ();
void hide_splash ();
+ void launch_chat ();
void show_about ();
void hide_about ();
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index 532902a3d2..9630c37fae 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -218,6 +218,7 @@ ARDOUR_UI::install_actions ()
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));
diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc
index 7a0e76606e..7b97d2f882 100644
--- a/gtk2_ardour/audio_region_view.cc
+++ b/gtk2_ardour/audio_region_view.cc
@@ -473,8 +473,6 @@ AudioRegionView::set_height (gdouble height)
// FIXME: ick
height -= 2;
- _height = height;
-
for (uint32_t n=0; n < wcnt; ++n) {
gdouble ht;
@@ -503,11 +501,6 @@ AudioRegionView::set_height (gdouble height)
manage_zero_line ();
reset_fade_shapes ();
-
- if (name_pixbuf) {
- name_pixbuf->raise_to_top();
- }
-
}
void
diff --git a/gtk2_ardour/crossfade_edit.cc b/gtk2_ardour/crossfade_edit.cc
index c1201f2f9a..726194c41b 100644
--- a/gtk2_ardour/crossfade_edit.cc
+++ b/gtk2_ardour/crossfade_edit.cc
@@ -497,6 +497,18 @@ CrossfadeEditor::add_control_point (double x, double y)
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;
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index f7b68fcbf1..572e192357 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -319,6 +319,7 @@ Editor::Editor ()
have_pending_keyboard_selection = false;
_follow_playhead = true;
+ _stationary_playhead = false;
_xfade_visibility = true;
editor_ruler_menu = 0;
no_ruler_shown_update = false;
@@ -1730,6 +1731,8 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
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")));
@@ -2243,7 +2246,8 @@ Editor::set_state (const XMLNode& node, int /*version*/)
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);
@@ -2341,6 +2345,18 @@ Editor::set_state (const XMLNode& node, int /*version*/)
}
}
+ 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);
@@ -2447,6 +2463,7 @@ Editor::get_state ()
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));
@@ -3698,6 +3715,29 @@ Editor::set_follow_playhead (bool yn)
}
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)
{
boost::shared_ptr<Crossfade> xfade (wxfade.lock());
@@ -4119,10 +4159,11 @@ Editor::undo_visual_state ()
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
@@ -4132,10 +4173,11 @@ Editor::redo_visual_state ()
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
@@ -4669,6 +4711,8 @@ _idle_resizer (gpointer arg)
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;
@@ -4682,6 +4726,8 @@ Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
_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)) {
@@ -4697,6 +4743,7 @@ Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
/* clamp */
if (uint32_t (min_resulting) < TimeAxisView::hSmall) {
_pending_resize_amount += TimeAxisView::hSmall - min_resulting;
+ cerr << "pending resize amount = " << _pending_resize_amount << endl;
}
}
@@ -4704,6 +4751,9 @@ Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
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 &&
@@ -4716,6 +4766,7 @@ Editor::idle_resize ()
}
}
+ _pending_resize_amount = 0;
flush_canvas ();
_group_tabs->set_dirty ();
resize_idle_id = -1;
@@ -5121,33 +5172,33 @@ Editor::super_rapid_screen_update ()
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
+ }
}
}
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 20e7567f36..0fc433d2fb 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -357,6 +357,10 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
/* 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; }
@@ -419,6 +423,10 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
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;
}
@@ -1401,6 +1409,8 @@ public:
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;
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
index d137ed6351..ec7472df91 100644
--- a/gtk2_ardour/editor_actions.cc
+++ b/gtk2_ardour/editor_actions.cc
@@ -207,6 +207,7 @@ Editor::register_actions ()
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);
@@ -270,17 +271,23 @@ Editor::register_actions ()
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);
@@ -550,6 +557,8 @@ Editor::register_actions ()
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);
@@ -567,6 +576,7 @@ Editor::register_actions ()
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);
diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc
index 510b7e019f..4ea6d27ea2 100644
--- a/gtk2_ardour/editor_canvas.cc
+++ b/gtk2_ardour/editor_canvas.cc
@@ -801,7 +801,7 @@ Editor::scroll_canvas_horizontally ()
}
#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 ();
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index d4e8f4b54f..f7fe6e7b4a 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -1555,7 +1555,7 @@ Editor::temporal_zoom (gdouble fpu)
/* 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;
}
@@ -2512,8 +2512,8 @@ Editor::rename_region()
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);
diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc
index 3213761c78..3717feb038 100644
--- a/gtk2_ardour/engine_dialog.cc
+++ b/gtk2_ardour/engine_dialog.cc
@@ -1255,24 +1255,34 @@ EngineControl::set_state (const XMLNode& root)
} 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") {
diff --git a/gtk2_ardour/generic_pluginui.cc b/gtk2_ardour/generic_pluginui.cc
index 636cdbc894..c8aa1f737d 100644
--- a/gtk2_ardour/generic_pluginui.cc
+++ b/gtk2_ardour/generic_pluginui.cc
@@ -322,7 +322,7 @@ GenericPluginUI::ControlUI::ControlUI ()
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;
diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc
index 615ce9d69f..fd9ff2458d 100644
--- a/gtk2_ardour/io_selector.cc
+++ b/gtk2_ardour/io_selector.cc
@@ -29,6 +29,7 @@
#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"
@@ -216,16 +217,88 @@ IOSelectorWindow::io_name_changed (void* src)
}
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 ()
{
diff --git a/gtk2_ardour/io_selector.h b/gtk2_ardour/io_selector.h
index a4545dbfc4..11454f8531 100644
--- a/gtk2_ardour/io_selector.h
+++ b/gtk2_ardour/io_selector.h
@@ -98,8 +98,18 @@ class PortInsertUI : public Gtk::HBox
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
diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc
index 2b16de3d70..daa2491f0f 100644
--- a/gtk2_ardour/main.cc
+++ b/gtk2_ardour/main.cc
@@ -281,10 +281,52 @@ fixup_bundle_environment ()
#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
diff --git a/gtk2_ardour/marker.cc b/gtk2_ardour/marker.cc
index f4848228f8..f0f8068e8b 100644
--- a/gtk2_ardour/marker.cc
+++ b/gtk2_ardour/marker.cc
@@ -255,20 +255,17 @@ Marker::Marker (PublicEditor& ed, ArdourCanvas::Group& parent, guint32 rgba, con
/* 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());
diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc
index 05a7f4628b..57faf1c3bb 100644
--- a/gtk2_ardour/mixer_strip.cc
+++ b/gtk2_ardour/mixer_strip.cc
@@ -207,6 +207,7 @@ MixerStrip::init ()
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");
@@ -1319,12 +1320,7 @@ MixerStrip::route_group_changed ()
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:
diff --git a/gtk2_ardour/nag.cc b/gtk2_ardour/nag.cc
index 7ae1b6e809..7a7a4aadbb 100644
--- a/gtk2_ardour/nag.cc
+++ b/gtk2_ardour/nag.cc
@@ -5,6 +5,8 @@
#include <fstream>
#include <gtkmm/stock.h>
+#include "pbd/openuri.h"
+
#include "ardour/ardour.h"
#include "ardour/filesystem_paths.h"
@@ -176,35 +178,16 @@ NagScreen::offer_to_donate ()
/* 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
-}
diff --git a/gtk2_ardour/nag.h b/gtk2_ardour/nag.h
index 664cff76fe..911f09d926 100644
--- a/gtk2_ardour/nag.h
+++ b/gtk2_ardour/nag.h
@@ -32,7 +32,6 @@ class NagScreen : public ArdourDialog
void mark_affirmed_subscriber ();
void offer_to_donate ();
void offer_to_subscribe ();
- bool open_uri (const char*);
static bool is_subscribed (bool& really);
};
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index 9c3c7902bb..201e89db3b 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -88,6 +88,7 @@ using namespace Gtkmm2ext;
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)
@@ -494,6 +495,7 @@ ProcessorBox::show_processor_menu (gint arg)
}
}
+ cut_action->set_sensitive (can_cut());
paste_action->set_sensitive (!_rr_selection.processors.empty());
processor_menu->popup (1, arg);
@@ -1054,6 +1056,27 @@ ProcessorBox::rename_processors ()
}
}
+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 ()
{
@@ -1333,10 +1356,10 @@ ProcessorBox::deactivate_processor (boost::shared_ptr<Processor> r)
}
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 ());
}
}
@@ -1551,9 +1574,9 @@ ProcessorBox::register_actions ()
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);
diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h
index d5e4572659..74ab5c85bb 100644
--- a/gtk2_ardour/processor_box.h
+++ b/gtk2_ardour/processor_box.h
@@ -238,8 +238,11 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
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>);
diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h
index e91f2911e3..1ddee9a585 100644
--- a/gtk2_ardour/public_editor.h
+++ b/gtk2_ardour/public_editor.h
@@ -228,6 +228,10 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible {
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.
*/
diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc
index 8e45b7ace0..85fa5b87e3 100644
--- a/gtk2_ardour/region_view.cc
+++ b/gtk2_ardour/region_view.cc
@@ -94,7 +94,6 @@ RegionView::RegionView (const RegionView& other)
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());
}
@@ -114,7 +113,6 @@ RegionView::RegionView (const RegionView& other, boost::shared_ptr<Region> other
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());
}
@@ -147,7 +145,6 @@ RegionView::init (Gdk::Color const & basic_color, bool wfd)
editor = 0;
valid = true;
in_destructor = false;
- _height = 0;
wait_for_data = wfd;
sync_mark = 0;
sync_line = 0;
diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h
index 43d8a00f17..d9bf4cd7e0 100644
--- a/gtk2_ardour/region_view.h
+++ b/gtk2_ardour/region_view.h
@@ -135,7 +135,6 @@ class RegionView : public TimeAxisViewItem
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;
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
index 62a2b2b8a0..4674bd3c19 100644
--- a/gtk2_ardour/route_time_axis.cc
+++ b/gtk2_ardour/route_time_axis.cc
@@ -1471,6 +1471,12 @@ RouteTimeAxisView::get_child_list()
}
+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)
{
@@ -1486,32 +1492,36 @@ 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());
@@ -1535,10 +1545,15 @@ RouteTimeAxisView::build_playlist_menu (Gtk::Menu * menu)
}
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) {
@@ -1549,8 +1564,8 @@ RouteTimeAxisView::use_playlist (boost::weak_ptr<Playlist> wpl)
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);
diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h
index 39d65cd499..1a9909374f 100644
--- a/gtk2_ardour/route_time_axis.h
+++ b/gtk2_ardour/route_time_axis.h
@@ -294,7 +294,7 @@ protected:
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;
diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc
index befed97743..6c96ebac48 100644
--- a/gtk2_ardour/route_ui.cc
+++ b/gtk2_ardour/route_ui.cc
@@ -262,9 +262,10 @@ RouteUI::mute_press (GdkEventButton* ev)
// 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 ());
}
@@ -357,9 +358,9 @@ RouteUI::solo_press(GdkEventButton* ev)
// 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());
}
@@ -491,10 +492,10 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
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))) {
diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc
index 65ae061e5c..381489cf88 100644
--- a/gtk2_ardour/sfdb_ui.cc
+++ b/gtk2_ardour/sfdb_ui.cc
@@ -443,6 +443,10 @@ SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::S
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);
@@ -1000,7 +1004,7 @@ SoundFileOmega::reset_options ()
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"));
}
}
diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc
index 16485f0082..04018dee7c 100644
--- a/gtk2_ardour/time_axis_view.cc
+++ b/gtk2_ardour/time_axis_view.cc
@@ -153,6 +153,7 @@ TimeAxisView::TimeAxisView (ARDOUR::Session* sess, PublicEditor& ed, TimeAxisVie
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|
@@ -1307,13 +1308,11 @@ TimeAxisView::idle_resize (uint32_t h)
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;
}
diff --git a/gtk2_ardour/time_axis_view_item.cc b/gtk2_ardour/time_axis_view_item.cc
index 3ecb152fea..f36e5f4eb5 100644
--- a/gtk2_ardour/time_axis_view_item.cc
+++ b/gtk2_ardour/time_axis_view_item.cc
@@ -78,7 +78,7 @@ double TimeAxisViewItem::NAME_HIGHLIGHT_THRESH;
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) {
@@ -558,6 +558,8 @@ TimeAxisViewItem::set_name_text(const ustring& new_name)
void
TimeAxisViewItem::set_height (double height)
{
+ _height = height;
+
if (name_highlight) {
if (height < NAME_HIGHLIGHT_THRESH) {
name_highlight->hide ();
@@ -841,9 +843,7 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
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 {
@@ -853,7 +853,7 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
}
high_enough_for_name = true;
}
-
+
if (visibility & FullWidthNameHighlight) {
name_highlight->property_x2() = pixel_width;
} else {
@@ -878,6 +878,8 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
frame_handle_end->property_x2() = pixel_width;
}
}
+
+ update_name_pixbuf_visibility ();
}
void
diff --git a/gtk2_ardour/time_axis_view_item.h b/gtk2_ardour/time_axis_view_item.h
index 5f97ddcf4f..0c4d5a3291 100644
--- a/gtk2_ardour/time_axis_view_item.h
+++ b/gtk2_ardour/time_axis_view_item.h
@@ -467,6 +467,7 @@ class TimeAxisViewItem : public Selectable, public PBD::ScopedConnectionList
ArdourCanvas::SimpleRect* frame_handle_start;
ArdourCanvas::SimpleRect* frame_handle_end;
+ double _height;
Visibility visibility;
bool _recregion;
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index 6baa724cf2..e3fcb58fa1 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -247,7 +247,6 @@ _ the regular process() call to session->process() is not made.
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;
diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h
index b6e8719ccd..5a6adda140 100644
--- a/libs/ardour/ardour/playlist.h
+++ b/libs/ardour/ardour/playlist.h
@@ -116,6 +116,7 @@ class Playlist : public SessionObject
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; }
@@ -240,6 +241,7 @@ class Playlist : public SessionObject
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;
@@ -289,6 +291,8 @@ class Playlist : public SessionObject
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 ();
diff --git a/libs/ardour/ardour/port_insert.h b/libs/ardour/ardour/port_insert.h
index 5e50b4775e..2f39d8688e 100644
--- a/libs/ardour/ardour/port_insert.h
+++ b/libs/ardour/ardour/port_insert.h
@@ -29,6 +29,7 @@
#include "ardour/types.h"
class XMLNode;
+class MTDM;
namespace ARDOUR {
@@ -64,6 +65,12 @@ class PortInsert : public IOProcessor
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&);
@@ -71,7 +78,10 @@ class PortInsert : public IOProcessor
boost::shared_ptr<Delivery> _out;
uint32_t bitslot;
-};
+ MTDM* _mtdm;
+ bool _latency_detect;
+ nframes_t _latency_flush_frames;
+ nframes_t _measured_latency;};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h
index 98f4e2d1b7..823fb4e7f2 100644
--- a/libs/ardour/ardour/rc_configuration_vars.h
+++ b/libs/ardour/ardour/rc_configuration_vars.h
@@ -136,7 +136,7 @@ CONFIG_VARIABLE (bool, periodic_safety_backups, "periodic-safety-backups", true)
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")
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index ba08e9f878..398a4936cc 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -76,7 +76,6 @@ AudioEngine::AudioEngine (string client_name)
_jack = 0;
_frame_rate = 0;
_buffer_size = 0;
- _freewheel_thread_registered = false;
_freewheeling = false;
m_meter_thread = 0;
@@ -1104,16 +1103,11 @@ AudioEngine::freewheel (bool onoff)
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;
}
}
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index 2cdb0dfbd1..3430eb5128 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -1387,14 +1387,22 @@ AudioRegion::get_transients (AnalysisFeatureList& results, bool force_new)
/* 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());
diff --git a/libs/ardour/crossfade.cc b/libs/ardour/crossfade.cc
index 4f20db5b35..276a42f77b 100644
--- a/libs/ardour/crossfade.cc
+++ b/libs/ardour/crossfade.cc
@@ -100,6 +100,7 @@ Crossfade::Crossfade (boost::shared_ptr<AudioRegion> in, boost::shared_ptr<Audio
_out = out;
_anchor_point = ap;
_fixed = true;
+ _follow_overlap = false;
initialize ();
}
diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc
index 035772305a..d6fa4e95bf 100644
--- a/libs/ardour/import.cc
+++ b/libs/ardour/import.cc
@@ -205,7 +205,7 @@ map_existing_mono_sources (const vector<string>& new_paths, Session& /*sess*/,
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)
{
@@ -229,6 +229,14 @@ create_mono_sources_for_writing (const vector<string>& new_paths, Session& sess,
}
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;
}
@@ -425,13 +433,13 @@ Session::import_audiofiles (ImportStatus& status)
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
@@ -468,7 +476,7 @@ Session::import_audiofiles (ImportStatus& status)
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 */
diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc
index 7abcca2718..efbc97bc91 100644
--- a/libs/ardour/ladspa_plugin.cc
+++ b/libs/ardour/ladspa_plugin.cc
@@ -178,8 +178,6 @@ LadspaPlugin::default_value (uint32_t port)
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);
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index 5cf0627448..5968f67f21 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -25,6 +25,8 @@
#include <string>
#include <climits>
+#include <boost/lexical_cast.hpp>
+
#include "pbd/failed_constructor.h"
#include "pbd/stateful_diff_command.h"
#include "pbd/xml++.h"
@@ -150,6 +152,7 @@ Playlist::Playlist (Session& sess, string nom, DataType type, bool hide)
init (hide);
first_set_state = false;
_name = nom;
+ _set_sort_id ();
}
@@ -164,6 +167,7 @@ Playlist::Playlist (Session& sess, const XMLNode& node, DataType type, bool hide
init (hide);
_name = "unnamed"; /* reset by set_state */
+ _set_sort_id ();
/* set state called by derived class */
}
@@ -359,6 +363,32 @@ Playlist::~Playlist ()
/* 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)
{
@@ -370,9 +400,13 @@ 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;
}
/***********************************************************************
@@ -2121,6 +2155,7 @@ Playlist::set_state (const XMLNode& node, int version)
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")) {
diff --git a/libs/ardour/port_insert.cc b/libs/ardour/port_insert.cc
index dee661db41..fb688c6f84 100644
--- a/libs/ardour/port_insert.cc
+++ b/libs/ardour/port_insert.cc
@@ -23,14 +23,15 @@
#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"
@@ -44,6 +45,11 @@ PortInsert::PortInsert (Session& s, boost::shared_ptr<MuteMaster> mm)
: 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 */
}
@@ -52,6 +58,11 @@ PortInsert::PortInsert (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLN
, _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();
}
@@ -61,6 +72,33 @@ PortInsert::PortInsert (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLN
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
@@ -70,6 +108,38 @@ PortInsert::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nf
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);
@@ -151,7 +221,11 @@ PortInsert::signal_latency() const
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
diff --git a/libs/ardour/port_set.cc b/libs/ardour/port_set.cc
index b96e45662b..7648db00cb 100644
--- a/libs/ardour/port_set.cc
+++ b/libs/ardour/port_set.cc
@@ -16,6 +16,8 @@
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"
@@ -30,7 +32,41 @@ PortSet::PortSet()
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
diff --git a/libs/gtkmm2ext/wscript b/libs/gtkmm2ext/wscript
index 1f8144294b..dec5c94c5d 100644
--- a/libs/gtkmm2ext/wscript
+++ b/libs/gtkmm2ext/wscript
@@ -32,6 +32,7 @@ gtkmm2ext_sources = [
'focus_entry.cc',
'grouped_buttons.cc',
'gtk_ui.cc',
+ 'gtkapplication.c',
'idle_adjustment.cc',
'keyboard.cc',
'motionfeedback.cc',
@@ -84,7 +85,9 @@ def build(bld):
'-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()
diff --git a/libs/pbd/openuri.cc b/libs/pbd/openuri.cc
new file mode 100644
index 0000000000..7c51dc55e9
--- /dev/null
+++ b/libs/pbd/openuri.cc
@@ -0,0 +1,28 @@
+#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
+}
diff --git a/libs/pbd/pbd/openuri.h b/libs/pbd/pbd/openuri.h
new file mode 100644
index 0000000000..34b8da4867
--- /dev/null
+++ b/libs/pbd/pbd/openuri.h
@@ -0,0 +1,8 @@
+#ifndef __libpbd_openuri_h__
+#define __libpbd_openuri_h__
+
+namespace PBD {
+ bool open_uri (const char*);
+}
+
+#endif
diff --git a/libs/pbd/wscript b/libs/pbd/wscript
index 6e10fe9fba..69839b907b 100644
--- a/libs/pbd/wscript
+++ b/libs/pbd/wscript
@@ -73,6 +73,7 @@ def build(bld):
locale_guard.cc
malign.cc
mountpoint.cc
+ openuri.cc
pathscanner.cc
pool.cc
property_list.cc
diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc
index b7886f7513..2c16e70f51 100644
--- a/libs/surfaces/osc/osc.cc
+++ b/libs/surfaces/osc/osc.cc
@@ -321,6 +321,7 @@ OSC::register_callbacks()
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);
diff --git a/libs/surfaces/osc/osc.h b/libs/surfaces/osc/osc.h
index 0c72671ae9..4c2fce44b0 100644
--- a/libs/surfaces/osc/osc.h
+++ b/libs/surfaces/osc/osc.h
@@ -167,6 +167,7 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI<OSCUIRequest>
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);
diff --git a/tools/synthesize_sources.pl b/tools/synthesize_sources.pl
index 54fb8eb60d..0785f09e40 100755
--- a/tools/synthesize_sources.pl
+++ b/tools/synthesize_sources.pl
@@ -78,11 +78,11 @@ foreach my $tmp (keys %sources) {
"-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