From 6ef5d85ae1f2c500c4163cd1df580b3f26991c1e Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 16 Mar 2010 15:33:04 +0000 Subject: changes from 2.X starting in march 2009 through oct 20 2009 (5826 inclusive) git-svn-id: svn://localhost/ardour2/branches/3.0@6761 d708f5d6-7413-0410-9779-e7cbd77b26cf --- PACKAGER_README | 15 ++-- README | 2 +- gtk2_ardour/about.cc | 7 +- gtk2_ardour/ardour.menus.in | 4 ++ gtk2_ardour/ardour_ui.cc | 66 +++++++++++++++--- gtk2_ardour/ardour_ui.h | 1 + gtk2_ardour/ardour_ui_ed.cc | 1 + gtk2_ardour/audio_region_view.cc | 7 -- gtk2_ardour/crossfade_edit.cc | 12 ++++ gtk2_ardour/editor.cc | 107 +++++++++++++++++++++-------- gtk2_ardour/editor.h | 10 +++ gtk2_ardour/editor_actions.cc | 10 +++ gtk2_ardour/editor_canvas.cc | 2 +- gtk2_ardour/editor_ops.cc | 4 +- gtk2_ardour/engine_dialog.cc | 46 ++++++++----- gtk2_ardour/generic_pluginui.cc | 2 +- gtk2_ardour/io_selector.cc | 79 ++++++++++++++++++++- gtk2_ardour/io_selector.h | 10 +++ gtk2_ardour/main.cc | 46 ++++++++++++- gtk2_ardour/marker.cc | 7 +- gtk2_ardour/mixer_strip.cc | 8 +-- gtk2_ardour/nag.cc | 27 ++------ gtk2_ardour/nag.h | 1 - gtk2_ardour/processor_box.cc | 35 ++++++++-- gtk2_ardour/processor_box.h | 5 +- gtk2_ardour/public_editor.h | 4 ++ gtk2_ardour/region_view.cc | 3 - gtk2_ardour/region_view.h | 1 - gtk2_ardour/route_time_axis.cc | 57 +++++++++------ gtk2_ardour/route_time_axis.h | 2 +- gtk2_ardour/route_ui.cc | 17 ++--- gtk2_ardour/sfdb_ui.cc | 6 +- gtk2_ardour/time_axis_view.cc | 13 ++-- gtk2_ardour/time_axis_view_item.cc | 12 ++-- gtk2_ardour/time_axis_view_item.h | 1 + libs/ardour/ardour/audioengine.h | 1 - libs/ardour/ardour/playlist.h | 4 ++ libs/ardour/ardour/port_insert.h | 12 +++- libs/ardour/ardour/rc_configuration_vars.h | 2 +- libs/ardour/audioengine.cc | 14 ++-- libs/ardour/audioregion.cc | 14 +++- libs/ardour/crossfade.cc | 1 + libs/ardour/import.cc | 16 +++-- libs/ardour/ladspa_plugin.cc | 2 - libs/ardour/playlist.cc | 41 ++++++++++- libs/ardour/port_insert.cc | 84 ++++++++++++++++++++-- libs/ardour/port_set.cc | 38 +++++++++- libs/gtkmm2ext/wscript | 5 +- libs/pbd/openuri.cc | 28 ++++++++ libs/pbd/pbd/openuri.h | 8 +++ libs/pbd/wscript | 1 + libs/surfaces/osc/osc.cc | 1 + libs/surfaces/osc/osc.h | 1 + tools/synthesize_sources.pl | 4 +- 54 files changed, 703 insertions(+), 204 deletions(-) create mode 100644 libs/pbd/openuri.cc create mode 100644 libs/pbd/pbd/openuri.h 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 \n\tChristophe Combelles \n"), + N_("French:\n\tAlain Fréhel \n\tChristophe Combelles \n\tMartin Blanchard\n"), N_("German:\n\tKarsten Petersen \ \n\tSebastian Arnold \ \n\tRobert Schwede\n"), @@ -181,6 +182,8 @@ static const char* translators[] = { N_("Greek:\n\t Klearchos Gourgourinis \n"), N_("Swedish:\n\t Petter Sundlöf \n"), N_("Polish:\n\t Piotr Zaryk \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 @@ + @@ -433,7 +434,10 @@ +#ifndef GTKOSX +#endif + 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 p; get_state_files_in_directory (_session->session_directory().root_path(), p); vector 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); @@ -2726,6 +2765,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 () { @@ -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 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 act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead")); + if (act) { + RefPtr tact = RefPtr::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)); @@ -3697,6 +3714,29 @@ Editor::set_follow_playhead (bool yn) } } +void +Editor::toggle_stationary_playhead () +{ + RefPtr act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead")); + if (act) { + RefPtr tact = RefPtr::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 wxfade) { @@ -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 (_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::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::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 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 _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 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 #include +#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 ProcessorBox::paste_action; +RefPtr ProcessorBox::cut_action; Glib::RefPtr SendProcessorEntry::_slider; ProcessorEntry::ProcessorEntry (boost::shared_ptr 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 > sel; + + get_selected_processors (sel); + + /* cut_processors () does not cut inserts */ + + for (vector >::const_iterator i = sel.begin (); i != sel.end (); ++i) { + + if (boost::dynamic_pointer_cast((*i)) != 0 || + (boost::dynamic_pointer_cast((*i)) != 0) || + (boost::dynamic_pointer_cast((*i)) != 0)) { + return true; + } + } + + return false; +} + void ProcessorBox::cut_processors () { @@ -1333,10 +1356,10 @@ ProcessorBox::deactivate_processor (boost::shared_ptr r) } void -ProcessorBox::get_selected_processors (ProcSelection& processors) +ProcessorBox::get_selected_processors (ProcSelection& processors) const { - list selection = processor_display.selection (); - for (list::iterator i = selection.begin(); i != selection.end(); ++i) { + const list selection = processor_display.selection (); + for (list::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)); - void get_selected_processors (ProcSelection&); + void get_selected_processors (ProcSelection&) const; + bool can_cut() const; + + static Glib::RefPtr cut_action; static Glib::RefPtr paste_action; void paste_processor_state (const XMLNodeList&, boost::shared_ptr); 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 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 a, boost::shared_ptr 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 > playlists; + vector > playlists, playlists_ds; boost::shared_ptr ds = get_diskstream(); RadioMenuItem::Group playlist_group; _session->playlists->get (playlists); - for (vector >::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 (*i)))); - - if (ds->playlist()->id() == (*i)->id()) { - static_cast(&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(*i)))); - static_cast(&playlist_items.back())->set_active(); - + /* find the playlists for this diskstream */ + for (vector >::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 >::iterator i = playlists_ds.begin(); i != playlists_ds.end(); ++i) { + playlist_items.push_back (RadioMenuElem (playlist_group, (*i)->name())); + RadioMenuItem *item = static_cast(&playlist_items.back()); + item->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::use_playlist), item, boost::weak_ptr (*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 wpl) +RouteTimeAxisView::use_playlist (RadioMenuItem *item, boost::weak_ptr wpl) { assert (is_track()); + // exit if we were triggered by deactivating the old playlist + if (!item->get_active()) { + return; + } + boost::shared_ptr pl (wpl.lock()); if (!pl) { @@ -1549,8 +1564,8 @@ RouteTimeAxisView::use_playlist (boost::weak_ptr 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); + void use_playlist (Gtk::RadioMenuItem *item, boost::weak_ptr 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 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 > 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); void notify_region_added (boost::shared_ptr); 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 _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 in, boost::shared_ptr