use filechooser widget in export dialog, selected files set format combos, hide progr...
authorNick Mainsbridge <beatroute@iprimus.com.au>
Fri, 26 Oct 2007 13:32:24 +0000 (13:32 +0000)
committerNick Mainsbridge <beatroute@iprimus.com.au>
Fri, 26 Oct 2007 13:32:24 +0000 (13:32 +0000)
git-svn-id: svn://localhost/ardour2/trunk@2576 d708f5d6-7413-0410-9779-e7cbd77b26cf

22 files changed:
gtk2_ardour/audio_region_view.cc
gtk2_ardour/audio_streamview.cc
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_canvas.cc
gtk2_ardour/editor_export_audio.cc
gtk2_ardour/editor_mouse.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_rulers.cc
gtk2_ardour/editor_tempodisplay.cc
gtk2_ardour/export_dialog.cc
gtk2_ardour/export_dialog.h
gtk2_ardour/region_view.cc
gtk2_ardour/streamview.cc
libs/ardour/SConscript
libs/ardour/ardour/audiosource.h
libs/ardour/ardour/jack_port.h
libs/ardour/ardour/types.h
libs/ardour/audio_playlist.cc
libs/ardour/globals.cc
libs/ardour/playlist.cc
libs/ardour/sndfile_helpers.cc

index 4bc10e93ec6e1995e8dfd87eb6cb00ea94da3c91..0ad6b8af5b7fcc972b20c3a05fa34abcb0bc32c9 100644 (file)
@@ -202,6 +202,8 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfd)
        fade_in_active_changed ();
        fade_out_active_changed ();
 
+       reset_width_dependent_items (_pixel_width);
+
        fade_in_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_event), fade_in_shape, this));
        fade_in_handle->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_handle_event), fade_in_handle, this));
        fade_out_shape->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_event), fade_out_shape, this));
index 22f8fa623972a3ef5298f92ea615eb9e8c652d31..c571cb1a7cc2a13bc909c75f5035fd9339658b34 100644 (file)
@@ -311,6 +311,7 @@ AudioStreamView::add_crossfade (boost::shared_ptr<Crossfade> crossfade)
 
        for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
                if ((*i)->crossfade == crossfade) {
+
                        if (!crossfades_visible || layer_display == Stacked) {
                                (*i)->hide();
                        } else {
@@ -340,10 +341,9 @@ AudioStreamView::add_crossfade (boost::shared_ptr<Crossfade> crossfade)
                                               _samples_per_unit,
                                               region_color,
                                               *lview, *rview);
-
+       cv->set_valid (true);
        crossfade->Invalidated.connect (mem_fun (*this, &AudioStreamView::remove_crossfade));
        crossfade_views.push_back (cv);
-
        if (!Config->get_xfades_visible() || !crossfades_visible || layer_display == Stacked) {
                cv->hide ();
        }
@@ -390,6 +390,8 @@ AudioStreamView::redisplay_diskstream ()
                        apl->foreach_crossfade (this, &AudioStreamView::add_crossfade);
        }
 
+       RegionViewList  copy;
+
        for (i = region_views.begin(); i != region_views.end(); ) {
                tmp = i;
                tmp++;
@@ -397,11 +399,47 @@ AudioStreamView::redisplay_diskstream ()
                if (!(*i)->is_valid()) {
                        delete *i;
                        region_views.erase (i);
+                       i = tmp;
+                       continue;
                } else {
                        (*i)->enable_display(true);
                }
 
+               /* 
+                  sort regionviews by layer so that when we call region_layered ()
+                  the canvas layering works out (in non-stacked mode).
+               */
+
+               if (copy.size() == 0) {
+                       copy.push_front((*i));
+                       i = tmp;
+                       continue;
+               }
+
+               RegionViewList::iterator k = copy.begin();
+               RegionViewList::iterator l = copy.end();
+               l--;
+
+               if ((*i)->region()->layer() <= (*k)->region()->layer()) {
+                       copy.push_front((*i));
+                       i = tmp;
+                       continue;
+               } else if ((*i)->region()->layer() >= (*l)->region()->layer()) {
+                       copy.push_back((*i));
+                       i = tmp;
+                       continue;
+               }
+
+               for (RegionViewList::iterator j = copy.begin(); j != copy.end(); ++j) {
+                 
+                       if ((*j)->region()->layer() >= (*i)->region()->layer()) {
+                               copy.insert(j, (*i));
+                               break;
+                       }
+               }
+
                i = tmp;
+
        }
 
        for (xi = crossfade_views.begin(); xi != crossfade_views.end();) {
@@ -416,10 +454,12 @@ AudioStreamView::redisplay_diskstream ()
                xi = tmpx;
        }
 
-       /* now fix layering */
-
-       for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
-               region_layered (*i);
+       /* now fix canvas layering */
+       
+       for (RegionViewList::iterator j = copy.begin(); j != copy.end(); ++j) {
+                       (*j)->enable_display(true);
+                       (*j)->set_y_position_and_height(0, height);
+                       region_layered (*j);
        }
 }
 
index da74ea96cc0eba2359aeaa16d029803e8b745aed..1e726277d25481cb2042e69aeb0d5b594bf54c12 100644 (file)
@@ -348,7 +348,8 @@ Editor::Editor ()
 
        range_marker_drag_rect = 0;
        marker_drag_line = 0;
-       
+       tempo_map_change_idle_handler_id = -1;
+       canvas_hroizontally_scrolled_handler_id = -1;
        set_midi_edit_mode (MidiEditPencil, true);
        set_mouse_mode (MouseObject, true);
 
@@ -1983,7 +1984,9 @@ Editor::set_snap_to (SnapType st)
        case SnapToAEighthBeat:
        case SnapToAQuarterBeat:
        case SnapToAThirdBeat:
+                compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + (nframes_t)(canvas_width * frames_per_unit));
                 update_tempo_based_rulers ();
+               break;
        default:
                /* relax */
                break;
@@ -2638,7 +2641,7 @@ Editor::setup_toolbar ()
        /* Zoom */
        
        zoom_box.set_spacing (1);
-       zoom_box.set_border_width (2);
+       zoom_box.set_border_width (0);
 
        zoom_in_button.set_name ("EditorTimeButton");
        zoom_in_button.set_size_request(-1,16);
@@ -3918,10 +3921,6 @@ Editor::set_frames_per_unit (double fpu)
 
        frames_per_unit = fpu;
 
-       if (frames != zoom_range_clock.current_duration()) {
-               zoom_range_clock.set (frames);
-       }
-
        if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
                if (!selection->tracks.empty()) {
                        for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
@@ -3963,8 +3962,9 @@ Editor::queue_visual_change (double fpu)
        pending_visual_change.frames_per_unit = fpu;
 
        if (pending_visual_change.idle_handler_id < 0) {
-               pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE, _idle_visual_changer, this, 0);
+               pending_visual_change.idle_handler_id = g_idle_add ( _idle_visual_changer, this);
        }
+       
 }
 
 int
@@ -3979,12 +3979,15 @@ Editor::idle_visual_changer ()
        VisualChange::Type p = pending_visual_change.pending;
 
        pending_visual_change.pending = (VisualChange::Type) 0;
-       pending_visual_change.idle_handler_id = -1;
        
        if (p & VisualChange::ZoomLevel) {
                set_frames_per_unit (pending_visual_change.frames_per_unit);
-       }
 
+               compute_fixed_ruler_scale ();
+               compute_current_bbt_points(pending_visual_change.time_origin, pending_visual_change.time_origin + (nframes_t)(canvas_width * pending_visual_change.frames_per_unit));
+               compute_bbt_ruler_scale (pending_visual_change.time_origin, pending_visual_change.time_origin + (nframes_t)(canvas_width * pending_visual_change.frames_per_unit));
+               update_tempo_based_rulers ();
+       }
        if (p & VisualChange::TimeOrigin) {
                if (pending_visual_change.time_origin != leftmost_frame) {
                        horizontal_adjustment.set_value (pending_visual_change.time_origin/frames_per_unit);
@@ -3994,6 +3997,7 @@ Editor::idle_visual_changer ()
                        redisplay_tempo (true);
                }
        }
+       pending_visual_change.idle_handler_id = -1;
 
        return 0; /* this is always a one-shot call */
 }
index 7e96f9c9c551823545750994e93b30451fdce588..4fc2bd0d1852b4b574562eba1548c0f65c2b7722 100644 (file)
@@ -476,6 +476,7 @@ class Editor : public PublicEditor
 
        void set_selected_regionview_from_region_list (boost::shared_ptr<ARDOUR::Region> region, Selection::Operation op = Selection::Set);
        void collect_new_region_view (RegionView *);
+       void collect_and_select_new_region_view (RegionView *);
 
        Gtk::MenuItem* region_edit_menu_split_item;
        Gtk::MenuItem* region_edit_menu_split_multichannel_item;
@@ -559,6 +560,7 @@ class Editor : public PublicEditor
        
        void initialize_rulers ();
        void update_just_smpte ();
+       void compute_fixed_ruler_scale (); //calculates the RulerScale of the fixed rulers
        void update_fixed_rulers ();
        void update_tempo_based_rulers (); 
        void popup_ruler_menu (nframes_t where = 0, ItemType type = RegionItem);
@@ -573,6 +575,55 @@ class Editor : public PublicEditor
        static gint _metric_get_frames (GtkCustomRulerMark **, gdouble, gdouble, gint);
        static gint _metric_get_minsec (GtkCustomRulerMark **, gdouble, gdouble, gint);
        
+       enum MinsecRulerScale {
+               minsec_show_seconds,
+               minsec_show_minutes,
+               minsec_show_hours,
+               minsec_show_frames
+       };
+
+       MinsecRulerScale minsec_ruler_scale;
+
+       nframes_t minsec_mark_interval;
+       gint minsec_mark_modulo;
+       gint minsec_nmarks;
+       void set_minsec_ruler_scale (gdouble lower, gdouble upper);
+
+       enum SMPTERulerScale {
+               smpte_show_bits,
+               smpte_show_frames,
+               smpte_show_seconds,
+               smpte_show_minutes,
+               smpte_show_hours
+       };
+
+       SMPTERulerScale smpte_ruler_scale;
+
+       nframes_t smpte_mark_interval;
+       gint smpte_mark_modulo;
+       gint smpte_nmarks;
+       void set_smpte_ruler_scale (gdouble lower, gdouble upper);
+
+       enum BBTRulerScale {
+               bbt_over,
+               bbt_show_64,
+               bbt_show_16,
+               bbt_show_4,
+               bbt_show_1,
+               bbt_show_beats,
+               bbt_show_ticks,
+               bbt_show_ticks_detail,
+               bbt_show_ticks_super_detail
+       };
+
+       BBTRulerScale bbt_ruler_scale;
+
+        uint32_t bbt_bars;
+       gint bbt_nmarks;
+       uint32_t bbt_bar_helper_on;
+       uint32_t bbt_accent_modulo;
+       void compute_bbt_ruler_scale (nframes_t lower, nframes_t upper);
+
        gint metric_get_smpte (GtkCustomRulerMark **, gdouble, gdouble, gint);
        gint metric_get_bbt (GtkCustomRulerMark **, gdouble, gdouble, gint);
        gint metric_get_frames (GtkCustomRulerMark **, gdouble, gdouble, gint);
@@ -696,6 +747,8 @@ class Editor : public PublicEditor
 
        void tie_vertical_scrolling ();
        void canvas_horizontally_scrolled ();
+       static int _idle_canvas_horizontally_scrolled (void *arg);
+       bool idle_canvas_horizontally_scrolled ();
 
        struct VisualChange {
            enum Type { 
@@ -1261,6 +1314,8 @@ class Editor : public PublicEditor
 
        void handle_new_duration ();
        void initialize_canvas ();
+       int canvas_hroizontally_scrolled_handler_id;
+       void reset_horizontally_scrolling_region (Gtk::Allocation* alloc = 0);
        void reset_scrolling_region (Gtk::Allocation* alloc = 0);
 
        /* display control */
@@ -1341,6 +1396,8 @@ class Editor : public PublicEditor
        void remove_metric_marks ();
        void draw_metric_marks (const ARDOUR::Metrics& metrics);
 
+       void compute_current_bbt_points (nframes_t left, nframes_t right);
+       int tempo_map_change_idle_handler_id;
        void tempo_map_changed (ARDOUR::Change);
        void redisplay_tempo (bool immediate_redraw);
        
index 86beec387e84876139f6b284cb8bb396a1300ac7..fbd4f13f02ad5476a7395e1724a7121a2c9782d2 100644 (file)
@@ -360,7 +360,7 @@ Editor::track_canvas_size_allocated ()
                transport_punchout_line->property_y1() = 0.0;
                transport_punchout_line->property_y2() = canvas_height;
        }
-               
+       compute_fixed_ruler_scale ();
        update_fixed_rulers();
        redisplay_tempo (true);
 
index 9b0a7c7cb590f2ff412f49a284fa304189b39b0b..3ab2012588bda379404397049ef450319e14c787 100644 (file)
@@ -82,9 +82,9 @@ Editor::export_range (nframes_t start, nframes_t end)
        if (session) {
                if (export_dialog == 0) {
                        export_dialog = new ExportSessionDialog (*this);
+                       export_dialog->connect_to_session (session);
                }
                
-               export_dialog->connect_to_session (session);
                export_dialog->set_range (start, end);
                export_dialog->start_export();
        }
@@ -121,9 +121,9 @@ Editor::export_range_markers ()
 
                if (export_range_markers_dialog == 0) {
                        export_range_markers_dialog = new ExportRangeMarkersDialog(*this);
+                       export_range_markers_dialog->connect_to_session (session);
                }
-               
-               export_range_markers_dialog->connect_to_session (session);
+
                export_range_markers_dialog->start_export();
        }
 }      
index c6bbf5ca5fe1eee741d2c9f897acf0edfad275c7..0827fc5321f8bd6b8aa5900c3e388874fd5cec42 100644 (file)
@@ -2898,6 +2898,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                vector<RegionView*> new_regionviews;
                
                for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
+
                        RegionView* rv;
                        RegionView* nrv;
 
@@ -2924,7 +2925,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                }
 
                /* reset selection to new regionviews */
-               
+
                selection->set (new_regionviews);
                
                /* reset drag_info data to reflect the fact that we are dragging the copies */
@@ -3288,7 +3289,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                                                tvp2 = trackview_by_y_position (iy1 + y_delta);
                                                temp_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
                                                rv->set_y_position_and_height (0, temp_rtv->height);
-       
+
                                                /*   if you un-comment the following, the region colours will follow the track colours whilst dragging,
                                                     personally, i think this can confuse things, but never mind.
                                                */
@@ -3358,7 +3359,7 @@ void
 Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
 {
        nframes_t where;
-       RegionView* rv = reinterpret_cast<RegionView *> (drag_info.data);
+       RegionView* rvdi = reinterpret_cast<RegionView *> (drag_info.data);
        pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
        bool nocommit = true;
        double speed;
@@ -3366,6 +3367,9 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
        bool regionview_y_movement;
        bool regionview_x_movement;
        vector<RegionView*> copies;
+       list <boost::shared_ptr<Playlist > > used_playlists;
+       list <sigc::connection > used_connections;
+       bool preserve_selection = false;
 
        /* first_move is set to false if the regionview has been moved in the 
           motion handler. 
@@ -3404,8 +3408,8 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                speed = rtv->get_diskstream()->speed();
        }
        
-       regionview_x_movement = (drag_info.last_frame_position != (nframes_t) (rv->region()->position()/speed));
-       regionview_y_movement = (drag_info.last_trackview != &rv->get_time_axis_view());
+       regionview_x_movement = (drag_info.last_frame_position != (nframes_t) (rvdi->region()->position()/speed));
+       regionview_y_movement = (drag_info.last_trackview != &rvdi->get_time_axis_view());
 
        //printf ("last_frame: %s position is %lu  %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed); 
        //printf ("last_rackview: %s \n", drag_info.last_trackview->name().c_str()); 
@@ -3432,64 +3436,82 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
                /* moved to a different audio track. */
                
-               vector<RegionView*> new_selection;
-
                for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) {
                        
-                       RegionView* rv = (*i);              
+                       RegionView* rv = (*i);      
 
                        double ix1, ix2, iy1, iy2;
                        
                        rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
                        rv->get_canvas_group()->i2w (ix1, iy1);
-                       TimeAxisView* tvp2 = trackview_by_y_position (iy1);
-                       RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(tvp2);
 
-                       boost::shared_ptr<Playlist> from_playlist = rv->region()->playlist();
+                       RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(trackview_by_y_position (iy1));
+
                        boost::shared_ptr<Playlist> to_playlist = rtv2->playlist();
 
+                       if (! to_playlist->frozen()) {
+                               /* 
+                                  we haven't seen this playlist before. 
+                                  we want to freeze it because we don't want to relayer per-region. 
+                                  its much better to do that just once if the playlist is large. 
+                               */
+
+                               /*
+                                  connect so the selection is changed when the new regionview finally appears (after thaw). 
+                                  keep track of it so we can disconnect later. 
+                               */
+
+                               sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view));
+                               used_connections.push_back (c);
+
+                               /* undo */
+                               session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
+
+                               /* remember used playlists so we can thaw them later */ 
+                               used_playlists.push_back(to_playlist);
+                               to_playlist->freeze();
+                       }
+                       
                        where = (nframes_t) (unit_to_frame (ix1) * speed);
                        boost::shared_ptr<Region> new_region (RegionFactory::create (rv->region()));
 
-                       /* undo the previous hide_dependent_views so that xfades don't
-                          disappear on copying regions 
-                       */
+                       if (!drag_info.copy) {
 
-                       rv->get_time_axis_view().reveal_dependent_views (*rv);
 
-                       if (!drag_info.copy) {
-                               
                                /* the region that used to be in the old playlist is not
                                   moved to the new one - we make a copy of it. as a result,
                                   any existing editor for the region should no longer be
                                   visible.
                                */ 
-           
+
+                               RouteTimeAxisView* from_playlist_rtv = dynamic_cast<RouteTimeAxisView*>(&(*i)->get_trackview());
+                               boost::shared_ptr<Playlist> from_playlist = from_playlist_rtv->playlist();
+
+                               if (! from_playlist->frozen()) {
+                                       from_playlist->freeze();
+                                       used_playlists.push_back(from_playlist);
+
+                                       sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view));
+                                       used_connections.push_back (c);
+
+                                       session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0));    
+                               }
+
                                rv->hide_region_editor();
                                rv->fake_set_opaque (false);
 
-                               session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0));    
                                from_playlist->remove_region ((rv->region()));
-                               session->add_command (new MementoCommand<Playlist>(*from_playlist, 0, &from_playlist->get_state()));    
 
                        } else {
 
                                /* the regionview we dragged around is a temporary copy, queue it for deletion */
-                               
+
                                copies.push_back (rv);
                        }
 
                        latest_regionview = 0;
-                       
-                       sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
-                       session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));        
+
                        to_playlist->add_region (new_region, where);
-                       session->add_command (new MementoCommand<Playlist>(*to_playlist, 0, &to_playlist->get_state()));        
-                       c.disconnect ();
-                                                             
-                       if (latest_regionview) {
-                               new_selection.push_back (latest_regionview);
-                       }
 
                        /* OK, this is where it gets tricky. If the playlist was being used by >1 tracks, and the region
                           was selected in all of them, then removing it from the playlist will have removed all
@@ -3506,6 +3528,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
                           EXCEPT .... if we are doing a copy drag, then the selection hasn't been modified and
                           we can just iterate.
+
                        */
 
                        if (drag_info.copy) {
@@ -3514,12 +3537,15 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                                if (selection->regions.empty()) {
                                        break;
                                } else { 
-                                       i = selection->regions.by_layer().begin();
+                                 /*
+                                   XXX see above .. but we just froze the playlists.. we have to keep iterating, right? 
+                                 */
+
+                                 //i = selection->regions.by_layer().begin();
+                                 ++i;
                                }
                        }
-               } 
-
-               selection->set (new_selection);
+               }
 
        } else {
 
@@ -3527,13 +3553,11 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
                list<RegionView*> regions = selection->regions.by_layer();
 
-               if (drag_info.copy) {
-                       selection->clear_regions();
-               }
-               
                for (list<RegionView*>::iterator i = regions.begin(); i != regions.end(); ++i) {
 
-                       rv = (*i);
+                       RegionView* rv = (*i);
+                       boost::shared_ptr<Playlist> to_playlist = (*i)->region()->playlist();
+                       RouteTimeAxisView* from_rtv = dynamic_cast<RouteTimeAxisView*> (&(rv->get_time_axis_view()));
 
                        if (!rv->region()->can_move()) {
                                continue;
@@ -3541,10 +3565,9 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
                        if (regionview_x_movement) {
                                double ownspeed = 1.0;
-                               rtv = dynamic_cast<RouteTimeAxisView*> (&(rv->get_time_axis_view()));
 
-                               if (rtv && rtv->get_diskstream()) {
-                                       ownspeed = rtv->get_diskstream()->speed();
+                               if (from_rtv && from_rtv->get_diskstream()) {
+                                       ownspeed = from_rtv->get_diskstream()->speed();
                                }
                                
                                /* base the new region position on the current position of the regionview.*/
@@ -3560,13 +3583,16 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                                where = rv->region()->position();
                        }
 
-                       boost::shared_ptr<Playlist> to_playlist = rv->region()->playlist();
+                       if (! to_playlist->frozen()) {
+                               sigc::connection c = from_rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_and_select_new_region_view));
+                               used_connections.push_back (c);
 
-                       assert (to_playlist);
+                               /* add the undo */      
+                               session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
 
-                       /* add the undo */
-
-                       session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));        
+                               used_playlists.push_back(to_playlist);
+                               to_playlist->freeze();
+                       }
 
                        if (drag_info.copy) {
 
@@ -3582,36 +3608,42 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
 
                                /* add it */
 
-                               latest_regionview = 0;
-                               sigc::connection c = rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
-                               to_playlist->add_region (newregion, (nframes_t) (where * rtv->get_diskstream()->speed()));
-                               c.disconnect ();
-                               
-                               if (latest_regionview) {
-                                       rtv->reveal_dependent_views (*latest_regionview);
-                                       selection->add (latest_regionview);
-                               }
+                               to_playlist->add_region (newregion, (nframes_t) (where * from_rtv->get_diskstream()->speed()));
 
                                /* if the original region was locked, we don't care for the new one */
                                
-                               newregion->set_locked (false);                  
+                               newregion->set_locked (false);
+                               copies.push_back (rv);
                                
                        } else {
 
                                /* just change the model */
 
                                rv->region()->set_position (where, (void*) this);
+                               preserve_selection = true;
 
                        }
 
-                       /* add the redo */
+               }
 
-                       session->add_command (new MementoCommand<Playlist>(*to_playlist, 0, &to_playlist->get_state()));
+       }
+       if (! preserve_selection) {
+         //selection->clear_regions();
+       }
+       while (used_playlists.size() > 0) {
 
-                       if (drag_info.copy) {
-                               copies.push_back (rv);
-                       }
+               list <boost::shared_ptr<Playlist > >::iterator i = used_playlists.begin();
+               (*i)->thaw();
+
+               if (used_connections.size()) {
+                       sigc::connection c = used_connections.front();
+                       c.disconnect();
+                       used_connections.pop_front();
                }
+               /* add the redo */
+
+               session->add_command (new MementoCommand<Playlist>(*(*i), 0, &(*i)->get_state()));
+               used_playlists.pop_front();
        }
 
   out:
@@ -3838,6 +3870,13 @@ Editor::collect_new_region_view (RegionView* rv)
        latest_regionview = rv;
 }
 
+void
+Editor::collect_and_select_new_region_view (RegionView* rv)
+{
+       selection->add(rv);
+       latest_regionview = rv;
+}
+
 void
 Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
 {
@@ -3892,7 +3931,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
 
        /* we need to deselect all other regionviews, and select this one
           i'm ignoring undo stuff, because the region creation will take care of it */
-       selection->set (latest_regionview);
+       //selection->set (latest_regionview);
        
        drag_info.item = latest_regionview->get_canvas_group();
        drag_info.data = latest_regionview;
@@ -4245,6 +4284,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        insert_result = motion_frozen_playlists.insert (pl);
                        if (insert_result.second) {
                                session->add_command(new MementoCommand<Playlist>(*pl, &pl->get_state(), 0));
+                               pl->freeze();
                        }
                }
        }
@@ -4434,7 +4474,7 @@ Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
                }
                
                for (set<boost::shared_ptr<Playlist> >::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) {
-                       //(*p)->thaw ();
+                       (*p)->thaw ();
                        session->add_command (new MementoCommand<Playlist>(*(*p).get(), 0, &(*p)->get_state()));
                }
                
index ca2d7039add2db3289f5708f974506082c426bbf..2cc30aee17f989439e6c2da6bad5e36a437d0b0f 100644 (file)
@@ -117,6 +117,8 @@ Editor::split_region_at (nframes_t where)
 void
 Editor::split_regions_at (nframes_t where, RegionSelection& regions)
 {
+       list <boost::shared_ptr<Playlist > > used_playlists;
+
        begin_reversible_command (_("split"));
 
        // if splitting a single region, and snap-to is using
@@ -135,15 +137,19 @@ Editor::split_regions_at (nframes_t where, RegionSelection& regions)
                snap_to (where);
        }
 
-       for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
 
-               RegionSelection::iterator tmp;
-               
-               tmp = a;
-               ++tmp;
+       for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ++a) {
 
                boost::shared_ptr<Playlist> pl = (*a)->region()->playlist();
 
+               if (! pl->frozen()) {
+                       /* we haven't seen this playlist before */
+
+                       /* remember used playlists so we can thaw them later */ 
+                       used_playlists.push_back(pl);
+                       pl->freeze();
+               }
+
                AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*a);
                if (arv)
                        _new_regionviews_show_envelope = arv->envelope_visible();
@@ -155,9 +161,13 @@ Editor::split_regions_at (nframes_t where, RegionSelection& regions)
                         session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
                }
 
-               a = tmp;
-    }
+       }
+       while (used_playlists.size() > 0) {
 
+               list <boost::shared_ptr<Playlist > >::iterator i = used_playlists.begin();
+               (*i)->thaw();
+               used_playlists.pop_front();
+       }
        commit_reversible_command ();
        _new_regionviews_show_envelope = false;
 }
index 88ff3a0c1e9452b7c991e3da4ffe5248352a388e..72e70955cdc1db7ea5fa1f1826760abf571a0735 100644 (file)
@@ -712,13 +712,16 @@ Editor::update_ruler_visibility ()
        
        time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
        time_canvas_event_box.queue_resize();
-       
+       compute_fixed_ruler_scale();
        update_fixed_rulers();
-       //update_tempo_based_rulers();
-       redisplay_tempo (false);
 
        time_canvas_event_box.show_all();
        time_button_frame.show_all();
+
+       compute_current_bbt_points (leftmost_frame, leftmost_frame + (nframes_t)(canvas_width * frames_per_unit));
+       compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + (nframes_t)(canvas_width * frames_per_unit));
+
+       redisplay_tempo (false);
 }
 
 void
@@ -738,6 +741,22 @@ Editor::update_just_smpte ()
        }
 }
 
+void
+Editor::compute_fixed_ruler_scale ()
+{
+       if (session == 0) {
+               return;
+       }
+
+       if (ruler_shown[ruler_metric_smpte]) {
+               set_smpte_ruler_scale (leftmost_frame, leftmost_frame + (canvas_width * frames_per_unit) );
+       }
+       
+       if (ruler_shown[ruler_metric_minsec]) {
+               set_minsec_ruler_scale (leftmost_frame, leftmost_frame + (canvas_width * frames_per_unit) );
+       }
+}
+
 void
 Editor::update_fixed_rulers ()
 {
@@ -781,7 +800,7 @@ Editor::update_tempo_based_rulers ()
        }
 
        ruler_metrics[ruler_metric_bbt].units_per_pixel = frames_per_unit;
-
+       
        if (ruler_shown[ruler_metric_bbt]) {
                gtk_custom_ruler_set_range (GTK_CUSTOM_RULER(_bbt_ruler), leftmost_frame, leftmost_frame+current_page_frames(),
                                            leftmost_frame, session->current_end_frame());
@@ -814,26 +833,15 @@ Editor::_metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble u
        return ruler_editor->metric_get_minsec (marks, lower, upper, maxchars);
 }
 
-gint
-Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars)
+void
+Editor::set_smpte_ruler_scale (gdouble lower, gdouble upper)
 {
        nframes_t range;
-       nframes_t pos;
        nframes_t spacer;
        nframes_t fr;
-       SMPTE::Time smpte;
-       gchar buf[16];
-       gint nmarks = 0;
-       gint n;
-       bool show_bits = false;
-       bool show_frames = false;
-       bool show_seconds = false;
-       bool show_minutes = false;
-       bool show_hours = false;
-       int mark_modulo;
 
        if (session == 0) {
-               return 0;
+               return;
        }
 
        fr = session->frame_rate();
@@ -847,93 +855,115 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp
        range = (nframes_t) floor (upper - lower);
 
        if (range < (2 * session->frames_per_smpte_frame())) { /* 0 - 2 frames */
-               show_bits = true;
-               mark_modulo = 20;
-               nmarks = 1 + (2 * Config->get_subframes_per_frame());
+               smpte_ruler_scale = smpte_show_bits;
+               smpte_mark_modulo = 20;
+               smpte_nmarks = 2 + (2 * Config->get_subframes_per_frame());
        } else if (range <= (fr / 4)) { /* 2 frames - 0.250 second */
-               show_frames = true;
-               mark_modulo = 1;
-               nmarks = 1 + (range / (nframes_t)session->frames_per_smpte_frame());
+               smpte_ruler_scale = smpte_show_frames;
+               smpte_mark_modulo = 1;
+               smpte_nmarks = 2 + (range / (nframes_t)session->frames_per_smpte_frame());
        } else if (range <= (fr / 2)) { /* 0.25-0.5 second */
-               show_frames = true;
-               mark_modulo = 2;
-               nmarks = 1 + (range / (nframes_t)session->frames_per_smpte_frame());
+               smpte_ruler_scale = smpte_show_frames;
+               smpte_mark_modulo = 2;
+               smpte_nmarks = 2 + (range / (nframes_t)session->frames_per_smpte_frame());
        } else if (range <= fr) { /* 0.5-1 second */
-               show_frames = true;
-               mark_modulo = 5;
-               nmarks = 1 + (range / (nframes_t)session->frames_per_smpte_frame());
+               smpte_ruler_scale = smpte_show_frames;
+               smpte_mark_modulo = 5;
+               smpte_nmarks = 2 + (range / (nframes_t)session->frames_per_smpte_frame());
        } else if (range <= 2 * fr) { /* 1-2 seconds */
-               show_frames = true;
-               mark_modulo = 10;
-               nmarks = 1 + (range / (nframes_t)session->frames_per_smpte_frame());
+               smpte_ruler_scale = smpte_show_frames;
+               smpte_mark_modulo = 10;
+               smpte_nmarks = 2 + (range / (nframes_t)session->frames_per_smpte_frame());
        } else if (range <= 8 * fr) { /* 2-8 seconds */
-               show_seconds = true;
-               mark_modulo = 1;
-               nmarks = 1 + (range / fr);
+               smpte_ruler_scale = smpte_show_seconds;
+               smpte_mark_modulo = 1;
+               smpte_nmarks = 2 + (range / fr);
        } else if (range <= 16 * fr) { /* 8-16 seconds */
-               show_seconds = true;
-               mark_modulo = 2;
-               nmarks = 1 + (range / fr);
+               smpte_ruler_scale = smpte_show_seconds;
+               smpte_mark_modulo = 2;
+               smpte_nmarks = 2 + (range / fr);
        } else if (range <= 30 * fr) { /* 16-30 seconds */
-               show_seconds = true;
-               mark_modulo = 5;
-               nmarks = 1 + (range / fr);
+               smpte_ruler_scale = smpte_show_seconds;
+               smpte_mark_modulo = 5;
+               smpte_nmarks = 2 + (range / fr);
        } else if (range <= 60 * fr) { /* 30-60 seconds */
-               show_seconds = true;
-               mark_modulo = 5;
-               nmarks = 1 + (range / fr);
+               smpte_ruler_scale = smpte_show_seconds;
+               smpte_mark_modulo = 5;
+               smpte_nmarks = 2 + (range / fr);
        } else if (range <= 2 * 60 * fr) { /* 1-2 minutes */
-               show_seconds = true;
-               mark_modulo = 20;
-               nmarks = 1 + (range / fr);
+               smpte_ruler_scale = smpte_show_seconds;
+               smpte_mark_modulo = 15;
+               smpte_nmarks = 2 + (range / fr);
        } else if (range <= 4 * 60 * fr) { /* 2-4 minutes */
-               show_seconds = true;
-               mark_modulo = 30;
-               nmarks = 1 + (range / fr);
+               smpte_ruler_scale = smpte_show_seconds;
+               smpte_mark_modulo = 30;
+               smpte_nmarks = 2 + (range / fr);
        } else if (range <= 10 * 60 * fr) { /* 4-10 minutes */
-               show_minutes = true;
-               mark_modulo = 2;
-               nmarks = 1 + 10;
+               smpte_ruler_scale = smpte_show_minutes;
+               smpte_mark_modulo = 2;
+               smpte_nmarks = 2 + 10;
        } else if (range <= 30 * 60 * fr) { /* 10-30 minutes */
-               show_minutes = true;
-               mark_modulo = 5;
-               nmarks = 1 + 30;
+               smpte_ruler_scale = smpte_show_minutes;
+               smpte_mark_modulo = 5;
+               smpte_nmarks = 2 + 30;
        } else if (range <= 60 * 60 * fr) { /* 30 minutes - 1hr */
-               show_minutes = true;
-               mark_modulo = 10;
-               nmarks = 1 + 60;
+               smpte_ruler_scale = smpte_show_minutes;
+               smpte_mark_modulo = 10;
+               smpte_nmarks = 2 + 60;
        } else if (range <= 4 * 60 * 60 * fr) { /* 1 - 4 hrs*/
-               show_minutes = true;
-               mark_modulo = 30;
-               nmarks = 1 + (60 * 4);
+               smpte_ruler_scale = smpte_show_minutes;
+               smpte_mark_modulo = 30;
+               smpte_nmarks = 2 + (60 * 4);
        } else if (range <= 8 * 60 * 60 * fr) { /* 4 - 8 hrs*/
-               show_hours = true;
-               mark_modulo = 1;
-               nmarks = 1 + 8;
+               smpte_ruler_scale = smpte_show_hours;
+               smpte_mark_modulo = 1;
+               smpte_nmarks = 2 + 8;
        } else if (range <= 16 * 60 * 60 * fr) { /* 16-24 hrs*/
-               show_hours = true;
-               mark_modulo = 1;
-               nmarks = 1 + 24;
+               smpte_ruler_scale = smpte_show_hours;
+               smpte_mark_modulo = 1;
+               smpte_nmarks = 2 + 24;
        } else {
     
                /* not possible if nframes_t is a 32 bit quantity */
     
-               show_hours = true;
-               mark_modulo = 4;
-               nmarks = 1 + 24;
+               smpte_ruler_scale = smpte_show_hours;
+               smpte_mark_modulo = 4;
+               smpte_nmarks = 2 + 24;
        }
   
+}
+
+gint
+Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars)
+{
+       nframes_t pos;
+       nframes_t spacer;
+       SMPTE::Time smpte;
+       gchar buf[16];
+       gint n;
+
+       if (session == 0) {
+               return 0;
+       }
+
+       if (lower > (spacer = (nframes_t)(128 * Editor::get_current_zoom ()))) {
+               lower = lower - spacer;
+       } else {
+               lower = 0;
+       }
+
        pos = (nframes_t) floor (lower);
        
-       *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);  
-       
-       if (show_bits) {
+       *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * smpte_nmarks);  
+       switch (smpte_ruler_scale) {
+       case smpte_show_bits:
+
                // Find smpte time of this sample (pos) with subframe accuracy
                session->sample_to_smpte(pos, smpte, true /* use_offset */, true /* use_subframes */ );
     
-               for (n = 0; n < nmarks; n++) {
+               for (n = 0; n < smpte_nmarks; n++) {
                        session->smpte_to_sample(smpte, pos, true /* use_offset */, true /* use_subframes */ );
-                       if ((smpte.subframes % mark_modulo) == 0) {
+                       if ((smpte.subframes % smpte_mark_modulo) == 0) {
                                if (smpte.subframes == 0) {
                                        (*marks)[n].style = GtkCustomRulerMarkMajor;
                                        snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
@@ -952,15 +982,16 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp
                        // Increment subframes by one
                        SMPTE::increment_subframes( smpte );
                }
-       } else if (show_seconds) {
+         break;
+       case smpte_show_seconds:
                // Find smpte time of this sample (pos)
                session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ );
                // Go to next whole second down
                SMPTE::seconds_floor( smpte );
 
-               for (n = 0; n < nmarks; n++) {
+               for (n = 0; n < smpte_nmarks; n++) {
                        session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ );
-                       if ((smpte.seconds % mark_modulo) == 0) {
+                       if ((smpte.seconds % smpte_mark_modulo) == 0) {
                                if (smpte.seconds == 0) {
                                        (*marks)[n].style = GtkCustomRulerMarkMajor;
                                        (*marks)[n].position = pos;
@@ -978,15 +1009,16 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp
                        (*marks)[n].label = g_strdup (buf);
                        SMPTE::increment_seconds( smpte );
                }
-       } else if (show_minutes) {
+         break;
+       case smpte_show_minutes:
                // Find smpte time of this sample (pos)
                session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ );
                // Go to next whole minute down
                SMPTE::minutes_floor( smpte );
 
-               for (n = 0; n < nmarks; n++) {
+               for (n = 0; n < smpte_nmarks; n++) {
                        session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ );
-                       if ((smpte.minutes % mark_modulo) == 0) {
+                       if ((smpte.minutes % smpte_mark_modulo) == 0) {
                                if (smpte.minutes == 0) {
                                        (*marks)[n].style = GtkCustomRulerMarkMajor;
                                } else {
@@ -1002,15 +1034,17 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp
                        (*marks)[n].position = pos;
                        SMPTE::increment_minutes( smpte );
                }
-       } else if (show_hours) {
+
+         break;
+       case smpte_show_hours:
                // Find smpte time of this sample (pos)
                session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ );
                // Go to next whole hour down
                SMPTE::hours_floor( smpte );
 
-               for (n = 0; n < nmarks; n++) {
+               for (n = 0; n < smpte_nmarks; n++) {
                        session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ );
-                       if ((smpte.hours % mark_modulo) == 0) {
+                       if ((smpte.hours % smpte_mark_modulo) == 0) {
                                (*marks)[n].style = GtkCustomRulerMarkMajor;
                                snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
                        } else {
@@ -1023,16 +1057,21 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp
 
                        SMPTE::increment_hours( smpte );
                }
-       } else { // show_frames
+         break;
+       case smpte_show_frames:
                // Find smpte time of this sample (pos)
                session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ );
                // Go to next whole frame down
                SMPTE::frames_floor( smpte );
 
-               for (n = 0; n < nmarks; n++) {
+               for (n = 0; n < smpte_nmarks; n++) {
                        session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ );
-                       if ((smpte.frames % mark_modulo) == 0)  {
-                               (*marks)[n].style = GtkCustomRulerMarkMajor;
+                       if ((smpte.frames % smpte_mark_modulo) == 0)  {
+                               if (smpte.frames == 0) {
+                                 (*marks)[n].style = GtkCustomRulerMarkMajor;
+                               } else {
+                                 (*marks)[n].style = GtkCustomRulerMarkMinor;
+                               }
                                (*marks)[n].position = pos;
                                snprintf (buf, sizeof(buf), "%s%02u:%02u:%02u:%02u", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
                        } else {
@@ -1044,40 +1083,34 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp
                        (*marks)[n].label = g_strdup (buf);
                        SMPTE::increment( smpte );
                }
+
+         break;
        }
   
-       return nmarks;
+       return smpte_nmarks;
 }
 
 
-gint
-Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars)
+void
+Editor::compute_bbt_ruler_scale (nframes_t lower, nframes_t upper)
 {
         if (session == 0) {
-                return 0;
+                return;
         }
-
        TempoMap::BBTPointList::iterator i;
+        BBT_Time lower_beat, upper_beat; // the beats at each end of the ruler
 
+        session->bbt_time((jack_nframes_t) lower, lower_beat);
+        session->bbt_time((jack_nframes_t) upper, upper_beat);
         uint32_t beats = 0;
-        uint32_t bars = 0;
-        uint32_t desirable_marks;
-       uint32_t magic_accent_number = 1;
-       gint nmarks;
-        char buf[64];
-        gint  n = 0;
-       nframes_t pos;
-       bool bar_helper_on = true;
-       
-       BBT_Time next_beat;
-       nframes_t next_beat_pos;
-
-       if ((desirable_marks = maxchars / 7) == 0) {
-               return 0;
-        }
 
-        /* align the tick marks to whatever we're snapping to... */
+       bbt_accent_modulo = 1;
+       bbt_bar_helper_on = false;
+        bbt_bars = 0;
+        bbt_nmarks = 1;
 
+       bbt_ruler_scale =  bbt_over;
+  
        switch (snap_type) {
        case SnapToAThirdBeat:
                 bbt_beat_subdivision = 3;
@@ -1087,180 +1120,432 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
                break;
        case SnapToAEighthBeat:
                 bbt_beat_subdivision = 8;
-               magic_accent_number = 2;
+               bbt_accent_modulo = 2;
                break;
        case SnapToASixteenthBeat:
                 bbt_beat_subdivision = 16;
-               magic_accent_number = 4;
+               bbt_accent_modulo = 4;
                break;
        case SnapToAThirtysecondBeat:
                 bbt_beat_subdivision = 32;
-               magic_accent_number = 8;
+               bbt_accent_modulo = 8;
                break;
        default:
-              bbt_beat_subdivision = 4;
+                bbt_beat_subdivision = 4;
                break;
        }
 
        if (current_bbt_points == 0 || current_bbt_points->empty()) {
-               return 0;
+               return;
        }
 
        i = current_bbt_points->end();
        i--;
-       bars = (*i).bar - (*current_bbt_points->begin()).bar;
-       beats = current_bbt_points->size() - bars;
+       if ((*i).beat >= (*current_bbt_points->begin()).beat) {
+         bbt_bars = (*i).bar - (*current_bbt_points->begin()).bar;
+       } else {
+         bbt_bars = (*i).bar - (*current_bbt_points->begin()).bar - 1;
+       }
+       beats = current_bbt_points->size() - bbt_bars;
 
        /*Only show the bar helper if there aren't many bars on the screen */
-       if (bars > 1) {
-               bar_helper_on = false;
+       if ((bbt_bars < 2) || (beats < 5)) {
+               bbt_bar_helper_on = true;
        }
 
-       if (desirable_marks > (beats / 4)) {
+       if (bbt_bars > 8192) {
+         bbt_ruler_scale =  bbt_over;
+       } else if (bbt_bars > 1024) {
+         bbt_ruler_scale = bbt_show_64;
+       } else if (bbt_bars > 256) {
+         bbt_ruler_scale = bbt_show_16;
+       } else if (bbt_bars > 64) {
+         bbt_ruler_scale = bbt_show_4;
+       } else if (bbt_bars > 10) {
+         bbt_ruler_scale =  bbt_show_1;
+       } else if (bbt_bars > 2) {
+         bbt_ruler_scale =  bbt_show_beats;
+       } else  if (bbt_bars > 0) {
+         bbt_ruler_scale =  bbt_show_ticks;
+       } else {
+         bbt_ruler_scale =  bbt_show_ticks_detail;
+       } 
 
-               /* we're in beat land...*/
+       if ((bbt_ruler_scale == bbt_show_ticks_detail) && (lower_beat.beats == upper_beat.beats) && (upper_beat.ticks - lower_beat.ticks <= Meter::ticks_per_beat / 4)) {
+               bbt_ruler_scale =  bbt_show_ticks_super_detail;
+       }
+}
 
-               uint32_t tick = 0;
-               uint32_t skip;
-               uint32_t t;
-               nframes_t frame_skip;
-               double frame_skip_error;
-               double accumulated_error;
-               double position_of_helper;
-               bool i_am_accented = false;
-               bool we_need_ticks = false;
-               bool helper_active = false;
-       
-               position_of_helper = lower + (30 * Editor::get_current_zoom ());
+gint
+Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars)
+{
+        if (session == 0) {
+                return 0;
+        }
 
-               if (desirable_marks >= (beats)) {
-                       nmarks = (beats * bbt_beat_subdivision) + 1;
-                       we_need_ticks = true;
-               } else {
-                       nmarks = beats + 1;
+       TempoMap::BBTPointList::iterator i;
+
+        char buf[64];
+        gint  n = 0;
+       nframes_t pos;
+       BBT_Time next_beat;
+       nframes_t next_beat_pos;
+        uint32_t beats = 0;
+
+       uint32_t tick = 0;
+       uint32_t skip;
+       uint32_t t;
+       nframes_t frame_skip;
+       double frame_skip_error;
+       double bbt_position_of_helper;
+       double accumulated_error;
+       bool i_am_accented = false;
+       bool helper_active = false;
+
+       if (current_bbt_points == 0 || current_bbt_points->empty()) {
+               return 0;
+       }
+
+       switch (bbt_ruler_scale) {
+
+       case bbt_show_beats:
+               beats = current_bbt_points->size();
+               bbt_nmarks = beats + 2;
+
+               *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
+
+               (*marks)[0].label = g_strdup(" ");
+               (*marks)[0].position = lower;
+               (*marks)[0].style = GtkCustomRulerMarkMicro;
+               
+               for (n = 1,   i = current_bbt_points->begin(); n < bbt_nmarks && i != current_bbt_points->end(); ++i) {
+                       if  ((*i).type != TempoMap::Beat) {
+                               continue;
+                       }
+                       if ((*i).frame < lower && (bbt_bar_helper_on)) {
+                               snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
+                               (*marks)[0].label = g_strdup (buf); 
+                               helper_active = true;
+                       } else {
+
+                               if ((*i).beat == 1) {
+                                       (*marks)[n].style = GtkCustomRulerMarkMajor;
+                                       snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+                               } else if (((*i).beat % 2 == 1)) {
+                                       (*marks)[n].style = GtkCustomRulerMarkMinor;
+                                       snprintf (buf, sizeof(buf), " ");
+                               } else {
+                                       (*marks)[n].style = GtkCustomRulerMarkMicro;
+                                       snprintf (buf, sizeof(buf), " ");
+                               }
+                               (*marks)[n].label =  g_strdup (buf);
+                               (*marks)[n].position = (*i).frame;
+                               n++;
+                       }
                }
+               break;
 
-               *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
+       case bbt_show_ticks:
+
+               beats = current_bbt_points->size();
+               bbt_nmarks = (beats + 2) * bbt_beat_subdivision;
+
+               bbt_position_of_helper = lower + (30 * Editor::get_current_zoom ());
+               *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
 
                (*marks)[0].label = g_strdup(" ");
                (*marks)[0].position = lower;
                (*marks)[0].style = GtkCustomRulerMarkMicro;
                
-               for (n = 1,   i = current_bbt_points->begin(); n < nmarks && i != current_bbt_points->end(); ++i) {
+               for (n = 1,   i = current_bbt_points->begin(); n < bbt_nmarks && i != current_bbt_points->end(); ++i) {
+                       if  ((*i).type != TempoMap::Beat) {
+                               continue;
+                       }
+                       if ((*i).frame < lower && (bbt_bar_helper_on)) {
+                               snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
+                               (*marks)[0].label = g_strdup (buf); 
+                               helper_active = true;
+                       } else {
 
-                       if ((*i).frame < lower && (bar_helper_on)) {
-                                       snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
-                                       (*marks)[0].label = g_strdup (buf); 
-                                       helper_active = true;
+                               if ((*i).beat == 1) {
+                                       (*marks)[n].style = GtkCustomRulerMarkMajor;
+                                       snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+                               } else {
+                                       (*marks)[n].style = GtkCustomRulerMarkMinor;
+                                       snprintf (buf, sizeof(buf), "%" PRIu32, (*i).beat);
+                               }
+                               if (((*i).frame < bbt_position_of_helper) && helper_active) {
+                                       snprintf (buf, sizeof(buf), " ");
+                               }
+                               (*marks)[n].label =  g_strdup (buf);
+                               (*marks)[n].position = (*i).frame;
+                               n++;
+                       }
+                       
+                       /* Add the tick marks */
+
+                       /* Find the next beat */
+                       next_beat.beats = (*i).beat;
+                       next_beat.bars = (*i).bar;
+                       next_beat.ticks = 0;
+                       
+                       if ((*i).meter->beats_per_bar() > (next_beat.beats + 1)) {
+                                 next_beat.beats += 1;
                        } else {
+                                 next_beat.bars += 1;
+                                 next_beat.beats = 1;
+                       }
+                               
+                       next_beat_pos = session->tempo_map().frame_time(next_beat);
+                       
+                       frame_skip = (nframes_t) floor (frame_skip_error = (session->frame_rate() *  60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute()));
+                       frame_skip_error -= frame_skip;
+                       skip = (uint32_t) (Meter::ticks_per_beat / bbt_beat_subdivision);
 
-                         if ((*i).type == TempoMap::Bar)  {
-                           if (((*i).frame < position_of_helper) && helper_active) {
-                             snprintf (buf, sizeof(buf), " ");
-                           } else {
-                             snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
-                           }
-                           (*marks)[n].label = g_strdup (buf);
-                           (*marks)[n].position = (*i).frame;
-                           (*marks)[n].style = GtkCustomRulerMarkMajor;
-                           n++;
-                           
-                         } else if (((*i).type == TempoMap::Beat) && ((*i).beat > 1)) {
-                           ((((*i).frame < position_of_helper) && bar_helper_on) || !we_need_ticks) ?
-                             snprintf (buf, sizeof(buf), " ") : snprintf (buf, sizeof(buf), "%" PRIu32, (*i).beat);
-                           if (((*i).beat % 2 == 1) || we_need_ticks) {
-                             (*marks)[n].style = GtkCustomRulerMarkMinor;
-                           } else {
-                             (*marks)[n].style = GtkCustomRulerMarkMicro;
-                           }
-                           (*marks)[n].label =  g_strdup (buf);
-                           (*marks)[n].position = (*i).frame;
-                           n++;
-                         }
+                       pos = (*i).frame + frame_skip;
+                       accumulated_error = frame_skip_error;
+
+                       tick = skip;
+                       
+                       for (t = 0; (tick < Meter::ticks_per_beat) && (n < bbt_nmarks) && (pos < next_beat_pos) ; pos += frame_skip, tick += skip, ++t) {
+
+                               if (t % bbt_accent_modulo == (bbt_accent_modulo - 1)) {
+                                       i_am_accented = true;
+                               }
+
+                               snprintf (buf, sizeof(buf), " ");
+                               (*marks)[n].label = g_strdup (buf);
 
+                               /* Error compensation for float to nframes_t*/
+                               accumulated_error += frame_skip_error;
+                               if (accumulated_error > 1) {
+                                       pos += 1;
+                                       accumulated_error -= 1.0f;
+                               }
+
+                               (*marks)[n].position = pos;
+
+                               if ((bbt_beat_subdivision > 4) && i_am_accented) {
+                                       (*marks)[n].style = GtkCustomRulerMarkMinor;
+                               } else {
+                                       (*marks)[n].style = GtkCustomRulerMarkMicro;
+                               }
+                               i_am_accented = false;
+                               n++;
                        }
+               }
 
+         break;
 
-                       /* Add the tick marks */
+       case bbt_show_ticks_detail:
 
-                       if (we_need_ticks && (*i).type == TempoMap::Beat) {
+               beats = current_bbt_points->size();
+               bbt_nmarks = (beats + 2) * bbt_beat_subdivision;
 
-                               /* Find the next beat */
+               bbt_position_of_helper = lower + (30 * Editor::get_current_zoom ());
+               *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
 
-                               next_beat.beats = (*i).beat;
-                               next_beat.bars = (*i).bar;
+               (*marks)[0].label = g_strdup(" ");
+               (*marks)[0].position = lower;
+               (*marks)[0].style = GtkCustomRulerMarkMicro;
+               
+               for (n = 1,   i = current_bbt_points->begin(); n < bbt_nmarks && i != current_bbt_points->end(); ++i) {
+                       if  ((*i).type != TempoMap::Beat) {
+                               continue;
+                       }
+                       if ((*i).frame < lower && (bbt_bar_helper_on)) {
+                               snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
+                               (*marks)[0].label = g_strdup (buf); 
+                               helper_active = true;
+                       } else {
 
-                               if ((*i).meter->beats_per_bar() > (next_beat.beats + 1)) {
-                                 next_beat.beats += 1;
+                               if ((*i).beat == 1) {
+                                       (*marks)[n].style = GtkCustomRulerMarkMajor;
+                                       snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
                                } else {
+                                       (*marks)[n].style = GtkCustomRulerMarkMinor;
+                                       snprintf (buf, sizeof(buf), "%" PRIu32, (*i).beat);
+                               }
+                               if (((*i).frame < bbt_position_of_helper) && helper_active) {
+                                       snprintf (buf, sizeof(buf), " ");
+                               }
+                               (*marks)[n].label =  g_strdup (buf);
+                               (*marks)[n].position = (*i).frame;
+                               n++;
+                       }
+                       
+                       /* Add the tick marks */
+
+                       /* Find the next beat */
+
+                       next_beat.beats = (*i).beat;
+                       next_beat.bars = (*i).bar;
+                       
+                       if ((*i).meter->beats_per_bar() > (next_beat.beats + 1)) {
+                                 next_beat.beats += 1;
+                       } else {
                                  next_beat.bars += 1;
                                  next_beat.beats = 1;
-                               }
+                       }
                                
-                               next_beat_pos = session->tempo_map().frame_time(next_beat);
+                       next_beat_pos = session->tempo_map().frame_time(next_beat);
+                       
+                       frame_skip = (nframes_t) floor (frame_skip_error = (session->frame_rate() *  60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute()));
+                       frame_skip_error -= frame_skip;
+                       skip = (uint32_t) (Meter::ticks_per_beat / bbt_beat_subdivision);
 
-                               frame_skip = (nframes_t) floor (frame_skip_error = (session->frame_rate() *  60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute()));
-                               frame_skip_error -= frame_skip;
-                               skip = (uint32_t) (Meter::ticks_per_beat / bbt_beat_subdivision);
+                       pos = (*i).frame + frame_skip;
+                       accumulated_error = frame_skip_error;
 
-                               pos = (*i).frame + frame_skip;
-                               accumulated_error = frame_skip_error;
+                       tick = skip;
+                       
+                       for (t = 0; (tick < Meter::ticks_per_beat) && (n < bbt_nmarks) && (pos < next_beat_pos) ; pos += frame_skip, tick += skip, ++t) {
 
-                               tick = skip;
-
-                               for (t = 0; (tick < Meter::ticks_per_beat) && (n < nmarks) && (pos < next_beat_pos) ; pos += frame_skip, tick += skip, ++t) {
+                               if (t % bbt_accent_modulo == (bbt_accent_modulo - 1)) {
+                                       i_am_accented = true;
+                               }
 
-                                       if (t % magic_accent_number == (magic_accent_number - 1)) {
-                                               i_am_accented = true;
-                                       }
-                                       if (Editor::get_current_zoom () > 32) {
-                                               snprintf (buf, sizeof(buf), " ");
-                                       } else if ((Editor::get_current_zoom () > 8) && !i_am_accented) {
-                                               snprintf (buf, sizeof(buf), " ");
-                                       } else  if (bar_helper_on && (pos < position_of_helper)) {
-                                               snprintf (buf, sizeof(buf), " ");
-                                       } else {
-                                               snprintf (buf, sizeof(buf), "%" PRIu32, tick);
-                                       }
+                               if (i_am_accented && (pos > bbt_position_of_helper)){
+                                       snprintf (buf, sizeof(buf), "%" PRIu32, tick);
+                               } else {
+                                       snprintf (buf, sizeof(buf), " ");
+                               }
 
-                                       (*marks)[n].label = g_strdup (buf);
+                               (*marks)[n].label = g_strdup (buf);
 
-                                       /* Error compensation for float to nframes_t*/
-                                       accumulated_error += frame_skip_error;
-                                       if (accumulated_error > 1) {
-                                               pos += 1;
-                                               accumulated_error -= 1.0f;
-                                       }
+                               /* Error compensation for float to nframes_t*/
+                               accumulated_error += frame_skip_error;
+                               if (accumulated_error > 1) {
+                                       pos += 1;
+                                       accumulated_error -= 1.0f;
+                               }
 
-                                       (*marks)[n].position = pos;
+                               (*marks)[n].position = pos;
 
-                                       if ((bbt_beat_subdivision > 4) && i_am_accented) {
-                                               (*marks)[n].style = GtkCustomRulerMarkMinor;
-                                       } else {
-                                               (*marks)[n].style = GtkCustomRulerMarkMicro;
-                                       }
-                                       i_am_accented = false;
-                                       n++;
-                               
+                               if ((bbt_beat_subdivision > 4) && i_am_accented) {
+                                       (*marks)[n].style = GtkCustomRulerMarkMinor;
+                               } else {
+                                       (*marks)[n].style = GtkCustomRulerMarkMicro;
                                }
+                               i_am_accented = false;
+                               n++;    
                        }
                }
-               return n; //return the actual number of marks made, since we might have skipped some fro fractional time signatures 
 
-       } else {
+         break;
+
+       case bbt_show_ticks_super_detail:
 
-               /* we're in bar land */
+               beats = current_bbt_points->size();
+               bbt_nmarks = (beats + 2) * bbt_beat_subdivision;
 
-               if (desirable_marks < (bars / 256)) {
-                       nmarks = 1;
-                       *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
-                       snprintf (buf, sizeof(buf), "too many bars... (currently %" PRIu32 ")", bars );
+               bbt_position_of_helper = lower + (30 * Editor::get_current_zoom ());
+               *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
+
+               (*marks)[0].label = g_strdup(" ");
+               (*marks)[0].position = lower;
+               (*marks)[0].style = GtkCustomRulerMarkMicro;
+               
+               for (n = 1,   i = current_bbt_points->begin(); n < bbt_nmarks && i != current_bbt_points->end(); ++i) {
+                       if  ((*i).type != TempoMap::Beat) {
+                                 continue;
+                       }
+                       if ((*i).frame < lower && (bbt_bar_helper_on)) {
+                                 snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
+                                 (*marks)[0].label = g_strdup (buf); 
+                                 helper_active = true;
+                       } else {
+
+                                 if ((*i).beat == 1) {
+                                         (*marks)[n].style = GtkCustomRulerMarkMajor;
+                                         snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+                                 } else {
+                                         (*marks)[n].style = GtkCustomRulerMarkMinor;
+                                         snprintf (buf, sizeof(buf), "%" PRIu32, (*i).beat);
+                                 }
+                                 if (((*i).frame < bbt_position_of_helper) && helper_active) {
+                                         snprintf (buf, sizeof(buf), " ");
+                                 }
+                                 (*marks)[n].label =  g_strdup (buf);
+                                 (*marks)[n].position = (*i).frame;
+                                 n++;
+                       }
+                       
+                       /* Add the tick marks */
+
+                       /* Find the next beat */
+
+                       next_beat.beats = (*i).beat;
+                       next_beat.bars = (*i).bar;
+                       
+                       if ((*i).meter->beats_per_bar() > (next_beat.beats + 1)) {
+                                 next_beat.beats += 1;
+                       } else {
+                                 next_beat.bars += 1;
+                                 next_beat.beats = 1;
+                       }
+                               
+                       next_beat_pos = session->tempo_map().frame_time(next_beat);
+                       
+                       frame_skip = (nframes_t) floor (frame_skip_error = (session->frame_rate() *  60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute()));
+                       frame_skip_error -= frame_skip;
+                       skip = (uint32_t) (Meter::ticks_per_beat / bbt_beat_subdivision);
+
+                       pos = (*i).frame + frame_skip;
+                       accumulated_error = frame_skip_error;
+
+                       tick = skip;
+                       
+                       for (t = 0; (tick < Meter::ticks_per_beat) && (n < bbt_nmarks) && (pos < next_beat_pos) ; pos += frame_skip, tick += skip, ++t) {
+
+                                 if (t % bbt_accent_modulo == (bbt_accent_modulo - 1)) {
+                                         i_am_accented = true;
+                                 }
+
+                                 if (pos > bbt_position_of_helper) {
+                                         snprintf (buf, sizeof(buf), "%" PRIu32, tick);
+                                 } else {
+                                         snprintf (buf, sizeof(buf), " ");
+                                 }
+
+                                 (*marks)[n].label = g_strdup (buf);
+
+                                 /* Error compensation for float to nframes_t*/
+                                 accumulated_error += frame_skip_error;
+                                 if (accumulated_error > 1) {
+                                         pos += 1;
+                                         accumulated_error -= 1.0f;
+                                 }
+
+                                 (*marks)[n].position = pos;
+                                 
+                                 if ((bbt_beat_subdivision > 4) && i_am_accented) {
+                                         (*marks)[n].style = GtkCustomRulerMarkMinor;
+                                 } else {
+                                         (*marks)[n].style = GtkCustomRulerMarkMicro;
+                                 }
+                                 i_am_accented = false;
+                                 n++;  
+                       }
+               }
+
+         break;
+
+       case bbt_over:
+                       bbt_nmarks = 1;
+                       *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
+                       snprintf (buf, sizeof(buf), "cannot handle %" PRIu32 " bars", bbt_bars );
                        (*marks)[0].style = GtkCustomRulerMarkMajor;
                        (*marks)[0].label = g_strdup (buf);
                        (*marks)[0].position = lower;
-               } else if (desirable_marks < (uint32_t)(nmarks = (gint) (bars / 64) + 1)) {
-                       *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
-                       for (n = 0,   i = current_bbt_points->begin(); i != current_bbt_points->end() && n < nmarks; i++) {
+                       n = 1;
+
+         break;
+
+       case bbt_show_64:
+                       bbt_nmarks = (gint) (bbt_bars / 64) + 1;
+                       *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
+                       for (n = 0,   i = current_bbt_points->begin(); i != current_bbt_points->end() && n < bbt_nmarks; i++) {
                                if ((*i).type == TempoMap::Bar)  {
                                        if ((*i).bar % 64 == 1) {
                                                if ((*i).bar % 256 == 1) {
@@ -1280,74 +1565,87 @@ Editor::metric_get_bbt (GtkCustomRulerMark **marks, gdouble lower, gdouble upper
                                        }
                                }
                        }
-               } else if (desirable_marks < (uint32_t)(nmarks = (bars / 16) + 1)) {
-                       *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
-                       for (n = 0,  i = current_bbt_points->begin(); i != current_bbt_points->end() && n < nmarks; i++) {
-                               if ((*i).type == TempoMap::Bar)  {
-                                       if ((*i).bar % 16 == 1) {
-                                               if ((*i).bar % 64 == 1) {
-                                                       snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
-                                                       (*marks)[n].style = GtkCustomRulerMarkMajor;
-                                               } else {
-                                                       snprintf (buf, sizeof(buf), " ");
-                                                       if ((*i).bar % 64 == 33)  {
-                                                               (*marks)[n].style = GtkCustomRulerMarkMinor;
-                                                       } else {
-                                                               (*marks)[n].style = GtkCustomRulerMarkMicro;
-                                                       }
-                                               }
-                                               (*marks)[n].label = g_strdup (buf);
-                                               (*marks)[n].position = (*i).frame;
-                                               n++;
+                       break;
+
+       case bbt_show_16:
+                       bbt_nmarks = (bbt_bars / 16) + 1;
+               *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
+               for (n = 0,  i = current_bbt_points->begin(); i != current_bbt_points->end() && n < bbt_nmarks; i++) {
+                       if ((*i).type == TempoMap::Bar)  {
+                         if ((*i).bar % 16 == 1) {
+                               if ((*i).bar % 64 == 1) {
+                                       snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+                                       (*marks)[n].style = GtkCustomRulerMarkMajor;
+                               } else {
+                                       snprintf (buf, sizeof(buf), " ");
+                                       if ((*i).bar % 64 == 33)  {
+                                               (*marks)[n].style = GtkCustomRulerMarkMinor;
+                                       } else {
+                                               (*marks)[n].style = GtkCustomRulerMarkMicro;
                                        }
                                }
+                               (*marks)[n].label = g_strdup (buf);
+                               (*marks)[n].position = (*i).frame;
+                               n++;
+                         }
                        }
-               } else if (desirable_marks < (uint32_t)(nmarks = (bars / 4) + 1)){
-                       *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
-                       for (n = 0,   i = current_bbt_points->begin(); i != current_bbt_points->end() && n < nmarks; ++i) {
-                               if ((*i).type == TempoMap::Bar)  {
-                                       if ((*i).bar % 4 == 1) {
-                                               if ((*i).bar % 16 == 1) {
-                                                       snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
-                                                       (*marks)[n].style = GtkCustomRulerMarkMajor;
-                                               } else {
-                                                       snprintf (buf, sizeof(buf), " ");
-                                                       if ((*i).bar % 16 == 9)  {
-                                                               (*marks)[n].style = GtkCustomRulerMarkMinor;
-                                                       } else {
-                                                               (*marks)[n].style = GtkCustomRulerMarkMicro;
-                                                       }
-                                               }
-                                               (*marks)[n].label = g_strdup (buf);
-                                               (*marks)[n].position = (*i).frame;
-                                               n++;
+               }
+         break;
+
+       case bbt_show_4:
+               bbt_nmarks = (bbt_bars / 4) + 1;
+               *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks);
+               for (n = 0,   i = current_bbt_points->begin(); i != current_bbt_points->end() && n < bbt_nmarks; ++i) {
+                       if ((*i).type == TempoMap::Bar)  {
+                         if ((*i).bar % 4 == 1) {
+                               if ((*i).bar % 16 == 1) {
+                                       snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+                                       (*marks)[n].style = GtkCustomRulerMarkMajor;
+                               } else {
+                                       snprintf (buf, sizeof(buf), " ");
+                                       if ((*i).bar % 16 == 9)  {
+                                               (*marks)[n].style = GtkCustomRulerMarkMinor;
+                                       } else {
+                                               (*marks)[n].style = GtkCustomRulerMarkMicro;
                                        }
                                }
+                               (*marks)[n].label = g_strdup (buf);
+                               (*marks)[n].position = (*i).frame;
+                               n++;
+                         }
                        }
-               } else {
-                       nmarks = bars + 1;
-                       *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks );
-                       for (n = 0,  i = current_bbt_points->begin(); i != current_bbt_points->end() && n < nmarks; i++) {
-                               if ((*i).type == TempoMap::Bar)  {
-                                       if ((*i).bar % 4 == 1) {
-                                               snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
-                                               (*marks)[n].style = GtkCustomRulerMarkMajor;
-                                       } else {
-                                               snprintf (buf, sizeof(buf), " ");
-                                               if ((*i).bar % 4 == 3)  {
-                                                       (*marks)[n].style = GtkCustomRulerMarkMinor;
-                                               } else {
-                                                       (*marks)[n].style = GtkCustomRulerMarkMicro;
-                                               }
-                                       }
-                                       (*marks)[n].label = g_strdup (buf);
-                                       (*marks)[n].position = (*i).frame;
-                                       n++;
-                               }
-                       }
-               }
-               return n;
+               }
+         break;
+
+       case bbt_show_1:
+  //   default:
+               bbt_nmarks = bbt_bars + 2;
+               *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * bbt_nmarks );
+               for (n = 0,  i = current_bbt_points->begin(); i != current_bbt_points->end() && n < bbt_nmarks; i++) {
+                       if ((*i).type == TempoMap::Bar)  {
+                         if ((*i).bar % 4 == 1) {
+                                       snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+                                       (*marks)[n].style = GtkCustomRulerMarkMajor;
+                         } else {
+                               snprintf (buf, sizeof(buf), " ");
+                               if ((*i).bar % 4 == 3)  {
+                                       (*marks)[n].style = GtkCustomRulerMarkMinor;
+                               } else {
+                                       (*marks)[n].style = GtkCustomRulerMarkMicro;
+                               }
+                         }
+                       (*marks)[n].label = g_strdup (buf);
+                       (*marks)[n].position = (*i).frame;
+                       n++;
+                       }
+               }
+       break;
+
        }
+
+       return n; //return the actual number of marks made, since we might have skipped some from fractional time signatures 
+
 }
 
 gint
@@ -1415,117 +1713,132 @@ sample_to_clock_parts ( nframes_t sample,
        return;
 }
 
-gint
-Editor::metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars)
+void
+Editor::set_minsec_ruler_scale (gdouble lower, gdouble upper)
 {
        nframes_t range;
        nframes_t fr;
-       nframes_t mark_interval;
-       nframes_t pos;
        nframes_t spacer;
-       long hrs, mins, secs, millisecs;
-       gchar buf[16];
-       gint nmarks;
-       gint n;
-       gint mark_modulo = 100;
-       bool show_seconds = false;
-       bool show_minutes = false;
-       bool show_hours = false;
-       nframes_t ilower = (nframes_t) floor (lower);
-       nframes_t iupper = (nframes_t) floor (upper);
 
        if (session == 0) {
-               return 0;
+               return;
        }
 
        fr = session->frame_rate();
 
        /* to prevent 'flashing' */
        if (lower > (spacer = (nframes_t)(128 * Editor::get_current_zoom ()))) {
-               lower = lower - spacer;
+               lower -= spacer;
        } else {
                lower = 0;
        }
-       upper = upper + spacer;
-       range = iupper - ilower;
+       upper += spacer;
+       range = (nframes_t) (upper - lower);
 
        if (range <  (fr / 50)) {
-               mark_interval =  fr / 100; /* show 1/100 seconds */
-               mark_modulo = 10;
+               minsec_mark_interval =  fr / 1000; /* show 1/1000 seconds */
+               minsec_ruler_scale = minsec_show_frames;
+               minsec_mark_modulo = 10;
        } else if (range <= (fr / 10)) { /* 0-0.1 second */
-               mark_interval = fr / 50; /* show 1/50 seconds */
-               mark_modulo = 20;
+               minsec_mark_interval = fr / 1000; /* show 1/1000 seconds */
+               minsec_ruler_scale = minsec_show_frames;
+               minsec_mark_modulo = 10;
        } else if (range <= (fr / 2)) { /* 0-0.5 second */
-               mark_interval = fr / 20;  /* show 1/20 seconds */
-               mark_modulo = 100;
+               minsec_mark_interval = fr / 100;  /* show 1/100 seconds */
+               minsec_ruler_scale = minsec_show_frames;
+               minsec_mark_modulo = 100;
        } else if (range <= fr) { /* 0-1 second */
-               mark_interval = fr / 10;  /* show 1/10 seconds */
-               mark_modulo = 200;
+               minsec_mark_interval = fr / 10;  /* show 1/10 seconds */
+               minsec_ruler_scale = minsec_show_frames;
+               minsec_mark_modulo = 200;
        } else if (range <= 2 * fr) { /* 1-2 seconds */
-               mark_interval = fr / 2; /* show 1/2 seconds */
-               mark_modulo = 500;
+               minsec_mark_interval = fr / 10; /* show 1/10 seconds */
+               minsec_ruler_scale = minsec_show_frames;
+               minsec_mark_modulo = 500;
        } else if (range <= 8 * fr) { /* 2-5 seconds */
-               mark_interval =  fr / 5; /* show 2 seconds */
-               mark_modulo = 1000;
+               minsec_mark_interval =  fr / 5; /* show 2 seconds */
+               minsec_ruler_scale = minsec_show_frames;
+               minsec_mark_modulo = 1000;
        } else if (range <= 16 * fr) { /* 8-16 seconds */
-               mark_interval =  fr; /* show 1 seconds */
-               show_seconds = true;
-               mark_modulo = 5;
+               minsec_mark_interval =  fr; /* show 1 seconds */
+               minsec_ruler_scale = minsec_show_seconds;
+               minsec_mark_modulo = 2;
        } else if (range <= 30 * fr) { /* 10-30 seconds */
-               mark_interval =  fr; /* show 10 seconds */
-               show_seconds = true;
-                mark_modulo = 5;
+               minsec_mark_interval =  fr; /* show 1 seconds */
+               minsec_ruler_scale = minsec_show_seconds;
+                minsec_mark_modulo = 5;
        } else if (range <= 60 * fr) { /* 30-60 seconds */
-                mark_interval = 5 * fr; /* show 5 seconds */
-                show_seconds = true;
-                mark_modulo = 3;
+                minsec_mark_interval = fr; /* show 1 seconds */
+                minsec_ruler_scale = minsec_show_seconds;
+                minsec_mark_modulo = 5;
         } else if (range <= 2 * 60 * fr) { /* 1-2 minutes */
-                mark_interval = 5 * fr; /* show 5 seconds */
-                show_seconds = true;
-                mark_modulo = 3;
+                minsec_mark_interval = 5 * fr; /* show 5 seconds */
+                minsec_ruler_scale = minsec_show_seconds;
+                minsec_mark_modulo = 3;
         } else if (range <= 4 * 60 * fr) { /* 4 minutes */
-                mark_interval = 10 * fr; /* show 10 seconds */
-                show_seconds = true;
-                mark_modulo = 30;
+                minsec_mark_interval = 5 * fr; /* show 10 seconds */
+                minsec_ruler_scale = minsec_show_seconds;
+                minsec_mark_modulo = 30;
         } else if (range <= 10 * 60 * fr) { /* 10 minutes */
-                mark_interval = 30 * fr; /* show 30 seconds */
-                show_seconds = true;
-                mark_modulo = 60;
+                minsec_mark_interval = 30 * fr; /* show 30 seconds */
+                minsec_ruler_scale = minsec_show_seconds;
+                minsec_mark_modulo = 120;
         } else if (range <= 30 * 60 * fr) { /* 10-30 minutes */
-                mark_interval =  60 * fr; /* show 1 minute */
-                show_minutes = true;
-               mark_modulo = 5;
+                minsec_mark_interval =  60 * fr; /* show 1 minute */
+                minsec_ruler_scale = minsec_show_minutes;
+               minsec_mark_modulo = 5;
         } else if (range <= 60 * 60 * fr) { /* 30 minutes - 1hr */
-                mark_interval = 2 * 60 * fr; /* show 2 minutes */
-                show_minutes = true;
-                mark_modulo = 10;
+                minsec_mark_interval = 2 * 60 * fr; /* show 2 minutes */
+                minsec_ruler_scale = minsec_show_minutes;
+                minsec_mark_modulo = 10;
         } else if (range <= 4 * 60 * 60 * fr) { /* 1 - 4 hrs*/
-                mark_interval = 5 * 60 * fr; /* show 10 minutes */
-                show_minutes = true;
-                mark_modulo = 30;
+                minsec_mark_interval = 5 * 60 * fr; /* show 10 minutes */
+                minsec_ruler_scale = minsec_show_minutes;
+                minsec_mark_modulo = 30;
         } else if (range <= 8 * 60 * 60 * fr) { /* 4 - 8 hrs*/
-                mark_interval = 20 * 60 * fr; /* show 20 minutes */
-                show_minutes = true;
-                mark_modulo = 60;
+                minsec_mark_interval = 20 * 60 * fr; /* show 20 minutes */
+                minsec_ruler_scale = minsec_show_minutes;
+                minsec_mark_modulo = 60;
         } else if (range <= 16 * 60 * 60 * fr) { /* 16-24 hrs*/
-                mark_interval =  60 * 60 * fr; /* show 60 minutes */
-                show_hours = true;
-               mark_modulo = 2;
+                minsec_mark_interval =  60 * 60 * fr; /* show 60 minutes */
+                minsec_ruler_scale = minsec_show_hours;
+               minsec_mark_modulo = 2;
         } else {
                                                                                                                    
                 /* not possible if nframes_t is a 32 bit quantity */
                                                                                                                    
-                mark_interval = 4 * 60 * 60 * fr; /* show 4 hrs */
+                minsec_mark_interval = 4 * 60 * 60 * fr; /* show 4 hrs */
         }
+       minsec_nmarks = 2 + (range / minsec_mark_interval);
+}
 
-       nmarks = 1 + (range / mark_interval);
-       *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
-       pos = ((ilower + (mark_interval/2))/mark_interval) * mark_interval;
-       
-       if (show_seconds) {
-               for (n = 0; n < nmarks; pos += mark_interval, ++n) {
-                       sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs);
-                       if (secs % mark_modulo == 0) {
+gint
+Editor::metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble upper, gint maxchars)
+{
+       nframes_t pos;
+       nframes_t spacer;
+       long hrs, mins, secs, millisecs;
+       gchar buf[16];
+       gint n;
+
+       if (session == 0) {
+               return 0;
+       }
+
+       /* to prevent 'flashing' */
+       if (lower > (spacer = (nframes_t)(128 * Editor::get_current_zoom ()))) {
+               lower = lower - spacer;
+       } else {
+               lower = 0;
+       }
+
+       *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * minsec_nmarks);
+       pos = ((((nframes_t) floor(lower)) + (minsec_mark_interval/2))/minsec_mark_interval) * minsec_mark_interval;
+       switch (minsec_ruler_scale) {
+       case minsec_show_seconds:
+               for (n = 0; n < minsec_nmarks; pos += minsec_mark_interval, ++n) {
+                       sample_to_clock_parts (pos, session->frame_rate(), &hrs, &mins, &secs, &millisecs);
+                       if (secs % minsec_mark_modulo == 0) {
                                if (secs == 0) {
                                        (*marks)[n].style = GtkCustomRulerMarkMajor;
                                } else {
@@ -1539,10 +1852,11 @@ Editor::metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble up
                        (*marks)[n].label = g_strdup (buf);
                        (*marks)[n].position = pos;
                }
-        } else if (show_minutes) {
-               for (n = 0; n < nmarks; pos += mark_interval, ++n) {
-                        sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs);
-                        if (mins % mark_modulo == 0) {
+         break;
+       case minsec_show_minutes:
+               for (n = 0; n < minsec_nmarks; pos += minsec_mark_interval, ++n) {
+                        sample_to_clock_parts (pos, session->frame_rate(), &hrs, &mins, &secs, &millisecs);
+                        if (mins % minsec_mark_modulo == 0) {
                                 if (mins == 0) {
                                         (*marks)[n].style = GtkCustomRulerMarkMajor;
                                 } else {
@@ -1556,10 +1870,11 @@ Editor::metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble up
                         (*marks)[n].label = g_strdup (buf);
                         (*marks)[n].position = pos;
                 }
-        } else if (show_hours) {
-                for (n = 0; n < nmarks; pos += mark_interval, ++n) {
-                        sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs);
-                        if (hrs % mark_modulo == 0) {
+         break;
+       case minsec_show_hours:
+                for (n = 0; n < minsec_nmarks; pos += minsec_mark_interval, ++n) {
+                        sample_to_clock_parts (pos, session->frame_rate(), &hrs, &mins, &secs, &millisecs);
+                        if (hrs % minsec_mark_modulo == 0) {
                                 (*marks)[n].style = GtkCustomRulerMarkMajor;
                                 snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs);
                         } else {
@@ -1569,11 +1884,12 @@ Editor::metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble up
                         (*marks)[n].label = g_strdup (buf);
                         (*marks)[n].position = pos;
                 }
-        } else {
-               for (n = 0; n < nmarks; pos += mark_interval, ++n) {
-                       sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs);
-                       if (millisecs % mark_modulo == 0) {
-                               if (millisecs == 0) {
+             break;
+       case minsec_show_frames:
+               for (n = 0; n < minsec_nmarks; pos += minsec_mark_interval, ++n) {
+                       sample_to_clock_parts (pos, session->frame_rate(), &hrs, &mins, &secs, &millisecs);
+                       if (millisecs % minsec_mark_modulo == 0) {
+                               if (secs == 0) {
                                        (*marks)[n].style = GtkCustomRulerMarkMajor;
                                } else {
                                        (*marks)[n].style = GtkCustomRulerMarkMinor;
@@ -1586,7 +1902,8 @@ Editor::metric_get_minsec (GtkCustomRulerMark **marks, gdouble lower, gdouble up
                        (*marks)[n].label = g_strdup (buf);
                        (*marks)[n].position = pos;
                }
+         break;
        }
 
-       return nmarks;
+       return minsec_nmarks;
 }
index 09133a8823c0283fdea35312cc83b81d423d34c0..831fe3b727deb2a82e1ba75e0f064b270cfad56c 100644 (file)
@@ -99,18 +99,44 @@ Editor::tempo_map_changed (Change ignored)
                return;
        }
 
-       ENSURE_GUI_THREAD(bind (mem_fun (*this, &Editor::tempo_map_changed), ignored));
-       
-       redisplay_tempo (false); // redraw rulers and measures
+        ENSURE_GUI_THREAD(bind (mem_fun (*this, &Editor::tempo_map_changed), ignored));
+
+       compute_current_bbt_points(leftmost_frame, leftmost_frame + (nframes_t)(canvas_width * frames_per_unit));
        session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks); // redraw metric markers
+       update_tempo_based_rulers ();
+       if (tempo_map_change_idle_handler_id  < 0) {
+                       tempo_map_change_idle_handler_id = Glib::signal_idle().connect (mem_fun (*this, &Editor::redraw_measures));
+       }
 }
 
-/**
- * This code was originally in tempo_map_changed, but this is called every time the canvas scrolls horizontally. 
- * That's why this is moved in here. The new tempo_map_changed is called when the ARDOUR::TempoMap actually changed.
- */
 void
 Editor::redisplay_tempo (bool immediate_redraw)
+{
+       if (!session) {
+               return;
+       }
+       
+       compute_current_bbt_points (leftmost_frame, leftmost_frame + (nframes_t)(canvas_width * frames_per_unit)); // redraw rulers and measures
+
+       if (immediate_redraw) {
+
+               hide_measures ();
+
+               if (current_bbt_points) {
+                       draw_measures ();
+               }
+
+       } else if (tempo_map_change_idle_handler_id  < 0) {
+
+               tempo_map_change_idle_handler_id = Glib::signal_idle().connect (mem_fun (*this, &Editor::redraw_measures));
+
+       }
+
+       update_tempo_based_rulers ();
+}
+
+void
+Editor::compute_current_bbt_points (nframes_t leftmost, nframes_t rightmost)
 {
        if (!session) {
                return;
@@ -118,8 +144,8 @@ Editor::redisplay_tempo (bool immediate_redraw)
 
        BBT_Time previous_beat, next_beat; // the beats previous to the leftmost frame and after the rightmost frame
 
-       session->bbt_time(leftmost_frame, previous_beat);
-       session->bbt_time(leftmost_frame + current_page_frames(), next_beat);
+       session->bbt_time(leftmost, previous_beat);
+       session->bbt_time(rightmost, next_beat);
 
        if (previous_beat.beats > 1) {
                previous_beat.beats -= 1;
@@ -129,7 +155,7 @@ Editor::redisplay_tempo (bool immediate_redraw)
        }
        previous_beat.ticks = 0;
 
-       if (session->tempo_map().meter_at(leftmost_frame + current_page_frames()).beats_per_bar () > next_beat.beats + 1) {
+       if (session->tempo_map().meter_at(rightmost).beats_per_bar () > next_beat.beats + 1) {
                next_beat.beats += 1;
        } else {
                next_beat.bars += 1;
@@ -142,29 +168,7 @@ Editor::redisplay_tempo (bool immediate_redraw)
                current_bbt_points = 0;
        }
 
-       if (session) {
-               current_bbt_points = session->tempo_map().get_points (session->tempo_map().frame_time (previous_beat), session->tempo_map().frame_time (next_beat));
-               update_tempo_based_rulers ();
-       } else {
-               current_bbt_points = 0;
-       }
-
-       if (immediate_redraw) {
-
-               hide_measures ();
-
-               if (session && current_bbt_points) {
-                       draw_measures ();
-               }
-
-       } else {
-
-               if (session && current_bbt_points) {
-                       Glib::signal_idle().connect (mem_fun (*this, &Editor::redraw_measures));
-               } else {
-                       hide_measures ();
-               }
-       }
+       current_bbt_points = session->tempo_map().get_points (session->tempo_map().frame_time (previous_beat), session->tempo_map().frame_time (next_beat) + 1);
 }
 
 void
@@ -179,6 +183,7 @@ Editor::redraw_measures ()
 {
        hide_measures ();
        draw_measures ();
+       tempo_map_change_idle_handler_id = -1;
        return false;
 }
 
index 2cf96fe02a8d1b20e53624f8ad4f400d43f1fd94..cbaee3d6d2bc766843c2c292378a9915b09e41fb 100644 (file)
@@ -37,6 +37,7 @@
 #include <ardour/audio_track.h>
 #include <ardour/audioregion.h>
 #include <ardour/audioengine.h>
+#include <ardour/audiofilesource.h>
 #include <ardour/gdither.h>
 #include <ardour/utils.h>
 
@@ -86,8 +87,8 @@ static const gchar *dither_types[] = {
 };
 
 static const gchar* channel_strings[] = {
-       N_("stereo"), 
-       N_("mono"), 
+       N_("Stereo"), 
+       N_("Mono"), 
        0
 };
 
@@ -112,7 +113,7 @@ ExportDialog::ExportDialog(PublicEditor& e)
          src_quality_label (_("Conversion Quality"), 1.0, 0.5),
          dither_type_label (_("Dither Type"), 1.0, 0.5),
          cuefile_only_checkbox (_("Export CD Marker File Only")),
-         file_browse_button (_("Browse")),
+         file_chooser (FILE_CHOOSER_ACTION_SAVE),
          track_selector_button (_("Specific tracks ..."))
 {
        guint32 n;
@@ -123,6 +124,7 @@ ExportDialog::ExportDialog(PublicEditor& e)
        track_and_master_selection_allowed = true;
        channel_count_selection_allowed = true;
        export_cd_markers_allowed = true;
+       set_resizable (false);  
 
        WindowTitle title(Glib::get_application_name());
        title += _("Export");
@@ -134,8 +136,6 @@ ExportDialog::ExportDialog(PublicEditor& e)
 
        spec.running = false;
 
-       file_entry.set_name ("ExportFileNameEntry");
-
        master_list = ListStore::create (exp_cols);
        master_selector.set_model (master_list);
 
@@ -176,11 +176,11 @@ ExportDialog::ExportDialog(PublicEditor& e)
        track_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
        master_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
 
-       get_vbox()->pack_start (file_frame, false, false);
+       get_vbox()->pack_start (file_frame, PACK_EXPAND_WIDGET);
 
        hpacker.set_spacing (5);
        hpacker.set_border_width (5);
-       hpacker.pack_start (format_frame, false, false);
+       hpacker.pack_start (format_frame, PACK_SHRINK );
 
        master_scroll.add (master_selector);
        track_scroll.add (track_selector);
@@ -195,19 +195,36 @@ ExportDialog::ExportDialog(PublicEditor& e)
 
        hpacker.pack_start (track_vpacker);
 
-       get_vbox()->pack_start (hpacker);
+       get_vbox()->pack_start (hpacker, PACK_SHRINK);
        
        track_selector_button.set_name ("EditorGTKButton");
        track_selector_button.signal_clicked().connect (mem_fun(*this, &ExportDialog::track_selector_button_click));
 
-       get_vbox()->pack_start (progress_bar, false, false);
+       Gtk::FileFilter filter_wav;
+       filter_wav.set_name("Wav files");
+       filter_wav.add_mime_type("audio/wav");
+       file_chooser.add_filter(filter_wav);
+       
+       Gtk::FileFilter filter_aiff;
+       filter_aiff.set_name("Aiff files");
+       filter_aiff.add_mime_type("audio/aiff");
+       filter_aiff.add_pattern("*.aif");
+       filter_aiff.add_pattern("*.aiff");
+       file_chooser.add_filter(filter_aiff);
+       
+       Gtk::FileFilter filter_any;
+       filter_any.set_name("All files");
+       filter_any.add_pattern("*");
+       file_chooser.add_filter(filter_any);
+       file_chooser.set_no_show_all();
 
-       Gtkmm2ext::set_size_request_to_display_given_text (file_entry, X_("Kg/quite/a/reasonable/size/for/files/i/think"), 5, 8);
+       get_vbox()->pack_start (progress_bar, false, false, 5);
+       progress_bar.set_no_show_all();
+       progress_bar.hide();
 
        file_hbox.set_spacing (5);
        file_hbox.set_border_width (5);
-       file_hbox.pack_start (file_entry, true, true);
-       file_hbox.pack_start (file_browse_button, false, false);
+       file_hbox.pack_start (file_chooser, PACK_EXPAND_WIDGET);
 
        file_frame.add (file_hbox);
        file_frame.set_border_width (5);
@@ -316,37 +333,35 @@ ExportDialog::ExportDialog(PublicEditor& e)
 
        cuefile_only_checkbox.set_name ("ExportCheckbox");
 
-       format_table.set_homogeneous (false);
+       format_table.set_homogeneous (true);
        format_table.set_border_width (5);
        format_table.set_col_spacings (5);
        format_table.set_row_spacings (5);
 
-       format_table.attach (channel_count_label, 0, 1, 0, 1);
-       format_table.attach (channel_count_combo, 1, 2, 0, 1);
+       format_table.attach (channel_count_label, 0, 1, 0, 1, FILL, FILL);
+       format_table.attach (channel_count_combo, 1, 2, 0, 1, FILL, FILL);
        
-       format_table.attach (header_format_label, 0, 1, 1, 2);
-       format_table.attach (header_format_combo, 1, 2, 1, 2);
+       format_table.attach (header_format_label, 0, 1, 1, 2, FILL, FILL);
+       format_table.attach (header_format_combo, 1, 2, 1, 2, FILL, FILL);
 
-       format_table.attach (bitdepth_format_label, 0, 1, 2, 3);
-       format_table.attach (bitdepth_format_combo, 1, 2, 2, 3);
+       format_table.attach (bitdepth_format_label, 0, 1, 2, 3, FILL, FILL);
+       format_table.attach (bitdepth_format_combo, 1, 2, 2, 3, FILL, FILL);
 
-       format_table.attach (endian_format_label, 0, 1, 3, 4);
-       format_table.attach (endian_format_combo, 1, 2, 3, 4);
+       format_table.attach (endian_format_label, 0, 1, 3, 4, FILL, FILL);
+       format_table.attach (endian_format_combo, 1, 2, 3, 4, FILL, FILL);
 
-       format_table.attach (sample_rate_label, 0, 1, 4, 5);
-       format_table.attach (sample_rate_combo, 1, 2, 4, 5);
+       format_table.attach (sample_rate_label, 0, 1, 4, 5, FILL, FILL);
+       format_table.attach (sample_rate_combo, 1, 2, 4, 5, FILL, FILL);
 
-       format_table.attach (src_quality_label, 0, 1, 5, 6);
-       format_table.attach (src_quality_combo, 1, 2, 5, 6);
+       format_table.attach (src_quality_label, 0, 1, 5, 6, FILL, FILL);
+       format_table.attach (src_quality_combo, 1, 2, 5, 6, FILL, FILL);
 
-       format_table.attach (dither_type_label, 0, 1, 6, 7);
-       format_table.attach (dither_type_combo, 1, 2, 6, 7);
+       format_table.attach (dither_type_label, 0, 1, 6, 7, FILL, FILL);
+       format_table.attach (dither_type_combo, 1, 2, 6, 7, FILL, FILL);
 
-       format_table.attach (cue_file_label, 0, 1, 7, 8);
-       format_table.attach (cue_file_combo, 1, 2, 7, 8);
-       format_table.attach (cuefile_only_checkbox, 0, 2, 8, 9);
-
-       file_entry.set_name ("ExportFileDisplay");
+       format_table.attach (cue_file_label, 0, 1, 7, 8, FILL, FILL);
+       format_table.attach (cue_file_combo, 1, 2, 7, 8, FILL, FILL);
+       format_table.attach (cuefile_only_checkbox, 0, 2, 8, 9, FILL, FILL);
 
        signal_delete_event().connect (mem_fun(*this, &ExportDialog::window_closed));
 
@@ -354,15 +369,14 @@ ExportDialog::ExportDialog(PublicEditor& e)
        cancel_button->signal_clicked().connect (mem_fun(*this, &ExportDialog::end_dialog));
        ok_button = add_button (_("Export"), RESPONSE_ACCEPT);
        ok_button->signal_clicked().connect (mem_fun(*this, &ExportDialog::do_export));
-       
-       file_browse_button.set_name ("EditorGTKButton");
-       file_browse_button.signal_clicked().connect (mem_fun(*this, &ExportDialog::browse));
-
        channel_count_combo.signal_changed().connect (mem_fun(*this, &ExportDialog::channels_chosen));
        bitdepth_format_combo.signal_changed().connect (mem_fun(*this, &ExportDialog::bitdepth_chosen));
        header_format_combo.signal_changed().connect (mem_fun(*this, &ExportDialog::header_chosen));
        sample_rate_combo.signal_changed().connect (mem_fun(*this, &ExportDialog::sample_rate_chosen));
        cue_file_combo.signal_changed().connect (mem_fun(*this, &ExportDialog::cue_file_type_chosen));
+
+       file_chooser.signal_update_preview().connect (mem_fun(*this, &ExportDialog::file_chooser_selection_changed));
+
 }
 
 ExportDialog::~ExportDialog()
@@ -373,24 +387,18 @@ void
 ExportDialog::do_not_allow_track_and_master_selection()
 {
        track_and_master_selection_allowed = false;
-       track_vpacker.set_no_show_all();
 }
 
 void
 ExportDialog::do_not_allow_channel_count_selection()
 {
        channel_count_selection_allowed = false;
-       channel_count_combo.set_no_show_all();
-       channel_count_label.set_no_show_all();
 }
 
 void
 ExportDialog::do_not_allow_export_cd_markers()
 {
        export_cd_markers_allowed = false;
-       cue_file_label.set_no_show_all();
-       cue_file_combo.set_no_show_all();
-       cuefile_only_checkbox.set_no_show_all();
 }
 
 void
@@ -433,7 +441,7 @@ ExportDialog::set_state()
 {
        XMLNode* node = session->instant_xml(X_("ExportDialog"));
        XMLProperty* prop;
-
+       bool fc_location_requested = false;
        if (node) {
 
                if ((prop = node->property (X_("sample_rate"))) != 0) {
@@ -458,13 +466,28 @@ ExportDialog::set_state()
                        endian_format_combo.set_active_text(prop->value());
                }
                if ((prop = node->property (X_("filename"))) != 0) {
-                       file_entry.set_text(prop->value());
+                       file_chooser.set_filename(prop->value());
+                       fc_location_requested = true;
+                       file_chooser.set_current_folder(Glib::path_get_basename(prop->value()));
                }
+                 
                if ((prop = node->property (X_("cue_file_type"))) != 0) {
                        cue_file_combo.set_active_text(prop->value());
                }
        }
 
+       if (!fc_location_requested) {
+
+               /*
+                 If the filename hasn't been set before, use the
+                 current session's export directory as a default
+                 location for the export.  
+               */
+
+               file_chooser.set_current_folder (session->session_directory().export_path().to_string());
+               file_chooser.set_current_name (_("export.wav"));
+       }
+
        header_chosen ();
        bitdepth_chosen();
        channels_chosen();
@@ -488,7 +511,7 @@ ExportDialog::set_state()
                if (!master) {
                        
                        /* default is to use all */
-                       if (channel_count_combo.get_active_text() == _("mono")) {
+                       if (channel_count_combo.get_active_text() == _("Mono")) {
                                nchns = 1;
                        } else {
                                nchns = 2;
@@ -564,7 +587,7 @@ ExportDialog::save_state()
        node->add_property(X_("header_format"), header_format_combo.get_active_text());
        node->add_property(X_("bitdepth_format"), bitdepth_format_combo.get_active_text());
        node->add_property(X_("endian_format"), endian_format_combo.get_active_text());
-       node->add_property(X_("filename"), file_entry.get_text());
+       node->add_property(X_("filename"), file_chooser.get_filename());
        node->add_property(X_("cue_file_type"), cue_file_combo.get_active_text());
 
        XMLNode* tracks = new XMLNode(X_("Tracks"));
@@ -888,7 +911,7 @@ ExportDialog::do_export_cd_markers (const string& path,const string& cuefile_typ
 void
 ExportDialog::do_export ()
 {
-       string filepath = file_entry.get_text();
+       string filepath = file_chooser.get_filename();
        
        if(!is_filepath_valid(filepath)){
                return;
@@ -896,7 +919,7 @@ ExportDialog::do_export ()
 
        if (export_cd_markers_allowed) {
                if (cue_file_combo.get_active_text () != _("None")) {
-                       do_export_cd_markers (file_entry.get_text(), cue_file_combo.get_active_text ());
+                       do_export_cd_markers (file_chooser.get_filename(), cue_file_combo.get_active_text ());
                }
 
                if (cuefile_only_checkbox.get_active()) {
@@ -913,12 +936,15 @@ ExportDialog::do_export ()
        // read user input into spec
        initSpec(filepath);
        
+       progress_bar.show();
        progress_connection = Glib::signal_timeout().connect (mem_fun(*this, &ExportDialog::progress_timeout), 100);
        cancel_label.set_text (_("Stop Export"));
 
        export_audio_data();
        
        progress_connection.disconnect ();
+       session->engine().freewheel (false);
+       progress_bar.hide();
        end_dialog ();
 }
        
@@ -937,9 +963,9 @@ ExportDialog::end_dialog ()
                }
        }
 
-       session->finalize_audio_export ();
+       hide ();
 
-       hide_all ();
+       session->finalize_audio_export ();
 
        set_modal (false);
        ok_button->set_sensitive(true);
@@ -967,11 +993,39 @@ ExportDialog::start_export ()
                
                file_entry.set_text (export_file_path.to_string());
        }
-       
+
        progress_bar.set_fraction (0);
+       progress_bar.hide();
+       progress_bar.set_no_show_all();
        cancel_label.set_text (_("Cancel"));
 
-       show_all ();
+       show_all();
+
+       if (track_and_master_selection_allowed) {
+               track_vpacker.show();
+       } else {
+               track_vpacker.hide();
+       }
+
+       file_chooser.show();
+
+       if (channel_count_selection_allowed) {
+               channel_count_combo.show();
+               channel_count_label.show();
+       } else {
+               channel_count_combo.hide();
+               channel_count_label.hide();
+       }
+
+       if (export_cd_markers_allowed) {
+               cue_file_label.show();
+               cue_file_combo.show();
+               cuefile_only_checkbox.show();
+       } else {
+               cue_file_label.hide();
+               cue_file_combo.hide();
+               cuefile_only_checkbox.hide();
+       }
 
        if (session->master_out()) {
                track_scroll.hide ();
@@ -979,15 +1033,21 @@ ExportDialog::start_export ()
                master_scroll.hide ();
                track_selector_button.hide ();
        }
+
+       track_and_master_selection_allowed = true;
+       channel_count_selection_allowed =  true;
+       export_cd_markers_allowed = true;
 }
 
 void
 ExportDialog::header_chosen ()
 {
        if (sndfile_header_format_from_string (header_format_combo.get_active_text ()) == SF_FORMAT_WAV) {
+               endian_format_combo.set_active_text (N_("Little-endian (Intel)"));
                endian_format_combo.set_sensitive (false);
        } else {
                endian_format_combo.set_sensitive (true);
+               endian_format_combo.set_active_text (N_("Big-endian (Mac)"));
        }
 }
 
@@ -1019,6 +1079,65 @@ ExportDialog::cue_file_type_chosen ()
        }
 }
 
+void
+ExportDialog::file_chooser_selection_changed ()
+{
+
+  /*
+    if the user selects an existing file from the 'browse for other folders' tab,
+    change the format settings to match the file.
+  */
+       if (file_chooser.get_filename().length() == 0) {
+               return;
+       }
+       if (Glib::file_test(file_chooser.get_preview_filename(),Glib::FILE_TEST_IS_DIR)){
+               file_chooser.set_current_name (_(""));
+               return;
+       }
+       if (!Glib::file_test(file_chooser.get_preview_filename(),Glib::FILE_TEST_EXISTS)) {
+               return;
+       }
+
+       SoundFileInfo finfo;
+       string error_msg, format_str;
+       
+       if (!AudioFileSource::get_soundfile_info (file_chooser.get_preview_filename(), finfo, error_msg)) {
+               error << string_compose(_("Export: cannot open file \"%1\"."), error_msg ) << endmsg;
+               return;
+       }
+
+       if (finfo.samplerate == 22050) {
+               sample_rate_combo.set_active_text (N_("22.05kHz"));
+       } else if (finfo.samplerate == 44100) {
+               sample_rate_combo.set_active_text (N_("44.1kHz"));
+       } else if (finfo.samplerate == 48000) {
+               sample_rate_combo.set_active_text (N_("48kHz"));
+       } else if (finfo.samplerate == 88200) {
+               sample_rate_combo.set_active_text (N_("88.2kHz"));
+       } else if (finfo.samplerate == 96000) {
+               sample_rate_combo.set_active_text (N_("96kHz"));
+       } else if (finfo.samplerate == 192000) {
+               sample_rate_combo.set_active_text (N_("192kHz"));
+       } 
+
+       if (finfo.channels == 1) {
+               channel_count_combo.set_active_text(N_("Mono"));
+       } else {
+               channel_count_combo.set_active_text(N_("Stereo"));
+       }
+
+       string::size_type pos;
+
+       pos = finfo.format_name.find_first_of (" ");
+       format_str = finfo.format_name.substr(pos + 1, 255);
+       pos = format_str.find_first_of (" ");
+       header_format_combo.set_active_text(format_str.substr(0, pos));
+
+       format_str = finfo.format_name;
+       pos = format_str.find_first_of (",");
+       bitdepth_format_combo.set_active_text(format_str.substr(pos + 2, 255));
+}
+
 void
 ExportDialog::sample_rate_chosen ()
 {
@@ -1053,7 +1172,7 @@ ExportDialog::channels_chosen ()
 {
        bool mono;
 
-       mono = (channel_count_combo.get_active_text() == _("mono"));
+       mono = (channel_count_combo.get_active_text() == _("Mono"));
 
        if (mono) {
                track_selector.get_column(2)->set_visible(false);
@@ -1145,7 +1264,7 @@ ExportDialog::is_filepath_valid(string &filepath)
                        return false;
                }
                else {
-                       string txt = _("File already exists, do you want to overwrite it?");
+                       string txt = _("File ") + filepath + _(" already exists, do you want to overwrite it?");
                        MessageDialog msg (*this, txt, false, MESSAGE_QUESTION, BUTTONS_YES_NO, true);
                        if ((ResponseType) msg.run() == Gtk::RESPONSE_NO) {
                                return false;
@@ -1175,7 +1294,7 @@ ExportDialog::initSpec(string &filepath)
        spec.stop = false;
        spec.port_map.clear();
        
-       if (channel_count_combo.get_active_text() == _("mono")) {
+       if (channel_count_combo.get_active_text() == _("Mono")) {
                spec.channels = 1;
        } else {
                spec.channels = 2;
@@ -1305,27 +1424,6 @@ ExportDialog::window_closed (GdkEventAny *ignored)
        return TRUE;
 }
 
-void
-ExportDialog::browse ()
-{
-       FileChooserDialog dialog("Export to file", browse_action());
-       dialog.set_transient_for(*this);
-       dialog.set_filename (file_entry.get_text());
-
-       dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
-       dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
-  
-       int result = dialog.run();
-
-       if (result == Gtk::RESPONSE_OK) {
-               string filename = dialog.get_filename();
-       
-               if (filename.length()) {
-                       file_entry.set_text (filename);
-               }
-       }
-}
-
 void
 ExportDialog::track_selector_button_click ()
 {
index 596467d3e1e0c2057844dc8a90e7a760e66926c9..d518f5ec8a8a7e007da5f59cddee77fc307a24de 100644 (file)
@@ -134,7 +134,7 @@ class ExportDialog : public ArdourDialog
 
        Gtk::Entry  file_entry;
        Gtk::HBox   file_hbox;
-       Gtk::Button file_browse_button;
+       Gtk::FileChooserWidget file_chooser;
 
        Gtk::Button* ok_button;
        Gtk::Button* cancel_button;
@@ -159,6 +159,7 @@ class ExportDialog : public ArdourDialog
        void bitdepth_chosen ();
        void sample_rate_chosen ();
        void cue_file_type_chosen();
+       void file_chooser_selection_changed();
 
        void fill_lists();
        void write_track_and_master_selection_to_spec();
@@ -171,8 +172,6 @@ class ExportDialog : public ArdourDialog
 
        void track_selector_button_click ();
 
-       void browse ();
-
        void set_state();
        void save_state();
 };
index 699ecdbcfa1fcc0de13bde94a871fc95f2fec8ae..cb8e7f235bb9185bc846eaa59060019a2dfc83e8 100644 (file)
@@ -141,7 +141,7 @@ RegionView::init (Gdk::Color& basic_color, bool wfd)
        sync_mark->property_fill_color_rgba() = fill_color;
        sync_mark->hide();
 
-       reset_width_dependent_items ((double) _region->length() / samples_per_unit);
+       //reset_width_dependent_items ((double) _region->length() / samples_per_unit);
 
        if (wfd)
                _enable_display = true;
@@ -214,9 +214,14 @@ RegionView::region_changed (Change what_changed)
        if (what_changed & Region::SyncOffsetChanged) {
                region_sync_changed ();
        }
+       /* 
+          this should not be needed now that only playlist can change layering
+       */
+       /*
        if (what_changed & Region::LayerChanged) {
                region_layered ();
        }
+       */
        if (what_changed & Region::LockChanged) {
                region_locked ();
        }
index 1a3fb9a0842ce3a39f6b74ceca16433ceb7ee802..f6d6924a761efd17c7da49c2829f81b5842d989a 100644 (file)
@@ -285,17 +285,18 @@ StreamView::apply_color (Gdk::Color& color, ColorTarget target)
 void
 StreamView::region_layered (RegionView* rv)
 {
-       rv->get_canvas_group()->lower_to_bottom();
 
-       /* don't ever leave it at the bottom, since then it doesn't
-          get events - the  parent group does instead ...
-       */
-       
-       /* this used to be + 1, but regions to the left ended up below
-         ..something.. and couldn't receive events.  why?  good question.
-       */
-       /* and now it's + 3 for midi note separator lines */
-       rv->get_canvas_group()->raise (rv->region()->layer() + 3);
+        /* 
+           Currently 'layer' has nothing to do with the desired canvas layer.
+            For now, ensure that multiple regionviews passed here in groups are 
+           ordered by 'layer' (lowest to highest). 
+
+           (see AudioStreamView::redisplay_diskstream ()).
+           We move them to the top layer as they arrive. 
+        */
+
+       rv->get_canvas_group()->raise_to_top();
 }
 
 void
index af08d4569c02ddae3be05bb79247b5972134ed7c..bcbc7c78acfb2f951ede484f904a2128bb9cb10b 100644 (file)
@@ -232,33 +232,11 @@ def CheckJackRecomputeLatency(context):
         context.Result(result)
         return result
 
-#
-# See if JACK supports jack_port_ensure_monitor_input()
-#
-jack_ensure_monitor_input_test = """
-#include <jack/jack.h>
-int main(int argc, char** argv)
-{
-           jack_port_t **port;
-
-           jack_port_ensure_monitor (*port, 1);
-           return 0;
-
-}
-"""
-
-def CheckJackEnsureMonitorInput(context):
-        context.Message('Checking for jack_port_ensure_monitor_input()...')
-        result = context.TryLink(jack_ensure_monitor_input_test, '.c')
-        context.Result(result)
-        return result
-
 conf = Configure(ardour, custom_tests = {
        'CheckJackClientOpen' : CheckJackClientOpen,
        'CheckJackRecomputeLatencies' : CheckJackRecomputeLatencies,
        'CheckJackRecomputeLatency' : CheckJackRecomputeLatency,
-       'CheckJackVideoFrameOffset' : CheckJackVideoFrameOffset,
-       'CheckJackEnsureMonitorInput' : CheckJackEnsureMonitorInput
+       'CheckJackVideoFrameOffset' : CheckJackVideoFrameOffset
 })
 
 if conf.CheckJackClientOpen():
@@ -272,11 +250,6 @@ if conf.CheckJackRecomputeLatency():
 
 if conf.CheckJackVideoFrameOffset():
        ardour.Append(CXXFLAGS="-DHAVE_JACK_VIDEO_SUPPORT")
-       
-if conf.CheckJackEnsureMonitorInput():
-       ardour.Append(CXXFLAGS='-DHAVE_JACK_PORT_ENSURE_MONITOR')
-else:
-    print '\nWARNING: You need at least svn revision 985 of jack for hardware monitoring to work correctly.\n'
 
 #
 # Optional header files
index 7b22528bd17756defee57e2fa248ab0ab9f6caac..3865019bc768961d35a769efe57a6b70357fed12 100644 (file)
@@ -61,10 +61,6 @@ const nframes_t frames_per_peak = 256;
        
        /* returns the number of items in this `audio_source' */
 
-       virtual nframes_t length() const {
-               return _length;
-       }
-
        virtual nframes_t available_peaks (double zoom) const;
 
        virtual nframes_t read (Sample *dst, nframes_t start, nframes_t cnt) const;
@@ -120,7 +116,6 @@ const nframes_t frames_per_peak = 256;
        bool                 _peaks_built;
        mutable Glib::Mutex  _lock;
        mutable Glib::Mutex  _peaks_ready_lock;
-       nframes_t            _length;
        Glib::ustring               peakpath;
        Glib::ustring              _captured_for;
 
index c3c31c938d00969c5cb34f12465fbdba08ab8517..d973ed2cab76c0ff3cdfc2a1bd8c17bc4f7606a3 100644 (file)
@@ -62,13 +62,7 @@ class JackPort : public virtual Port {
        }
 
        void ensure_monitor_input (bool yn) {
-
-#ifdef HAVE_JACK_PORT_ENSURE_MONITOR
                jack_port_ensure_monitor (_port, yn);
-#else
-               jack_port_request_monitor(_port, yn);
-#endif
-
        }
 
        /*XXX completely bloody useless imho*/
index 0c5a8e044f080a55cbb8d64043812224b627f96e..8dd9ccc211518f21f3c643850432da8d63a7e47b 100644 (file)
@@ -279,7 +279,7 @@ namespace ARDOUR {
        enum MonitorModel {
                HardwareMonitoring,
                SoftwareMonitoring,
-               ExternalMonitoring,
+               ExternalMonitoring
        };
 
        enum DenormalModel {
@@ -292,7 +292,7 @@ namespace ARDOUR {
        enum RemoteModel {
                UserOrdered,
                MixerOrdered,
-               EditorOrdered,
+               EditorOrdered
        };
 
        enum CrossfadeModel {
index f4c10cbc1295aedbf423418403407767e5bc007c..0631c9121b1fcf5e2b2acf257d07dddac6eaf7a0 100644 (file)
@@ -337,6 +337,7 @@ AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
        boost::shared_ptr<AudioRegion> top;
        boost::shared_ptr<AudioRegion> bottom;
        boost::shared_ptr<Crossfade>   xfade;
+       RegionList*  touched_regions;
 
        if (in_set_state || in_partition) {
                return;
@@ -398,7 +399,7 @@ AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
                                break;
 
                        case OverlapExternal:
-
                                /*     [ -------- top ------- ]
                                 * {=========== bottom =============}
                                 */
@@ -411,11 +412,15 @@ AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
                                */
                                
                                xfade_length = min ((nframes_t) 720, top->length());
-                               
-                               xfade = boost::shared_ptr<Crossfade> (new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn));
-                               add_crossfade (xfade);
+
+                               if (top_region_at (top->first_frame()) == top) {
+                                       xfade = boost::shared_ptr<Crossfade> (new Crossfade (top, bottom, xfade_length, top->first_frame(), StartOfIn));
+                                       add_crossfade (xfade);
+                               }
 
                                if (top_region_at (top->last_frame() - 1) == top) {
+
                                        /* 
                                           only add a fade out if there is no region on top of the end of 'top' (which 
                                           would cover it).
@@ -425,9 +430,58 @@ AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
                                        add_crossfade (xfade);
                                }
                                break;
-                               
+                       case OverlapStart:
+
+                               /*                   { ==== top ============ } 
+                                *   [---- bottom -------------------] 
+                                */
+
+                               if (Config->get_xfade_model() == FullCrossfade) {
+                                       touched_regions = regions_touched (top->first_frame(), bottom->last_frame());
+                                       if (touched_regions->size() <= 2) {
+                                               xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
+                                               add_crossfade (xfade);
+                                       }
+                               } else {
+
+                                       touched_regions = regions_touched (top->first_frame(), 
+                                                                          top->first_frame() + min ((nframes_t)Config->get_short_xfade_seconds() * _session.frame_rate(), 
+                                                                                                    top->length()));
+                                       if (touched_regions->size() <= 2) {
+                                               xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
+                                               add_crossfade (xfade);
+                                       }
+                               }
+                               break;
+                       case OverlapEnd:
+
+
+                               /* [---- top ------------------------] 
+                                *                { ==== bottom ============ } 
+                                */ 
+
+                               if (Config->get_xfade_model() == FullCrossfade) {
+
+                                       touched_regions = regions_touched (bottom->first_frame(), top->last_frame());
+                                       if (touched_regions->size() <= 2) {
+                                               xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, 
+                                                                                                    Config->get_xfade_model(), Config->get_xfades_active()));
+                                               add_crossfade (xfade);
+                                       }
+
+                               } else {
+                                       touched_regions = regions_touched (bottom->first_frame(), 
+                                                                          bottom->first_frame() + min ((nframes_t)Config->get_short_xfade_seconds() * _session.frame_rate(), 
+                                                                                                       bottom->length()));
+                                       if (touched_regions->size() <= 2) {
+                                               xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
+                                               add_crossfade (xfade);
+                                       }
+                               }
+                               break;
                        default:
-                               xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, Config->get_xfade_model(), Config->get_xfades_active()));
+                               xfade = boost::shared_ptr<Crossfade> (new Crossfade (region, other, 
+                                                                                    Config->get_xfade_model(), Config->get_xfades_active()));
                                add_crossfade (xfade);
                        }
                }
@@ -471,6 +525,7 @@ void AudioPlaylist::notify_crossfade_added (boost::shared_ptr<Crossfade> x)
        if (g_atomic_int_get(&block_notifications)) {
                _pending_xfade_adds.insert (_pending_xfade_adds.end(), x);
        } else {
+
                NewCrossfade (x); /* EMIT SIGNAL */
        }
 }
index badd13412e924d419510af8b6b44d95ca62f56f8..7405077cf33b0fc0b120b3c0f8e837c33a1341a3 100644 (file)
@@ -486,7 +486,7 @@ ARDOUR::coverage (nframes_t sa, nframes_t ea,
             "B overlaps the end of A"                             
 
        */
-       if ((sb >= sa) && (sb <= ea)) {
+       if ((sb > sa) && (sb <= ea)) {
                return OverlapEnd;
        }
        /*
index 09b54000d8a07b93829d1a82d5d556fe4ae968bb..8d20d8539d75417cb5bc6313f6629f76b6a9738b 100644 (file)
@@ -70,6 +70,7 @@ struct RegionSortByLastLayerOp {
     }
 };
 
+
 Playlist::Playlist (Session& sess, string nom, DataType type, bool hide)
        : SessionObject(sess, nom)
        , _type(type)
@@ -350,7 +351,9 @@ Playlist::notify_region_removed (boost::shared_ptr<Region> r)
                /* this might not be true, but we have to act
                   as though it could be.
                */
+               pending_length = false;
                LengthChanged (); /* EMIT SIGNAL */
+               pending_modified = false;
                Modified (); /* EMIT SIGNAL */
        }
 }
@@ -367,7 +370,9 @@ Playlist::notify_region_added (boost::shared_ptr<Region> r)
                pending_modified = true;
                pending_length = true;
        } else {
+               pending_length = false;
                LengthChanged (); /* EMIT SIGNAL */
+               pending_modified = false;
                Modified (); /* EMIT SIGNAL */
        }
 }
@@ -378,7 +383,9 @@ Playlist::notify_length_changed ()
        if (holding_state ()) {
                pending_length = true;
        } else {
+               pending_length = false;
                LengthChanged(); /* EMIT SIGNAL */
+               pending_modified = false;
                Modified (); /* EMIT SIGNAL */
        }
 }
@@ -437,6 +444,7 @@ Playlist::flush_notifications ()
                }
                pending_modified = false;
                Modified (); /* EMIT SIGNAL */
+               
        }
 
        for (s = dependent_checks_needed.begin(); s != dependent_checks_needed.end(); ++s) {
@@ -458,7 +466,7 @@ void
 Playlist::add_region (boost::shared_ptr<Region> region, nframes_t position, float times) 
 { 
        RegionLock rlock (this);
-       
+       delay_notifications();
        times = fabs (times);
        
        int itimes = (int) floor (times);
@@ -494,6 +502,8 @@ Playlist::add_region (boost::shared_ptr<Region> region, nframes_t position, floa
                boost::shared_ptr<Region> sub = RegionFactory::create (region, 0, length, name, region->layer(), region->flags());
                add_region_internal (sub, pos);
        }
+
+       release_notifications ();
 }
 
 void
@@ -654,7 +664,6 @@ Playlist::partition (nframes_t start, nframes_t end, bool just_top_level)
 void
 Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, RegionList& thawlist)
 {
-       RegionLock rlock (this);
        boost::shared_ptr<Region> region;
        boost::shared_ptr<Region> current;
        string new_name;
@@ -662,14 +671,19 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
        OverlapType overlap;
        nframes_t pos1, pos2, pos3, pos4;
        RegionList new_regions;
+       RegionList copy;
 
        in_partition = true;
 
+       delay_notifications();
+
        /* need to work from a copy, because otherwise the regions we add during the process
           get operated on as well.
        */
-
-       RegionList copy = regions;
+       {
+               RegionLock rlock (this);
+               copy = regions;
+       }
 
        for (RegionList::iterator i = copy.begin(); i != copy.end(); i = tmp) {
                
@@ -677,9 +691,10 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                ++tmp;
 
                current = *i;
-               
+
                if (current->first_frame() == start && current->last_frame() == end) {
                        if (cutting) {
+                               RegionLock rlock (this);
                                remove_region_internal (current);
                        }
                        continue;
@@ -688,14 +703,14 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                if ((overlap = current->coverage (start, end)) == OverlapNone) {
                        continue;
                }
-               
+
                pos1 = current->position();
                pos2 = start;
                pos3 = end;
                pos4 = current->last_frame();
 
                if (overlap == OverlapInternal) {
-                       
+
                        /* split: we need 3 new regions, the front, middle and end.
                           cut:   we need 2 regions, the front and end.
                        */
@@ -715,9 +730,10 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                                
                                /* "middle" ++++++ */
                                
-                               _session.region_name (new_name, current->name(), false);
+                               _session.region_name (new_name, current->name(), false); //takes the session-wide region lock
                                region = RegionFactory::create (current, pos2 - pos1, pos3 - pos2, new_name,
                                                       regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::LeftOfSplit|Region::RightOfSplit));
+                               RegionLock rlock (this);
                                add_region_internal (region, start);
                                new_regions.push_back (region);
                        }
@@ -727,10 +743,11 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                        _session.region_name (new_name, current->name(), false);
                        region = RegionFactory::create (current, pos3 - pos1, pos4 - pos3, new_name, 
                                               regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit));
-
-                       add_region_internal (region, end);
-                       new_regions.push_back (region);
-
+                       {
+                               RegionLock rlock (this);
+                               add_region_internal (region, end);
+                               new_regions.push_back (region);
+                       }
                        /* "front" ***** */
                                
                        current->freeze ();
@@ -755,8 +772,9 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                                /* end +++++ */
                                
                                _session.region_name (new_name, current->name(), false);
-                               region = RegionFactory::create (current, pos2 - pos1, pos4 - pos2, new_name, (layer_t) regions.size(),
+                               region = RegionFactory::create (current, pos2 - pos1, pos4 - pos2, new_name, regions.size(),
                                                       Region::Flag(current->flags()|Region::Automatic|Region::LeftOfSplit));
+                               RegionLock rlock (this);
                                add_region_internal (region, start);
                                new_regions.push_back (region);
                        }
@@ -791,6 +809,7 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                                 _session.region_name (new_name, current->name(), false);
                                 region = RegionFactory::create (current, 0, pos3 - pos1, new_name,
                                                        regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit));
+                                RegionLock rlock (this);
                                 add_region_internal (region, pos1);
                                 new_regions.push_back (region);
                        } 
@@ -820,6 +839,7 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
                        */
 
                        if (cutting) {
+                               RegionLock rlock (this);
                                remove_region_internal (current);
                        }
                        new_regions.push_back (current);
@@ -831,6 +851,8 @@ Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, Regi
        for (RegionList::iterator i = new_regions.begin(); i != new_regions.end(); ++i) {
                check_dependents (*i, false);
        }
+
+       release_notifications ();
 }
 
 boost::shared_ptr<Playlist>
@@ -1209,7 +1231,9 @@ Playlist::clear (bool with_signals)
        }
 
        if (with_signals) {
+               pending_length = false;
                LengthChanged ();
+               pending_modified = false;
                Modified ();
        }
 
@@ -1587,7 +1611,7 @@ Playlist::relayer ()
        /* don't send multiple Modified notifications
           when multiple regions are relayered.
        */
-
        freeze ();
 
        /* build up a new list of regions on each layer */
@@ -1607,7 +1631,6 @@ Playlist::relayer ()
                copy.sort (cmp);
        }
        
-       
        for (RegionList::iterator i = copy.begin(); i != copy.end(); ++i) {
 
                /* find the lowest layer that this region can go on */
index d47a9b9423420541c47bfe9666ece3094896e5d8..96dc2c777908b33e9570414580e3cf4d8b164337 100644 (file)
@@ -63,11 +63,11 @@ int sndfile_header_formats[SNDFILE_HEADER_FORMATS] = {
 };
 
 const char * const sndfile_bitdepth_formats_strings[SNDFILE_BITDEPTH_FORMATS+1] = {
-       N_("16 bit"),
-       N_("24 bit"),
-       N_("32 bit"),
-       N_("8 bit"),
-       N_("float"),
+       N_("Signed 16 bit PCM"),
+       N_("Signed 24 bit PCM"),
+       N_("Signed 32 bit PCM"),
+       N_("Signed 8 bit PCM"),
+       N_("32 bit float"),
        0
 };