changes from 2.X starting in march 2009 through oct 20 2009 (5826 inclusive)
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 16 Mar 2010 15:33:04 +0000 (15:33 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 16 Mar 2010 15:33:04 +0000 (15:33 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@6761 d708f5d6-7413-0410-9779-e7cbd77b26cf

54 files changed:
PACKAGER_README
README
gtk2_ardour/about.cc
gtk2_ardour/ardour.menus.in
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/audio_region_view.cc
gtk2_ardour/crossfade_edit.cc
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_actions.cc
gtk2_ardour/editor_canvas.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/engine_dialog.cc
gtk2_ardour/generic_pluginui.cc
gtk2_ardour/io_selector.cc
gtk2_ardour/io_selector.h
gtk2_ardour/main.cc
gtk2_ardour/marker.cc
gtk2_ardour/mixer_strip.cc
gtk2_ardour/nag.cc
gtk2_ardour/nag.h
gtk2_ardour/processor_box.cc
gtk2_ardour/processor_box.h
gtk2_ardour/public_editor.h
gtk2_ardour/region_view.cc
gtk2_ardour/region_view.h
gtk2_ardour/route_time_axis.cc
gtk2_ardour/route_time_axis.h
gtk2_ardour/route_ui.cc
gtk2_ardour/sfdb_ui.cc
gtk2_ardour/time_axis_view.cc
gtk2_ardour/time_axis_view_item.cc
gtk2_ardour/time_axis_view_item.h
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/playlist.h
libs/ardour/ardour/port_insert.h
libs/ardour/ardour/rc_configuration_vars.h
libs/ardour/audioengine.cc
libs/ardour/audioregion.cc
libs/ardour/crossfade.cc
libs/ardour/import.cc
libs/ardour/ladspa_plugin.cc
libs/ardour/playlist.cc
libs/ardour/port_insert.cc
libs/ardour/port_set.cc
libs/gtkmm2ext/wscript
libs/pbd/openuri.cc [new file with mode: 0644]
libs/pbd/pbd/openuri.h [new file with mode: 0644]
libs/pbd/wscript
libs/surfaces/osc/osc.cc
libs/surfaces/osc/osc.h
tools/synthesize_sources.pl

index dd5be31c6df9b667ac3d51abca1fddc8a4e8fe30..3b797d3c58f312dd9f123c1b95f67e153481f95c 100644 (file)
@@ -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 ababed7471c38628f8f741730ee356b7807721ff..9f70698de99b173016f6a3218c36963e1746cb71 100644 (file)
--- 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.
index e3734ec6ce50dde6eaa52946c2cb497cd8be01ff..317be6f4030376f8801f122bbc7c1a44ca79ad3c 100644 (file)
@@ -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/"));
index d5bb7b797cf4b7a59d1ab59eb2f7dd845b5aa908..26ce7c53238272393cb0a791d2e058c229c87974 100644 (file)
                     <menuitem action='track-height-smaller'/>
                     <menuitem action='track-height-small'/>
                </menu>
+                <menuitem action='track-record-enable-toggle'/>
                <menuitem action='toggle-track-active'/>        
                <menuitem action='remove-track'/>       
        </menu>
               <separator/>
         </menu>
         <menu name='Help' action='Help'>
+#ifndef GTKOSX
             <menuitem action='About'/>
+#endif
+             <menuitem action='Chat'/>
        </menu>
      </menubar>
 
index 73b4e060fb69890d7960dc3f5cf0a21e51ae6a3d..786e14aa693754853f6ea9297e3c9d0bb47b38aa 100644 (file)
@@ -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);
@@ -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);
index 25bd74b55cf724225aaa50646704bcdb359099ff..e131cf5431eed14da21008c54eb48eace42880bb 100644 (file)
@@ -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 ();
 
index 532902a3d22213f072937e9278ca2c76ff8df83d..9630c37fae6338c32e14c80a8746c0b16d360244 100644 (file)
@@ -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));
index 7a0e76606ef9d14a3cfa8fb4014112adaac78091..7b97d2f882c4df5dfb096894c294853fc7b29b5e 100644 (file)
@@ -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
index c1201f2f9a91fca313de9dce9105df30006aca15..726194c41b989431339fc0f4f3fe6f5a0a8a6426 100644 (file)
@@ -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;
index f7b68fcbf105518298546d6e94f9b55aa0b0cf17..572e1923573a13654d4c21ebaf31c282ecbe93ae 100644 (file)
@@ -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));
@@ -3697,6 +3714,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)
 {
@@ -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
+                }
                
        }
 }
index 20e7567f367fbe7c359305361cbf38f1834b9ec8..0fc433d2fb45faa8f3cd355295f1b42d20d28c75 100644 (file)
@@ -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;
 
index d137ed6351ccf92b5532e608a27b04c0fe26cc7f..ec7472df9196a25552db597a41d5862ecc404a01 100644 (file)
@@ -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);
index 510b7e019f5a59c77f35dbb1cdeb6025c73ceb11..4ea6d27ea26977b9cb33c64b381f91048ba66edb 100644 (file)
@@ -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 ();
index d4e8f4b54f622d53612588bbb985c15c1d668499..f7fe6e7b4ad74bf95e310eafc66c575817731882 100644 (file)
@@ -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);
index 3213761c781c48992547b1d7264340df613d1a8e..3717feb038b5e994492036e1ac14533eb40ef6c6 100644 (file)
@@ -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") {
index 636cdbc894f2e19e79fa75b277d867232f1c3c1b..c8aa1f737d8d181b7a7850a54eeed0a58901b51b 100644 (file)
@@ -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;
index 615ce9d69fae61c2988f027fe31fd0034916aa22..fd9ff2458d93fe5fea581b4c301b1a3659aa0512 100644 (file)
@@ -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 ()
 {
index a4545dbfc43c34133ce4757d8bdab5c277539a4f..11454f8531e0228ae208cfc9ab00a0e4a4d4d14d 100644 (file)
@@ -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
index 2b16de3d70be41e7c1206525bd85071b32f008e5..daa2491f0fc8d4462b9ca7a9a2ecbb2caeee5dde 100644 (file)
@@ -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
index f4848228f8286ac13e89263ffea60d2e92069fbd..f0f8068e8b86f19df4fb84882c3cf877f8cadebb 100644 (file)
@@ -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());
 
index 05a7f4628b593c38dd744a3abc775ce2217b76df..57faf1c3bb1946ceabbdf84c93c9320fb4969cbb 100644 (file)
@@ -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:
index 7ae1b6e809ec10b350abca1c844f6aafc58abab0..7a7a4aadbb8cc92106d735adc4d77164db5f74f6 100644 (file)
@@ -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
-}
index 664cff76fe1ecbb89f326d99de19abd7970bb3eb..911f09d926502c2f3a6c59a2cfb5e5b4fa4809c2 100644 (file)
@@ -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);
 };
 
index 9c3c7902bb5a4153c5746801a33b9410ba826acc..201e89db3b2a4b848972e2c57dd7d5a0c1cb5baf 100644 (file)
@@ -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);
index d5e4572659f6112e2612a3f464003a7e0bfdb20b..74ab5c85bb7753a9c6ccbea0bebbfa0e4a836feb 100644 (file)
@@ -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>);
 
index e91f2911e311edb76ff18a6453b52c4d968c1967..1ddee9a585ac8e4201034f0d31dcb8d7aba3f0cd 100644 (file)
@@ -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.
         */
index 8e45b7ace05ca4d5d61a8b959dc1fea665b72526..85fa5b87e3b0a3ec9726dc3884a9f4f2a76bbc1d 100644 (file)
@@ -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;
index 43d8a00f171e199da21bc65c869ad89badfc34d5..d9bf4cd7e0460f04b138da1ce511384b2023fd92 100644 (file)
@@ -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;
index 62a2b2b8a076795e995ba10c276050cdbfe607db..4674bd3c193db526bf36bad2fb3286247003dba1 100644 (file)
@@ -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);
index 39d65cd499b4254f7dc40cb735209624a1a654e0..1a9909374f08acfa3653574359b6fa82c20274bc 100644 (file)
@@ -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;
 
index befed977436c402e53f2ed9c0b0e1016cc3d7643..6c96ebac4881172105cf608244e479ee18912158 100644 (file)
@@ -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))) {
 
index 65ae061e5c3da5b564376647be94212da200e49d..381489cf88ce856e19b25ca6cfb94f7866a4a6ae 100644 (file)
@@ -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"));
                        }
 
                }
index 16485f0082c906f6c3c76dab85f526600b877669..04018dee7c5f936f7bcbf29ff07df7913912d00c 100644 (file)
@@ -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;
 }
index 3ecb152fea47604bb7e8a946bdab456ba67805e0..f36e5f4eb525b98cb692a8b8e40801a072701cc7 100644 (file)
@@ -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
index 5f97ddcf4f2e55883e91ef37f6e17502a52e1179..0c4d5a329169a6031e7bbfeef91539cdab55483a 100644 (file)
@@ -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;
 
index 6baa724cf2599ccd913098d3d2351bfaf98d3d1e..e3fcb58fa1f9fefba6e688b9d1dadd8ecbfb57f5 100644 (file)
@@ -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;
index b6e8719ccd8a2a6906d90c308c09f8c8b5f985e1..5a6adda140f04a2dac1827aea331f422454bef6f 100644 (file)
@@ -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 ();
index 5e50b4775e70fd30ad4d3e4d560b2b89d6647ff1..2f39d8688ecb26dfe3549c87c84fbffa8a715a67 100644 (file)
@@ -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
 
index 98f4e2d1b75b6536c37ee96d42c2a71420920acb..823fb4e7f269d7648fdb49882e13e8dc7195f5bf 100644 (file)
@@ -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")
index ba08e9f878cf5d57da56b2f137d2ac731ee8a338..398a4936cc283481fe4e8dea0f41fe3d5865f428 100644 (file)
@@ -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;
        }
 }
 
index 2cdb0dfbd12095e5745ed033446086b4f2ecdb5c..3430eb5128a7761ef315da1e485b4ed1cff9d478 100644 (file)
@@ -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());
index 4f20db5b35dd35584074736412342b8fdb9b63f6..276a42f77ba4b4cf16415060578f21b9c2f71f76 100644 (file)
@@ -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 ();
 }
index 035772305a1b014d6fb34e59dedcdb93777abbe5..d6fa4e95bf3c471897e87e319051e068a7b2c5da 100644 (file)
@@ -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 */
index 7abcca27189e8aa7214eee657bf115e07880fe24..efbc97bc9165edea157b398e1976e156280a6d3a 100644 (file)
@@ -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);
index 5cf062744805add24434e98ea1421ec7f7acc223..5968f67f215353de7e719e58825dad61cd5f998c 100644 (file)
@@ -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")) {
index dee661db4157c5e05e7bd781aca1b16066b2a41b..fb688c6f84f72c13cda8f79e49caf61921de008b 100644 (file)
 #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
index b96e45662b945da03a9e513ddb6a4e3e6c02ca81..7648db00cb413dff0d94f5f26695cf65b58480fd 100644 (file)
@@ -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
index 1f8144294be0f057f1293d6d318d4184668c3017..dec5c94c5db45622d091eabce8de3451c738ec02 100644 (file)
@@ -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 (file)
index 0000000..7c51dc5
--- /dev/null
@@ -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 (file)
index 0000000..34b8da4
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __libpbd_openuri_h__
+#define __libpbd_openuri_h__
+
+namespace PBD {
+        bool open_uri (const char*);
+}
+
+#endif
index 6e10fe9fba33cddfb13c3618c01ddc37192e4ea4..69839b907b24ba3dc65d24d609f40fd8defef67b 100644 (file)
@@ -73,6 +73,7 @@ def build(bld):
                 locale_guard.cc
                 malign.cc
                mountpoint.cc
+                openuri.cc
                pathscanner.cc
                pool.cc
                 property_list.cc
index b7886f75130b2a39a83d445ea33e7d43accf345f..2c16e70f5119337093184f50e8088634cb11a7b4 100644 (file)
@@ -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);
index 0c72671ae90fbdc934aa0ed3955d1d697cac65ff..4c2fce44b01c09c77882b5f4e78dd1169ac26c19 100644 (file)
@@ -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);
index 54fb8eb60d3902b39d4dc31247e16250cfcc41ce..0785f09e40745d578a8fd9ac32608c9c14f69910 100755 (executable)
@@ -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