Abstraction cleanups/polish, towards merging with trunk
authorDavid Robillard <d@drobilla.net>
Sun, 30 Jul 2006 03:25:38 +0000 (03:25 +0000)
committerDavid Robillard <d@drobilla.net>
Sun, 30 Jul 2006 03:25:38 +0000 (03:25 +0000)
git-svn-id: svn://localhost/ardour2/branches/midi@720 d708f5d6-7413-0410-9779-e7cbd77b26cf

27 files changed:
gtk2_ardour/audio_regionview.cc
gtk2_ardour/audio_regionview.h
gtk2_ardour/audio_streamview.cc
gtk2_ardour/audio_streamview.h
gtk2_ardour/audio_time_axis.cc
gtk2_ardour/audio_time_axis.h
gtk2_ardour/editor.cc
gtk2_ardour/plugin_selector.h
gtk2_ardour/regionview.cc
gtk2_ardour/regionview.h
gtk2_ardour/route_time_axis.cc
gtk2_ardour/route_time_axis.h
gtk2_ardour/streamview.cc
gtk2_ardour/streamview.h
gtk2_ardour/taperegionview.cc
libs/ardour/ardour/audio_diskstream.h
libs/ardour/ardour/diskstream.h
libs/ardour/ardour/midi_diskstream.h
libs/ardour/ardour/playlist.h
libs/ardour/ardour/region.h
libs/ardour/ardour/session.h
libs/ardour/audio_diskstream.cc
libs/ardour/diskstream.cc
libs/ardour/midi_diskstream.cc
libs/ardour/session.cc
libs/ardour/session_butler.cc
libs/ardour/session_state.cc

index 125654c35c2ba879c6b6d50db15e5fb11e690d19..f22028f33e4eb768e3cda47171524756b22d39fa 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2001 Paul Davis 
+    Copyright (C) 2001-2006 Paul Davis 
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -19,6 +19,7 @@
 */
 
 #include <cmath>
+#include <cassert>
 #include <algorithm>
 
 #include <gtkmm.h>
@@ -68,20 +69,18 @@ AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView
 }
 
 void
-AudioRegionView::init (Gdk::Color& basic_color, bool wfw)
+AudioRegionView::init (Gdk::Color& basic_color, bool wfd)
 {
-    ArdourCanvas::Points shape;
+       // FIXME: Some redundancy here with RegionView::init.  Need to figure out
+       // where order is important and where it isn't...
+       
+       RegionView::init(basic_color, wfd);
+
        XMLNode *node;
 
-       editor = 0;
-       valid = true;
-       in_destructor = false;
        _amplitude_above_axis = 1.0;
-       zero_line = 0;
-       wait_for_waves = wfw;
-       _height = 0;
-
-       _flags = 0;
+       zero_line             = 0;
+       _flags                = 0;
 
        if ((node = _region.extra_xml ("GUI")) != 0) {
                set_flags (node);
@@ -98,23 +97,6 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfw)
 
        create_waves ();
 
-       name_highlight->set_data ("regionview", this);
-       name_text->set_data ("regionview", this);
-
-       //      shape = new ArdourCanvas::Points ();
-
-       /* an equilateral triangle */
-
-       shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1));
-       shape.push_back (Gnome::Art::Point ((sync_mark_width - 1)/2, 1));
-       shape.push_back (Gnome::Art::Point (0, sync_mark_width - 1));
-       shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1));
-
-       sync_mark =  new ArdourCanvas::Polygon (*group);
-       sync_mark->property_points() = shape;
-       sync_mark->property_fill_color_rgba() = fill_color;
-       sync_mark->hide();
-
        fade_in_shape = new ArdourCanvas::Polygon (*group);
        fade_in_shape->property_fill_color_rgba() = fade_color;
        fade_in_shape->set_data ("regionview", this);
@@ -175,8 +157,6 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfw)
 
        _region.StateChanged.connect (mem_fun(*this, &AudioRegionView::region_changed));
 
-       group->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_event), group, this));
-       name_highlight->signal_event().connect (bind (mem_fun (PublicEditor::instance(), &PublicEditor::canvas_region_view_name_highlight_event), name_highlight, this));
        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));
@@ -184,8 +164,6 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfw)
 
        set_colors ();
 
-       ColorChanged.connect (mem_fun (*this, &AudioRegionView::color_handler));
-
        /* XXX sync mark drag? */
 }
 
@@ -201,14 +179,6 @@ AudioRegionView::~AudioRegionView ()
 
        /* all waveviews etc will be destroyed when the group is destroyed */
 
-       for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
-               delete *g;
-       }
-
-       if (editor) {
-               delete editor;
-       }
-
        if (gain_line) {
                delete gain_line;
        }
@@ -217,58 +187,17 @@ AudioRegionView::~AudioRegionView ()
 ARDOUR::AudioRegion&
 AudioRegionView::audio_region() const
 {
-       // Guaranteed to succeed
+       // "Guaranteed" to succeed...
        return dynamic_cast<AudioRegion&>(_region);
 }
 
-
-gint
-AudioRegionView::_lock_toggle (ArdourCanvas::Item* item, GdkEvent* ev, void* arg)
-{
-       switch (ev->type) {
-       case GDK_BUTTON_RELEASE:
-               static_cast<AudioRegionView*>(arg)->lock_toggle ();
-               return TRUE;
-               break;
-       default:
-               break;
-       } 
-       return FALSE;
-}
-
-void
-AudioRegionView::lock_toggle ()
-{
-       _region.set_locked (!_region.locked());
-}
-
 void
 AudioRegionView::region_changed (Change what_changed)
 {
        ENSURE_GUI_THREAD (bind (mem_fun(*this, &AudioRegionView::region_changed), what_changed));
 
-       if (what_changed & BoundsChanged) {
-               region_resized (what_changed);
-               region_sync_changed ();
-       }
-       if (what_changed & Region::MuteChanged) {
-               region_muted ();
-       }
-       if (what_changed & Region::OpacityChanged) {
-               region_opacity ();
-       }
-       if (what_changed & ARDOUR::NameChanged) {
-               region_renamed ();
-       }
-       if (what_changed & Region::SyncOffsetChanged) {
-               region_sync_changed ();
-       }
-       if (what_changed & Region::LayerChanged) {
-               region_layered ();
-       }
-       if (what_changed & Region::LockChanged) {
-               region_locked ();
-       }
+       RegionView::region_changed(what_changed);
+
        if (what_changed & AudioRegion::ScaleAmplitudeChanged) {
                region_scale_amplitude_changed ();
        }
@@ -365,38 +294,19 @@ AudioRegionView::region_scale_amplitude_changed ()
        }
 }
 
-void
-AudioRegionView::region_locked ()
-{
-       /* name will show locked status */
-       region_renamed ();
-}
-
 void
 AudioRegionView::region_resized (Change what_changed)
 {
-       double unit_length;
-
-       if (what_changed & ARDOUR::PositionChanged) {
-               set_position (_region.position(), 0);
-       }
+       RegionView::region_resized(what_changed);
 
        if (what_changed & Change (StartChanged|LengthChanged)) {
 
-               set_duration (_region.length(), 0);
-
-               unit_length = _region.length() / samples_per_unit;
-               
-               reset_width_dependent_items (unit_length);
-               
                for (uint32_t n = 0; n < waves.size(); ++n) {
                        waves[n]->property_region_start() = _region.start();
-               }
+               }
                
                for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
 
-                       (*i)->set_duration (unit_length);
-
                        for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
                                (*w)->property_region_start() = _region.start();
                        }
@@ -407,8 +317,8 @@ AudioRegionView::region_resized (Change what_changed)
 void
 AudioRegionView::reset_width_dependent_items (double pixel_width)
 {
-       TimeAxisViewItem::reset_width_dependent_items (pixel_width);
-       _pixel_width = pixel_width;
+       RegionView::reset_width_dependent_items(pixel_width);
+       assert(_pixel_width == pixel_width);
 
        if (zero_line) {
                zero_line->property_x2() = pixel_width - 1.0;
@@ -432,18 +342,10 @@ AudioRegionView::reset_width_dependent_items (double pixel_width)
        reset_fade_shapes ();
 }
 
-void
-AudioRegionView::region_layered ()
-{
-       RouteTimeAxisView *atv = dynamic_cast<RouteTimeAxisView*> (&get_time_axis_view());
-       atv->view()->region_layered (this);
-}
-       
 void
 AudioRegionView::region_muted ()
 {
-       set_frame_color ();
-       region_renamed ();
+       RegionView::region_muted();
 
        for (uint32_t n=0; n < waves.size(); ++n) {
                if (_region.muted()) {
@@ -460,6 +362,7 @@ AudioRegionView::set_height (gdouble height)
 {
        uint32_t wcnt = waves.size();
 
+       // FIXME: ick
        TimeAxisViewItem::set_height (height - 2);
        
        _height = height;
@@ -695,36 +598,16 @@ AudioRegionView::reset_fade_out_shape_width (jack_nframes_t width)
 void
 AudioRegionView::set_samples_per_unit (gdouble spu)
 {
-       TimeAxisViewItem::set_samples_per_unit (spu);
+       RegionView::set_samples_per_unit (spu);
 
        for (uint32_t n=0; n < waves.size(); ++n) {
                waves[n]->property_samples_per_unit() = spu;
        }
 
-       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-               (*i)->set_samples_per_unit (spu);
-               (*i)->set_duration (_region.length() / samples_per_unit);
-       }
-
        if (gain_line) {
                gain_line->reset ();
        }
        reset_fade_shapes ();
-       region_sync_changed ();
-}
-
-bool
-AudioRegionView::set_duration (jack_nframes_t frames, void *src)
-{
-       if (!TimeAxisViewItem::set_duration (frames, src)) {
-               return false;
-       }
-       
-       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-               (*i)->set_duration (_region.length() / samples_per_unit);
-       }
-
-       return true;
 }
 
 void
@@ -738,7 +621,8 @@ AudioRegionView::set_amplitude_above_axis (gdouble spp)
 void
 AudioRegionView::compute_colors (Gdk::Color& basic_color)
 {
-       TimeAxisViewItem::compute_colors (basic_color);
+       RegionView::compute_colors(basic_color);
+       
        uint32_t r, g, b, a;
 
        /* gain color computed in envelope_active_changed() */
@@ -750,16 +634,12 @@ AudioRegionView::compute_colors (Gdk::Color& basic_color)
 void
 AudioRegionView::set_colors ()
 {
-       TimeAxisViewItem::set_colors ();
+       RegionView::set_colors();
        
        if (gain_line) {
                gain_line->set_line_color (audio_region().envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]);
        }
 
-       if (sync_mark) {
-               sync_mark->property_fill_color_rgba() = fill_color;
-       }
-
        for (uint32_t n=0; n < waves.size(); ++n) {
                if (_region.muted()) {
                        waves[n]->property_wave_color() = color_map[cMutedWaveForm];
@@ -769,18 +649,6 @@ AudioRegionView::set_colors ()
        }
 }
 
-void
-AudioRegionView::set_frame_color ()
-{
-       if (_region.opaque()) {
-               fill_opacity = 180;
-       } else {
-               fill_opacity = 100;
-       }
-
-       TimeAxisViewItem::set_frame_color ();
-}
-
 void
 AudioRegionView::show_region_editor ()
 {
@@ -795,89 +663,6 @@ AudioRegionView::show_region_editor ()
        editor->get_window()->raise();
 }
 
-void
-AudioRegionView::hide_region_editor()
-{
-       if (editor) {
-               editor->hide_all ();
-       }
-}
-
-void
-AudioRegionView::region_renamed ()
-{
-       string str;
-
-       if (_region.locked()) {
-               str += '>';
-               str += _region.name();
-               str += '<';
-       } else {
-               str = _region.name();
-       }
-
-       if (audio_region().speed_mismatch (trackview.session().frame_rate())) {
-               str = string ("*") + str;
-       }
-
-       if (_region.muted()) {
-               str = string ("!") + str;
-       }
-
-       set_item_name (str, this);
-       set_name_text (str);
-}
-
-void
-AudioRegionView::region_sync_changed ()
-{
-       if (sync_mark == 0) {
-               return;
-       }
-
-       int sync_dir;
-       jack_nframes_t sync_offset;
-
-       sync_offset = _region.sync_offset (sync_dir);
-
-       /* this has to handle both a genuine change of position, a change of samples_per_unit,
-          and a change in the bounds of the _region.
-        */
-
-       if (sync_offset == 0) {
-
-               /* no sync mark - its the start of the region */
-
-               sync_mark->hide();
-
-       } else {
-
-               if ((sync_dir < 0) || ((sync_dir > 0) && (sync_offset > _region.length()))) { 
-
-                       /* no sync mark - its out of the bounds of the region */
-
-                       sync_mark->hide();
-
-               } else {
-
-                       /* lets do it */
-
-                       Points points;
-                       
-                       //points = sync_mark->property_points().get_value();
-                       
-                       double offset = sync_offset / samples_per_unit;
-                       points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1));
-                       points.push_back (Gnome::Art::Point (offset + ((sync_mark_width-1)/2), 1));
-                       points.push_back (Gnome::Art::Point (offset, sync_mark_width - 1));
-                       points.push_back (Gnome::Art::Point (offset - ((sync_mark_width-1)/2), 1));     
-                       sync_mark->property_points().set_value (points);
-                       sync_mark->show();
-
-               }
-       }
-}
-
 void
 AudioRegionView::set_waveform_visible (bool yn)
 {
@@ -954,8 +739,8 @@ AudioRegionView::create_waves ()
                
                wave_caches.push_back (WaveView::create_cache ());
 
-               if (wait_for_waves) {
-                       if (audio_region().source(n).peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), peaks_ready_connection)) {
+               if (wait_for_data) {
+                       if (audio_region().source(n).peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), data_ready_connection)) {
                                create_one_wave (n, true);
                        } else {
                                create_zero_line = false;
@@ -1056,7 +841,7 @@ AudioRegionView::peaks_ready_handler (uint32_t which)
 
        if (!waves.empty()) {
                /* all waves created, don't hook into peaks ready anymore */
-               peaks_ready_connection.disconnect ();           
+               data_ready_connection.disconnect ();            
        }
 }
 
@@ -1184,22 +969,6 @@ AudioRegionView::set_waveform_shape (WaveformShape shape)
        }
 }
 
-void
-AudioRegionView::move (double x_delta, double y_delta)
-{
-       if (_region.locked() || (x_delta == 0 && y_delta == 0)) {
-               return;
-       }
-
-       get_canvas_group()->move (x_delta, y_delta);
-
-       /* note: ghosts never leave their tracks so y_delta for them is always zero */
-
-       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-               (*i)->group->move (x_delta, 0.0);
-       }
-}
-
 GhostRegion*
 AudioRegionView::add_ghost (AutomationTimeAxisView& atv)
 {
@@ -1243,21 +1012,6 @@ AudioRegionView::add_ghost (AutomationTimeAxisView& atv)
        return ghost;
 }
 
-void
-AudioRegionView::remove_ghost (GhostRegion* ghost)
-{
-       if (in_destructor) {
-               return;
-       }
-
-       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-               if (*i == ghost) {
-                       ghosts.erase (i);
-                       break;
-               }
-       }
-}
-
 void
 AudioRegionView::entered ()
 {
index 7889f0c8b52f3bb7e1ab16e727ce71ab732071cd..b59f5f4791caff16758f6cf87e081a701814b560 100644 (file)
@@ -57,21 +57,15 @@ class AudioRegionView : public RegionView
 
        ~AudioRegionView ();
        
-       virtual void init (Gdk::Color& base_color, bool wait_for_waves);
+       virtual void init (Gdk::Color& base_color, bool wait_for_data = false);
        
        ARDOUR::AudioRegion& audio_region() const;
     
-    bool is_valid() const { return valid; }
-    void set_valid (bool yn) { valid = yn; }
-
     void set_height (double);
     void set_samples_per_unit (double);
-    bool set_duration (jack_nframes_t, void*);
 
     void set_amplitude_above_axis (gdouble spp);
 
-    void move (double xdelta, double ydelta);
-
     void temporarily_hide_envelope (); ///< Dangerous!
     void unhide_envelope ();           ///< Dangerous!
 
@@ -80,11 +74,10 @@ class AudioRegionView : public RegionView
     void set_waveform_shape (WaveformShape);
 
     bool waveform_rectified() const { return _flags & WaveformRectified; }
-    bool waveform_visible() const { return _flags & WaveformVisible; }
-    bool envelope_visible() const { return _flags & EnvelopeVisible; }
+    bool waveform_visible()   const { return _flags & WaveformVisible; }
+    bool envelope_visible()   const { return _flags & EnvelopeVisible; }
     
     void show_region_editor ();
-    void hide_region_editor();
 
     void add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event);
     void remove_gain_point_event (ArdourCanvas::Item *item, GdkEvent *event);
@@ -95,7 +88,6 @@ class AudioRegionView : public RegionView
     void envelope_active_changed ();
 
     GhostRegion* add_ghost (AutomationTimeAxisView&);
-    void remove_ghost (GhostRegion*);
 
     void reset_fade_in_shape_width (jack_nframes_t);
     void reset_fade_out_shape_width (jack_nframes_t);
@@ -113,11 +105,11 @@ class AudioRegionView : public RegionView
     */
     
     AudioRegionView (ArdourCanvas::Group *, 
-                    RouteTimeAxisView&,
-                    ARDOUR::AudioRegion&,
-                    double initial_samples_per_unit,
-                    Gdk::Color& basic_color,
-                    TimeAxisViewItem::Visibility);
+                            RouteTimeAxisView&,
+                            ARDOUR::AudioRegion&,
+                            double      samples_per_unit,
+                            Gdk::Color& basic_color,
+                            TimeAxisViewItem::Visibility);
     
     enum Flags {
            EnvelopeVisible = 0x1,
@@ -125,32 +117,22 @@ class AudioRegionView : public RegionView
            WaveformRectified = 0x8
     };
 
-    vector<ArdourCanvas::WaveView *> waves; ///< waveviews 
+    vector<ArdourCanvas::WaveView *> waves;
     vector<ArdourCanvas::WaveView *> tmp_waves; ///< see ::create_waves()
-    ArdourCanvas::Polygon* sync_mark; ///< polgyon for sync position 
-    ArdourCanvas::Text* no_wave_msg; ///< text 
-    ArdourCanvas::SimpleLine* zero_line; ///< simpleline 
-    ArdourCanvas::Polygon* fade_in_shape; ///< polygon 
-    ArdourCanvas::Polygon* fade_out_shape; ///< polygon 
-    ArdourCanvas::SimpleRect* fade_in_handle; ///< simplerect 
-    ArdourCanvas::SimpleRect* fade_out_handle; ///< simplerect 
+    ArdourCanvas::Polygon*           sync_mark; ///< polgyon for sync position 
+    ArdourCanvas::SimpleLine*        zero_line;
+    ArdourCanvas::Polygon*           fade_in_shape;
+    ArdourCanvas::Polygon*           fade_out_shape;
+    ArdourCanvas::SimpleRect*        fade_in_handle;
+    ArdourCanvas::SimpleRect*        fade_out_handle;
     
     AudioRegionGainLine * gain_line;
-    AudioRegionEditor   * editor;
 
-    vector<ControlPoint *> control_points;
     double _amplitude_above_axis;
-    double current_visible_sync_position;
 
     uint32_t _flags;
     uint32_t fade_color;
-    bool     valid; /* see StreamView::redisplay_diskstream() */
-    double _pixel_width;
-    double _height;
-    bool    in_destructor;
-    bool    wait_for_waves;
-    sigc::connection peaks_ready_connection;
-
+    
     void reset_fade_shapes ();
     void reset_fade_in_shape ();
     void reset_fade_out_shape ();
@@ -162,31 +144,21 @@ class AudioRegionView : public RegionView
     void region_resized (ARDOUR::Change);
     void region_moved (void *);
     void region_muted ();
-    void region_locked ();
-    void region_layered ();
-    void region_renamed ();
-    void region_sync_changed ();
     void region_scale_amplitude_changed ();
 
-    static gint _lock_toggle (ArdourCanvas::Item*, GdkEvent*, void*);
-    void lock_toggle ();
-
     void create_waves ();
     void create_one_wave (uint32_t, bool);
     void manage_zero_line ();
     void peaks_ready_handler (uint32_t);
-    void reset_name (gdouble width);
     void set_flags (XMLNode *);
     void store_flags ();
 
     void set_colors ();
     void compute_colors (Gdk::Color&);
-    virtual void set_frame_color ();
     void reset_width_dependent_items (double pixel_width);
     void set_waveview_data_src();
 
     vector<GnomeCanvasWaveViewCache*> wave_caches;
-    vector<GhostRegion*> ghosts;
     
     void color_handler (ColorID, uint32_t);
 };
index 1e43f1dac13f770bcfa92e1598960810c8d645f1..0d0cd7889ca65fb668c7e22f1343cc1b17ea343e 100644 (file)
@@ -54,7 +54,6 @@ using namespace Editing;
 AudioStreamView::AudioStreamView (AudioTimeAxisView& tv)
        : StreamView (tv)
 {
-       region_color = _trackview.color();
        crossfades_visible = true;
 
        if (tv.is_audio_track())
@@ -62,43 +61,16 @@ AudioStreamView::AudioStreamView (AudioTimeAxisView& tv)
        else
                stream_base_color = color_map[cAudioBusBase];
 
-       /* set_position() will position the group */
-
-       canvas_group = new ArdourCanvas::Group(*_trackview.canvas_display);
-
-       canvas_rect = new ArdourCanvas::SimpleRect (*canvas_group);
-       canvas_rect->property_x1() = 0.0;
-       canvas_rect->property_y1() = 0.0;
-       canvas_rect->property_x2() = 1000000.0;
-       canvas_rect->property_y2() = (double) tv.height;
        canvas_rect->property_outline_color_rgba() = color_map[cAudioTrackOutline];
-       canvas_rect->property_outline_what() = (guint32) (0x1|0x2|0x8);  // outline ends and bottom 
-       canvas_rect->property_fill_color_rgba() = stream_base_color;
-
-       canvas_rect->signal_event().connect (bind (mem_fun (_trackview.editor, &PublicEditor::canvas_stream_view_event), canvas_rect, &_trackview));
 
-       _samples_per_unit = _trackview.editor.get_current_zoom();
        _amplitude_above_axis = 1.0;
 
-       if (_trackview.is_audio_track()) {
-               _trackview.audio_track()->DiskstreamChanged.connect (mem_fun (*this, &AudioStreamView::diskstream_changed));
-               _trackview.session().TransportStateChange.connect (mem_fun (*this, &AudioStreamView::transport_changed));
-               _trackview.get_diskstream()->RecordEnableChanged.connect (mem_fun (*this, &AudioStreamView::rec_enable_changed));
-               _trackview.session().RecordStateChanged.connect (mem_fun (*this, &AudioStreamView::sess_rec_enable_changed));
-       } 
-
-       rec_updating = false;
-       rec_active = false;
        use_rec_regions = tv.editor.show_waveforms_recording ();
        last_rec_peak_frame = 0;
-
-       ColorChanged.connect (mem_fun (*this, &AudioStreamView::color_handler));
 }
 
 AudioStreamView::~AudioStreamView ()
 {
-       undisplay_diskstream ();
-       delete canvas_group;
 }
 
 int
@@ -132,7 +104,6 @@ AudioStreamView::set_samples_per_unit (gdouble spp)
 
 int 
 AudioStreamView::set_amplitude_above_axis (gdouble app)
-
 {
        RegionViewList::iterator i;
 
@@ -206,8 +177,6 @@ AudioStreamView::remove_region_view (Region *r)
 {
        ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::remove_region_view), r));
 
-       StreamView::remove_region_view(r);
-       
        for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end();) {
                list<CrossfadeView*>::iterator tmp;
                
@@ -222,6 +191,8 @@ AudioStreamView::remove_region_view (Region *r)
                
                i = tmp;
        }
+
+       StreamView::remove_region_view(r);
 }
 
 void
index d05ecd930796ffc82eb7442854b33adcd2c3efaf..05ce8125f618d514b155851076b5d808f80b769c 100644 (file)
@@ -59,10 +59,9 @@ class AudioStreamView : public StreamView
        void set_waveform_shape (WaveformShape);
 
        int set_height (gdouble h);
-
        int set_samples_per_unit (gdouble spp);
 
-       int set_amplitude_above_axis (gdouble app);
+       int     set_amplitude_above_axis (gdouble app);
        gdouble get_amplitude_above_axis () { return _amplitude_above_axis; }
 
        void set_show_waveforms (bool yn);
@@ -90,17 +89,17 @@ class AudioStreamView : public StreamView
        void playlist_modified ();
        void playlist_changed (ARDOUR::Diskstream *ds);
 
-       bool crossfades_visible;
        void add_crossfade (ARDOUR::Crossfade*);
        void remove_crossfade (ARDOUR::Crossfade*);
 
        void color_handler (ColorID id, uint32_t val);
        
 
+       double _amplitude_above_axis;
+       
        typedef list<CrossfadeView*> CrossfadeViewList;
        CrossfadeViewList crossfade_views;
-
-       double _amplitude_above_axis;
+       bool              crossfades_visible;
 
        list<sigc::connection>     peak_ready_connections;
        jack_nframes_t             last_rec_peak_frame;
index ea822b97c5c6add99c3091ca6b6711151fb3f5a7..13383fa6a4660e5141f46d901d5a7bd05adacfd2 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2000-2006 Paul Davis 
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -41,7 +41,6 @@
 #include <ardour/audioplaylist.h>
 #include <ardour/audio_diskstream.h>
 #include <ardour/insert.h>
-#include <ardour/ladspa_plugin.h>
 #include <ardour/location.h>
 #include <ardour/panner.h>
 #include <ardour/playlist.h>
 #include "audio_time_axis.h"
 #include "automation_gain_line.h"
 #include "automation_pan_line.h"
-#include "automation_time_axis.h"
 #include "canvas_impl.h"
 #include "crossfade_view.h"
 #include "enums.h"
 #include "gain_automation_time_axis.h"
-#include "gui_thread.h"
 #include "keyboard.h"
 #include "pan_automation_time_axis.h"
 #include "playlist_selector.h"
 #include "plugin_selector.h"
 #include "plugin_ui.h"
-#include "point_selection.h"
 #include "prompter.h"
 #include "public_editor.h"
-#include "redirect_automation_line.h"
-#include "redirect_automation_time_axis.h"
 #include "audio_regionview.h"
-#include "rgb_macros.h"
-#include "selection.h"
 #include "simplerect.h"
 #include "audio_streamview.h"
 #include "utils.h"
@@ -87,9 +79,12 @@ using namespace Editing;
 
 
 AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, boost::shared_ptr<Route> rt, Canvas& canvas)
-       : AxisView(sess), // FIXME: won't compile without this, why??
-       RouteTimeAxisView(ed, sess, rt, canvas)
+       : AxisView(sess)
+       RouteTimeAxisView(ed, sess, rt, canvas)
 {
+       // Make sure things are sane...
+       assert(!is_track() || is_audio_track());
+
        subplugin_menu.set_name ("ArdourContextMenu");
        gain_track = 0;
        pan_track = 0;
@@ -143,11 +138,6 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
 
 AudioTimeAxisView::~AudioTimeAxisView ()
 {
-       vector_delete (&redirect_automation_curves);
-
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               delete *i;
-       }
 }
 
 AudioStreamView*
@@ -227,56 +217,14 @@ AudioTimeAxisView::set_state (const XMLNode& node)
 }
 
 void
-AudioTimeAxisView::reset_redirect_automation_curves ()
-{
-       for (vector<RedirectAutomationLine*>::iterator i = redirect_automation_curves.begin(); i != redirect_automation_curves.end(); ++i) {
-               (*i)->reset();
-       }
-}
-
-void
-AudioTimeAxisView::build_display_menu ()
+AudioTimeAxisView::build_automation_action_menu ()
 {
        using namespace Menu_Helpers;
 
-       /* get the size menu ready */
-
-       build_size_menu ();
-
-       /* prepare it */
-
-       TimeAxisView::build_display_menu ();
-
-       /* now fill it with our stuff */
-
-       MenuList& items = display_menu->items();
-       display_menu->set_name ("ArdourContextMenu");
-       
-       items.push_back (MenuElem (_("Height"), *size_menu));
-       items.push_back (MenuElem (_("Color"), mem_fun(*this, &AudioTimeAxisView::select_track_color)));
-
-
-       items.push_back (SeparatorElem());
-       items.push_back (MenuElem (_("Hide all crossfades"), mem_fun(*this, &AudioTimeAxisView::hide_all_xfades)));
-       items.push_back (MenuElem (_("Show all crossfades"), mem_fun(*this, &AudioTimeAxisView::show_all_xfades)));
-       items.push_back (SeparatorElem());
-
-       build_remote_control_menu ();
-       items.push_back (MenuElem (_("Remote Control ID"), *remote_control_menu));
+       RouteTimeAxisView::build_automation_action_menu ();
 
-       automation_action_menu = manage (new Menu);
        MenuList& automation_items = automation_action_menu->items();
-       automation_action_menu->set_name ("ArdourContextMenu");
        
-       automation_items.push_back (MenuElem (_("Show all automation"),
-                                             mem_fun(*this, &AudioTimeAxisView::show_all_automation)));
-
-       automation_items.push_back (MenuElem (_("Show existing automation"),
-                                             mem_fun(*this, &AudioTimeAxisView::show_existing_automation)));
-
-       automation_items.push_back (MenuElem (_("Hide all automation"),
-                                             mem_fun(*this, &AudioTimeAxisView::hide_all_automation)));
-
        automation_items.push_back (SeparatorElem());
 
        automation_items.push_back (CheckMenuElem (_("Fader"), 
@@ -288,11 +236,21 @@ AudioTimeAxisView::build_display_menu ()
                                                   mem_fun(*this, &AudioTimeAxisView::toggle_pan_track)));
        pan_automation_item = static_cast<CheckMenuItem*> (&automation_items.back());
        pan_automation_item->set_active(show_pan_automation);
+       
+}
 
-       automation_items.push_back (MenuElem (_("Plugins"), subplugin_menu));
+void
+AudioTimeAxisView::append_extra_display_menu_items ()
+{
+       using namespace Menu_Helpers;
 
-       items.push_back (MenuElem (_("Automation"), *automation_action_menu));
+       MenuList& items = display_menu->items();
 
+       // crossfade stuff
+       items.push_back (MenuElem (_("Hide all crossfades"), mem_fun(*this, &AudioTimeAxisView::hide_all_xfades)));
+       items.push_back (MenuElem (_("Show all crossfades"), mem_fun(*this, &AudioTimeAxisView::show_all_xfades)));
+
+       // waveform menu
        Menu *waveform_menu = manage(new Menu);
        MenuList& waveform_items = waveform_menu->items();
        waveform_menu->set_name ("ArdourContextMenu");
@@ -312,39 +270,6 @@ AudioTimeAxisView::build_display_menu ()
        rectified_item = static_cast<RadioMenuItem *> (&waveform_items.back());
 
        items.push_back (MenuElem (_("Waveform"), *waveform_menu));
-
-       if (is_audio_track()) {
-
-               Menu* alignment_menu = manage (new Menu);
-               MenuList& alignment_items = alignment_menu->items();
-               alignment_menu->set_name ("ArdourContextMenu");
-
-               RadioMenuItem::Group align_group;
-               
-               alignment_items.push_back (RadioMenuElem (align_group, _("Align with existing material"), bind (mem_fun(*this, &AudioTimeAxisView::set_align_style), ExistingMaterial)));
-               align_existing_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back());
-               if (get_diskstream()->alignment_style() == ExistingMaterial) {
-                       align_existing_item->set_active();
-               }
-               alignment_items.push_back (RadioMenuElem (align_group, _("Align with capture time"), bind (mem_fun(*this, &AudioTimeAxisView::set_align_style), CaptureTime)));
-               align_capture_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back());
-               if (get_diskstream()->alignment_style() == CaptureTime) {
-                       align_capture_item->set_active();
-               }
-               
-               items.push_back (MenuElem (_("Alignment"), *alignment_menu));
-
-               get_diskstream()->AlignmentStyleChanged.connect (mem_fun(*this, &AudioTimeAxisView::align_style_changed));
-       }
-
-       items.push_back (SeparatorElem());
-       items.push_back (CheckMenuElem (_("Active"), mem_fun(*this, &RouteUI::toggle_route_active)));
-       route_active_menu_item = dynamic_cast<CheckMenuItem *> (&items.back());
-       route_active_menu_item->set_active (_route->active());
-
-       items.push_back (SeparatorElem());
-       items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route)));
-
 }
 
 void
@@ -393,16 +318,6 @@ AudioTimeAxisView::set_waveform_shape (WaveformShape shape)
        map_frozen ();
 }      
 
-void
-AudioTimeAxisView::set_selected_regionviews (RegionSelection& regions)
-{
-       AudioStreamView* asv = audio_view();
-
-       if (asv) {
-               asv->set_selected_regionviews (regions);
-       }
-}
-
 void
 AudioTimeAxisView::add_gain_automation_child ()
 {
@@ -587,322 +502,6 @@ AudioTimeAxisView::pan_hidden ()
         _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
 }
 
-AudioTimeAxisView::RedirectAutomationInfo::~RedirectAutomationInfo ()
-{
-       for (vector<RedirectAutomationNode*>::iterator i = lines.begin(); i != lines.end(); ++i) {
-               delete *i;
-       }
-}
-
-
-AudioTimeAxisView::RedirectAutomationNode::~RedirectAutomationNode ()
-{
-       parent.remove_ran (this);
-
-       if (view) {
-               delete view;
-       }
-}
-
-void
-AudioTimeAxisView::remove_ran (RedirectAutomationNode* ran)
-{
-       if (ran->view) {
-               remove_child (ran->view);
-       }
-}
-
-AudioTimeAxisView::RedirectAutomationNode*
-AudioTimeAxisView::find_redirect_automation_node (boost::shared_ptr<Redirect> redirect, uint32_t what)
-{
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-
-               if ((*i)->redirect == redirect) {
-
-                       for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
-                               if ((*ii)->what == what) {
-                                       return *ii;
-                               }
-                       }
-               }
-       }
-
-       return 0;
-}
-
-// FIXME: duplicated in midi_time_axis.cc
-static string 
-legalize_for_xml_node (string str)
-{
-       string::size_type pos;
-       string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=:";
-       string legal;
-
-       legal = str;
-       pos = 0;
-
-       while ((pos = legal.find_first_not_of (legal_chars, pos)) != string::npos) {
-               legal.replace (pos, 1, "_");
-               pos += 1;
-       }
-
-       return legal;
-}
-
-
-void
-AudioTimeAxisView::add_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what)
-{
-       RedirectAutomationLine* ral;
-       string name;
-       RedirectAutomationNode* ran;
-
-       if ((ran = find_redirect_automation_node (redirect, what)) == 0) {
-               fatal << _("programming error: ")
-                     << string_compose (X_("redirect automation curve for %1:%2 not registered with audio track!"),
-                                 redirect->name(), what)
-                     << endmsg;
-               /*NOTREACHED*/
-               return;
-       }
-
-       if (ran->view) {
-               return;
-       }
-
-       name = redirect->describe_parameter (what);
-
-       /* create a string that is a legal XML node name that can be used to refer to this redirect+port combination */
-
-       char state_name[256];
-       snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (redirect->name()).c_str(), what);
-
-       ran->view = new RedirectAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *redirect, state_name);
-
-       ral = new RedirectAutomationLine (name, 
-                                         *redirect, what, _session, *ran->view,
-                                         *ran->view->canvas_display, redirect->automation_list (what));
-       
-       ral->set_line_color (color_map[cRedirectAutomationLine]);
-       ral->queue_reset ();
-
-       ran->view->add_line (*ral);
-
-       ran->view->Hiding.connect (bind (mem_fun(*this, &AudioTimeAxisView::redirect_automation_track_hidden), ran, redirect));
-
-       if (!ran->view->marked_for_display()) {
-               ran->view->hide ();
-       } else {
-               ran->menu_item->set_active (true);
-       }
-
-       add_child (ran->view);
-
-       audio_view()->foreach_regionview (bind (mem_fun(*this, &AudioTimeAxisView::add_ghost_to_redirect), ran->view));
-
-       redirect->mark_automation_visible (what, true);
-}
-
-void
-AudioTimeAxisView::redirect_automation_track_hidden (AudioTimeAxisView::RedirectAutomationNode* ran, boost::shared_ptr<Redirect> r)
-{
-       if (!_hidden) {
-               ran->menu_item->set_active (false);
-       }
-
-       r->mark_automation_visible (ran->what, false);
-
-        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
-}
-
-void
-AudioTimeAxisView::add_existing_redirect_automation_curves (boost::shared_ptr<Redirect> redirect)
-{
-       set<uint32_t> s;
-       RedirectAutomationLine *ral;
-
-       redirect->what_has_visible_automation (s);
-
-       for (set<uint32_t>::iterator i = s.begin(); i != s.end(); ++i) {
-               
-               if ((ral = find_redirect_automation_curve (redirect, *i)) != 0) {
-                       ral->queue_reset ();
-               } else {
-                       add_redirect_automation_curve (redirect, (*i));
-               }
-       }
-}
-
-void
-AudioTimeAxisView::add_redirect_to_subplugin_menu (boost::shared_ptr<Redirect> r)
-{
-       using namespace Menu_Helpers;
-       RedirectAutomationInfo *rai;
-       list<RedirectAutomationInfo*>::iterator x;
-       
-       const std::set<uint32_t>& automatable = r->what_can_be_automated ();
-       std::set<uint32_t> has_visible_automation;
-
-       r->what_has_visible_automation(has_visible_automation);
-
-       if (automatable.empty()) {
-               return;
-       }
-
-       for (x = redirect_automation.begin(); x != redirect_automation.end(); ++x) {
-               if ((*x)->redirect == r) {
-                       break;
-               }
-       }
-
-       if (x == redirect_automation.end()) {
-
-               rai = new RedirectAutomationInfo (r);
-               redirect_automation.push_back (rai);
-
-       } else {
-
-               rai = *x;
-
-       }
-
-       /* any older menu was deleted at the top of redirects_changed()
-          when we cleared the subplugin menu.
-       */
-
-       rai->menu = manage (new Menu);
-       MenuList& items = rai->menu->items();
-       rai->menu->set_name ("ArdourContextMenu");
-
-       items.clear ();
-
-       for (std::set<uint32_t>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) {
-
-               RedirectAutomationNode* ran;
-               CheckMenuItem* mitem;
-               
-               string name = r->describe_parameter (*i);
-               
-               items.push_back (CheckMenuElem (name));
-               mitem = dynamic_cast<CheckMenuItem*> (&items.back());
-
-               if (has_visible_automation.find((*i)) != has_visible_automation.end()) {
-                       mitem->set_active(true);
-               }
-
-               if ((ran = find_redirect_automation_node (r, *i)) == 0) {
-
-                       /* new item */
-                       
-                       ran = new RedirectAutomationNode (*i, mitem, *this);
-                       
-                       rai->lines.push_back (ran);
-
-               } else {
-
-                       ran->menu_item = mitem;
-
-               }
-
-               mitem->signal_toggled().connect (bind (mem_fun(*this, &AudioTimeAxisView::redirect_menu_item_toggled), rai, ran));
-       }
-
-       /* add the menu for this redirect, because the subplugin
-          menu is always cleared at the top of redirects_changed().
-          this is the result of some poor design in gtkmm and/or
-          GTK+.
-       */
-
-       subplugin_menu.items().push_back (MenuElem (r->name(), *rai->menu));
-       rai->valid = true;
-}
-
-void
-AudioTimeAxisView::redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutomationInfo* rai,
-                                              AudioTimeAxisView::RedirectAutomationNode* ran)
-{
-       bool showit = ran->menu_item->get_active();
-       bool redraw = false;
-
-       if (ran->view == 0 && showit) {
-               add_redirect_automation_curve (rai->redirect, ran->what);
-               redraw = true;
-       }
-
-       if (showit != ran->view->marked_for_display()) {
-
-               if (showit) {
-                       ran->view->set_marked_for_display (true);
-                       ran->view->canvas_display->show();
-               } else {
-                       rai->redirect->mark_automation_visible (ran->what, true);
-                       ran->view->set_marked_for_display (false);
-                       ran->view->hide ();
-               }
-
-               redraw = true;
-
-       }
-
-       if (redraw && !no_redraw) {
-
-               /* now trigger a redisplay */
-               
-                _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
-
-       }
-}
-
-void
-AudioTimeAxisView::redirects_changed (void *src)
-{
-       using namespace Menu_Helpers;
-
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               (*i)->valid = false;
-       }
-
-       subplugin_menu.items().clear ();
-
-       _route->foreach_redirect (this, &AudioTimeAxisView::add_redirect_to_subplugin_menu);
-       _route->foreach_redirect (this, &AudioTimeAxisView::add_existing_redirect_automation_curves);
-
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ) {
-
-               list<RedirectAutomationInfo*>::iterator tmp;
-
-               tmp = i;
-               ++tmp;
-
-               if (!(*i)->valid) {
-
-                       delete *i;
-                       redirect_automation.erase (i);
-
-               } 
-
-               i = tmp;
-       }
-
-       /* change in visibility was possible */
-
-       _route->gui_changed ("track_height", this);
-}
-
-RedirectAutomationLine *
-AudioTimeAxisView::find_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what)
-{
-       RedirectAutomationNode* ran;
-
-       if ((ran = find_redirect_automation_node (redirect, what)) != 0) {
-               if (ran->view) {
-                       return dynamic_cast<RedirectAutomationLine*> (ran->view->lines.front());
-               } 
-       }
-
-       return 0;
-}
-
 void
 AudioTimeAxisView::show_all_automation ()
 {
@@ -911,15 +510,7 @@ AudioTimeAxisView::show_all_automation ()
        pan_automation_item->set_active (true);
        gain_automation_item->set_active (true);
        
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
-                       if ((*ii)->view == 0) {
-                               add_redirect_automation_curve ((*i)->redirect, (*ii)->what);
-                       } 
-
-                       (*ii)->menu_item->set_active (true);
-               }
-       }
+       RouteTimeAxisView::show_all_automation ();
 
        no_redraw = false;
 
@@ -934,13 +525,7 @@ AudioTimeAxisView::show_existing_automation ()
        pan_automation_item->set_active (true);
        gain_automation_item->set_active (true);
 
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
-                       if ((*ii)->view != 0) {
-                               (*ii)->menu_item->set_active (true);
-                       }
-               }
-       }
+       RouteTimeAxisView::show_existing_automation ();
 
        no_redraw = false;
 
@@ -955,36 +540,12 @@ AudioTimeAxisView::hide_all_automation ()
        pan_automation_item->set_active (false);
        gain_automation_item->set_active (false);
 
-       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
-               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
-                       (*ii)->menu_item->set_active (false);
-               }
-       }
+       RouteTimeAxisView::hide_all_automation();
 
        no_redraw = false;
         _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
 }
 
-void
-AudioTimeAxisView::region_view_added (RegionView* rv)
-{
-       assert(dynamic_cast<AudioRegionView*>(rv));
-
-       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
-               AutomationTimeAxisView* atv;
-
-               if ((atv = dynamic_cast<AutomationTimeAxisView*> (*i)) != 0) {
-                       rv->add_ghost (*atv);
-               }
-       }
-}
-
-void
-AudioTimeAxisView::add_ghost_to_redirect (RegionView* rv, AutomationTimeAxisView* atv)
-{
-       rv->add_ghost (*atv);
-}
-
 void
 AudioTimeAxisView::show_all_xfades ()
 {
@@ -1030,7 +591,7 @@ AudioTimeAxisView::reveal_dependent_views (TimeAxisViewItem& tavi)
 void
 AudioTimeAxisView::route_active_changed ()
 {
-       RouteUI::route_active_changed ();
+       RouteTimeAxisView::route_active_changed ();
 
        if (is_audio_track()) {
                if (_route->active()) {
index 2a6aa1c4d68f9edffe47e386c14bb607d6276d84..2162771285c32f915c2a45baedcaa2cfdd9884a1 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2000-2006 Paul Davis 
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -33,7 +33,6 @@
 #include <list>
 
 #include <ardour/types.h>
-#include <ardour/region.h>
 
 #include "ardour_dialog.h"
 #include "route_ui.h"
@@ -62,7 +61,6 @@ class AudioRegionView;
 class AutomationLine;
 class AutomationGainLine;
 class AutomationPanLine;
-class RedirectAutomationLine;
 class TimeSelection;
 class AutomationTimeAxisView;
 
@@ -78,11 +76,10 @@ class AudioTimeAxisView : public RouteTimeAxisView
        void set_show_waveforms_recording (bool yn);
        void show_all_xfades ();
        void hide_all_xfades ();
-       void set_selected_regionviews (RegionSelection&);
        void hide_dependent_views (TimeAxisViewItem&);
        void reveal_dependent_views (TimeAxisViewItem&);
                
-       /* overridden from parent to store display state */
+       /* Overridden from parent to store display state */
        guint32 show_at (double y, int& nth, Gtk::VBox *parent);
        void hide ();
        
@@ -95,83 +92,16 @@ class AudioTimeAxisView : public RouteTimeAxisView
        
        void route_active_changed ();
 
-       AutomationTimeAxisView *gain_track;
-       AutomationTimeAxisView *pan_track;
-
-       void update_automation_view (ARDOUR::AutomationType);
-       void reset_redirect_automation_curves ();
-
-       // variables to get the context menu
-       // automation buttons correctly initialized
-       bool show_gain_automation;
-       bool show_pan_automation;
-
-       // FIXME?
-       void redirects_changed (void *);
-
-       void build_display_menu ();
-
-       Gtk::CheckMenuItem* waveform_item;
-       Gtk::RadioMenuItem* traditional_item;
-       Gtk::RadioMenuItem* rectified_item;
+       void build_automation_action_menu ();
+       void append_extra_display_menu_items ();
        
        void toggle_show_waveforms ();
-
        void set_waveform_shape (WaveformShape);
        void toggle_waveforms ();
 
-       /* automation stuff */
-       
-       Gtk::Menu*          automation_action_menu;
-       Gtk::CheckMenuItem* gain_automation_item;
-       Gtk::CheckMenuItem* pan_automation_item;
-
-       void automation_click ();
-       void clear_automation ();
-       void hide_all_automation ();
        void show_all_automation ();
        void show_existing_automation ();
-
-       struct RedirectAutomationNode {
-           uint32_t what;
-           Gtk::CheckMenuItem* menu_item;
-           AutomationTimeAxisView* view;
-           AudioTimeAxisView& parent;
-
-           RedirectAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, AudioTimeAxisView& p)
-                   : what (w), menu_item (mitem), view (0), parent (p) {}
-
-           ~RedirectAutomationNode ();
-       };
-
-       struct RedirectAutomationInfo {
-           boost::shared_ptr<ARDOUR::Redirect> redirect;
-           bool valid;
-           Gtk::Menu* menu;
-           vector<RedirectAutomationNode*> lines;
-
-           RedirectAutomationInfo (boost::shared_ptr<ARDOUR::Redirect> r) 
-                   : redirect (r), valid (true) {}
-
-           ~RedirectAutomationInfo ();
-       };
-
-       list<RedirectAutomationInfo*> redirect_automation;
-       RedirectAutomationNode* find_redirect_automation_node (boost::shared_ptr<ARDOUR::Redirect> redirect, uint32_t what);
-       
-       Gtk::Menu subplugin_menu;
-       void add_redirect_to_subplugin_menu (boost::shared_ptr<ARDOUR::Redirect>);
-
-       void remove_ran (RedirectAutomationNode* ran);
-
-       void redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutomationInfo*,
-                                        AudioTimeAxisView::RedirectAutomationNode*);
-       void redirect_automation_track_hidden (RedirectAutomationNode*, boost::shared_ptr<ARDOUR::Redirect>);
-       
-       vector<RedirectAutomationLine*> redirect_automation_curves;
-       RedirectAutomationLine *find_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect>,uint32_t);
-       void add_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect>, uint32_t);
-       void add_existing_redirect_automation_curves (boost::shared_ptr<ARDOUR::Redirect>);
+       void hide_all_automation ();
 
        void add_gain_automation_child ();
        void add_pan_automation_child ();
@@ -185,8 +115,18 @@ class AudioTimeAxisView : public RouteTimeAxisView
 
        void update_pans ();
 
-       void region_view_added (RegionView*);
-       void add_ghost_to_redirect (RegionView*, AutomationTimeAxisView*);
+       AutomationTimeAxisView* gain_track;
+       AutomationTimeAxisView* pan_track;
+
+       // Set from XML so context menu automation buttons can be correctly initialized
+       bool show_gain_automation;
+       bool show_pan_automation;
+       
+       Gtk::CheckMenuItem* waveform_item;
+       Gtk::RadioMenuItem* traditional_item;
+       Gtk::RadioMenuItem* rectified_item;
+       Gtk::CheckMenuItem* gain_automation_item;
+       Gtk::CheckMenuItem* pan_automation_item;
 };
 
 #endif /* __ardour_audio_time_axis_h__ */
index 6edc738c413c579f1f6d5f3622f9f4c8c8aad4d8..fcd17cdb4c9a8d7171928c8c585d93e8fb7c3431 100644 (file)
@@ -209,15 +209,6 @@ Editor::Editor (AudioEngine& eng)
          
          toolbar_selection_clock_table (2,3),
          
-         //mouse_mode_button_table (2, 3),
-
-         /*mouse_select_button (_("range")),
-         mouse_move_button (_("object")),
-         mouse_gain_button (_("gain")),
-         mouse_zoom_button (_("zoom")),
-         mouse_timefx_button (_("timefx")),
-         mouse_audition_button (_("listen")),*/
-
          automation_mode_button (_("mode")),
          global_automation_button (_("automation")),
 
@@ -2588,9 +2579,8 @@ Editor::setup_toolbar ()
        mouse_mode_button_box.pack_start(mouse_audition_button, true, true);
        mouse_mode_button_box.set_homogeneous(true);
 
-       // This one needs a little more "FUDGE" on my machine at least..
        edit_mode_selector.set_name ("EditModeSelector");
-       Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "Splice Edit", 3+FUDGE, 10);
+       Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "Splice Edit", 2+FUDGE, 10);
        set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
        edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
 
index 220de74871f501b9669d1effc6ae092f23d2bcef..bbaf359aa49479de3e02f23053b1550e0393f7de 100644 (file)
@@ -29,6 +29,7 @@ namespace ARDOUR {
        class Session;
        class PluginManager;
        class Plugin;
+       class PluginInfo;
 }
 
 class PluginSelector : public ArdourDialog
index d47b09853c5928d3dcd83bff482c59ae446639b1..411117b1afb1848bd08492add47732fba2ebb980 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2001 Paul Davis 
+    Copyright (C) 2001-2006 Paul Davis 
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -82,35 +82,21 @@ RegionView::RegionView (ArdourCanvas::Group*         parent,
 }
 
 void
-RegionView::init (Gdk::Color& basic_color, bool wfw)
+RegionView::init (Gdk::Color& basic_color, bool wfd)
 {
-    ArdourCanvas::Points shape;
-       //XMLNode *node;
-
-       editor = 0;
-       valid = true;
+       editor        = 0;
+       valid         = true;
        in_destructor = false;
-       _height = 0;
-
-       _flags = 0;
-
-       /*
-       if ((node = _region.extra_xml ("GUI")) != 0) {
-               set_flags (node);
-       } else {
-               //_flags = WaveformVisible;
-               store_flags ();
-       }*/
+       _height       = 0;
+       wait_for_data = wfd;
 
        compute_colors (basic_color);
 
        name_highlight->set_data ("regionview", this);
        name_text->set_data ("regionview", this);
 
-       //      shape = new ArdourCanvas::Points ();
-
        /* an equilateral triangle */
-
+    ArdourCanvas::Points shape;
        shape.push_back (Gnome::Art::Point (-((sync_mark_width-1)/2), 1));
        shape.push_back (Gnome::Art::Point ((sync_mark_width - 1)/2, 1));
        shape.push_back (Gnome::Art::Point (0, sync_mark_width - 1));
@@ -234,9 +220,6 @@ RegionView::region_resized (Change what_changed)
 
                        (*i)->set_duration (unit_length);
 
-                       /*for (vector<WaveView*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
-                               (*w)->property_region_start() = _region.start();
-                       }*/
                }
        }
 }
@@ -246,27 +229,6 @@ RegionView::reset_width_dependent_items (double pixel_width)
 {
        TimeAxisViewItem::reset_width_dependent_items (pixel_width);
        _pixel_width = pixel_width;
-/*
-       if (zero_line) {
-               zero_line->property_x2() = pixel_width - 1.0;
-       }
-
-       if (fade_in_handle) {
-               if (pixel_width <= 6.0) {
-                       fade_in_handle->hide();
-                       fade_out_handle->hide();
-               } else {
-                       if (_height < 5.0) {
-                               fade_in_handle->hide();
-                               fade_out_handle->hide();
-                       } else {
-                               fade_in_handle->show();
-                               fade_out_handle->show();
-                       }
-               }
-       }
-
-       reset_fade_shapes ();*/
 }
 
 void
@@ -282,14 +244,6 @@ RegionView::region_muted ()
 {
        set_frame_color ();
        region_renamed ();
-
-       /*for (uint32_t n=0; n < waves.size(); ++n) {
-               if (_region.muted()) {
-                       waves[n]->property_wave_color() = color_map[cMutedWaveForm];
-               } else {
-                       waves[n]->property_wave_color() = color_map[cWaveForm];
-               }
-       }*/
 }
 
 void
@@ -350,19 +304,11 @@ RegionView::set_samples_per_unit (gdouble spu)
 {
        TimeAxisViewItem::set_samples_per_unit (spu);
 
-       /*for (uint32_t n=0; n < waves.size(); ++n) {
-               waves[n]->property_samples_per_unit() = spu;
-       }*/
-
        for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
                (*i)->set_samples_per_unit (spu);
                (*i)->set_duration (_region.length() / samples_per_unit);
        }
 
-       /*if (gain_line) {
-               gain_line->reset ();
-       }*/
-       //reset_fade_shapes ();
        region_sync_changed ();
 }
 
@@ -384,10 +330,6 @@ void
 RegionView::compute_colors (Gdk::Color& basic_color)
 {
        TimeAxisViewItem::compute_colors (basic_color);
-       uint32_t r, g, b, a;
-
-       UINT_TO_RGBA (fill_color, &r, &g, &b, &a);
-       fade_color = RGBA_TO_UINT(r,g,b,120);
 }
 
 void
@@ -395,21 +337,9 @@ RegionView::set_colors ()
 {
        TimeAxisViewItem::set_colors ();
        
-       /*if (gain_line) {
-               gain_line->set_line_color (_region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]);
-       }*/
-
        if (sync_mark) {
                sync_mark->property_fill_color_rgba() = fill_color;
        }
-
-       /*for (uint32_t n=0; n < waves.size(); ++n) {
-               if (_region.muted()) {
-                       waves[n]->property_wave_color() = color_map[cMutedWaveForm];
-               } else {
-                       waves[n]->property_wave_color() = color_map[cWaveForm];
-               }
-       }*/
 }
 
 void
@@ -445,10 +375,9 @@ RegionView::region_renamed ()
                str = _region.name();
        }
 
-       /* FIXME
        if (_region.speed_mismatch (trackview.session().frame_rate())) {
                str = string ("*") + str;
-       }*/
+       }
 
        if (_region.muted()) {
                str = string ("!") + str;
index 29c5817a251b1d0dc046c35cc301ab087dbb089f..d2d2c2276058394ee9636c64a3865e45d7f5ec41 100644 (file)
@@ -49,7 +49,7 @@ class RegionView : public TimeAxisViewItem
 
        ~RegionView ();
        
-       virtual void init (Gdk::Color& base_color, bool wait_for_waves);
+       virtual void init (Gdk::Color& base_color, bool wait_for_data);
     
        ARDOUR::Region& region() const { return _region; }
        
@@ -57,8 +57,8 @@ class RegionView : public TimeAxisViewItem
     void set_valid (bool yn) { valid = yn; }
 
     virtual void set_height (double) = 0;
-    void set_samples_per_unit (double);
-    bool set_duration (jack_nframes_t, void*);
+    virtual void set_samples_per_unit (double);
+    virtual bool set_duration (jack_nframes_t, void*);
 
     void move (double xdelta, double ydelta);
 
@@ -70,9 +70,9 @@ class RegionView : public TimeAxisViewItem
     bool set_position(jack_nframes_t pos, void* src, double* delta = 0);
 
     virtual void show_region_editor () = 0;
-    void hide_region_editor();
+    virtual void hide_region_editor();
 
-    void region_changed (ARDOUR::Change);
+    virtual void region_changed (ARDOUR::Change);
 
     virtual GhostRegion* add_ghost (AutomationTimeAxisView&) = 0;
     void                 remove_ghost (GhostRegion*);
@@ -93,56 +93,44 @@ class RegionView : public TimeAxisViewItem
     RegionView (ArdourCanvas::Group *, 
                    TimeAxisView&,
                    ARDOUR::Region&,
-                   double initial_samples_per_unit,
+                   double      samples_per_unit,
                    Gdk::Color& basic_color,
                    TimeAxisViewItem::Visibility);
     
        ARDOUR::Region& _region;
     
-    enum Flags {
-           EnvelopeVisible = 0x1,
-           WaveformVisible = 0x4,
-           WaveformRectified = 0x8
-    };
-
     ArdourCanvas::Polygon* sync_mark; ///< polgyon for sync position 
-    ArdourCanvas::Text* no_wave_msg; ///< text 
+    ArdourCanvas::Text*    no_wave_msg;
 
     RegionEditor *editor;
 
     vector<ControlPoint *> control_points;
     double current_visible_sync_position;
 
-    uint32_t _flags;
-    uint32_t fade_color;
     bool     valid; ///< see StreamView::redisplay_diskstream() 
     double  _pixel_width;
     double  _height;
     bool    in_destructor;
-    bool    wait_for_waves;
-    
-       sigc::connection peaks_ready_connection;
-
-    void region_resized (ARDOUR::Change);
-    void region_moved (void *);
-    void region_muted ();
-    void region_locked ();
-    void region_opacity ();
-    void region_layered ();
-    void region_renamed ();
-    void region_sync_changed ();
-    void region_scale_amplitude_changed ();
+
+    bool             wait_for_data;
+       sigc::connection data_ready_connection;
+
+    virtual void region_resized (ARDOUR::Change);
+    void         region_moved (void *);
+    virtual void region_muted ();
+    void         region_locked ();
+    void         region_opacity ();
+    void         region_layered ();
+    void         region_renamed ();
+    void         region_sync_changed ();
 
     static gint _lock_toggle (ArdourCanvas::Item*, GdkEvent*, void*);
     void        lock_toggle ();
 
-    void peaks_ready_handler (uint32_t);
-    void reset_name (gdouble width);
-
-    void set_colors ();
-    void compute_colors (Gdk::Color&);
+    virtual void set_colors ();
+    virtual void compute_colors (Gdk::Color&);
     virtual void set_frame_color ();
-    void reset_width_dependent_items (double pixel_width);
+    virtual void reset_width_dependent_items (double pixel_width);
 
     vector<GhostRegion*> ghosts;
     
index b4f250b5ef4b87287afc6610f827a14ff4f745d3..1eba885b4427dd00705045a2b31153ebc667f043 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2006 Paul Davis 
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -30,6 +30,8 @@
 #include <pbd/stl_delete.h>
 #include <pbd/whitespace.h>
 
+#include <gtkmm/menu.h>
+#include <gtkmm/menuitem.h>
 #include <gtkmm2ext/gtk_ui.h>
 #include <gtkmm2ext/selector.h>
 #include <gtkmm2ext/stop_signal.h>
@@ -49,6 +51,9 @@
 
 #include "ardour_ui.h"
 #include "route_time_axis.h"
+#include "automation_time_axis.h"
+#include "redirect_automation_time_axis.h"
+#include "redirect_automation_line.h"
 #include "canvas_impl.h"
 #include "crossfade_view.h"
 #include "enums.h"
@@ -217,6 +222,12 @@ RouteTimeAxisView::~RouteTimeAxisView ()
 {
        GoingAway (); /* EMIT_SIGNAL */
 
+       vector_delete (&redirect_automation_curves);
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               delete *i;
+       }
+
        if (playlist_menu) {
                delete playlist_menu;
                playlist_menu = 0;
@@ -373,6 +384,97 @@ RouteTimeAxisView::automation_click ()
        automation_action_menu->popup (1, 0);
 }
 
+void
+RouteTimeAxisView::build_automation_action_menu ()
+{
+       using namespace Menu_Helpers;
+
+       automation_action_menu = manage (new Menu);
+       MenuList& automation_items = automation_action_menu->items();
+       automation_action_menu->set_name ("ArdourContextMenu");
+       
+       automation_items.push_back (MenuElem (_("Show all automation"),
+                                             mem_fun(*this, &RouteTimeAxisView::show_all_automation)));
+
+       automation_items.push_back (MenuElem (_("Show existing automation"),
+                                             mem_fun(*this, &RouteTimeAxisView::show_existing_automation)));
+
+       automation_items.push_back (MenuElem (_("Hide all automation"),
+                                             mem_fun(*this, &RouteTimeAxisView::hide_all_automation)));
+
+       automation_items.push_back (MenuElem (_("Plugins"), subplugin_menu));
+}
+
+void
+RouteTimeAxisView::build_display_menu ()
+{
+       using namespace Menu_Helpers;
+
+       /* get the size menu ready */
+
+       build_size_menu ();
+
+       /* prepare it */
+
+       TimeAxisView::build_display_menu ();
+
+       /* now fill it with our stuff */
+
+       MenuList& items = display_menu->items();
+       display_menu->set_name ("ArdourContextMenu");
+       
+       items.push_back (MenuElem (_("Height"), *size_menu));
+       items.push_back (MenuElem (_("Color"), mem_fun(*this, &RouteTimeAxisView::select_track_color)));
+
+       items.push_back (SeparatorElem());
+
+       build_remote_control_menu ();
+       items.push_back (MenuElem (_("Remote Control ID"), *remote_control_menu));
+
+       build_automation_action_menu ();
+       items.push_back (MenuElem (_("Automation"), *automation_action_menu));
+
+       // Hook for derived classes to add type specific stuff
+       items.push_back (SeparatorElem());
+       append_extra_display_menu_items ();
+       items.push_back (SeparatorElem());
+       
+       if (is_track()) {
+
+               Menu* alignment_menu = manage (new Menu);
+               MenuList& alignment_items = alignment_menu->items();
+               alignment_menu->set_name ("ArdourContextMenu");
+
+               RadioMenuItem::Group align_group;
+               
+               alignment_items.push_back (RadioMenuElem (align_group, _("Align with existing material"),
+                       bind (mem_fun(*this, &RouteTimeAxisView::set_align_style), ExistingMaterial)));
+               align_existing_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back());
+               if (get_diskstream()->alignment_style() == ExistingMaterial)
+                       align_existing_item->set_active();
+               
+               alignment_items.push_back (RadioMenuElem (align_group, _("Align with capture time"),
+                       bind (mem_fun(*this, &RouteTimeAxisView::set_align_style), CaptureTime)));
+               align_capture_item = dynamic_cast<RadioMenuItem*>(&alignment_items.back());
+               if (get_diskstream()->alignment_style() == CaptureTime)
+                       align_capture_item->set_active();
+               
+               items.push_back (MenuElem (_("Alignment"), *alignment_menu));
+
+               get_diskstream()->AlignmentStyleChanged.connect (
+                       mem_fun(*this, &RouteTimeAxisView::align_style_changed));
+       }
+
+       items.push_back (SeparatorElem());
+       items.push_back (CheckMenuElem (_("Active"), mem_fun(*this, &RouteUI::toggle_route_active)));
+       route_active_menu_item = dynamic_cast<CheckMenuItem *> (&items.back());
+       route_active_menu_item->set_active (_route->active());
+
+       items.push_back (SeparatorElem());
+       items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route)));
+}
+
+
 void
 RouteTimeAxisView::show_timestretch (jack_nframes_t start, jack_nframes_t end)
 {
@@ -759,6 +861,12 @@ RouteTimeAxisView::set_selected_points (PointSelection& points)
        }
 }
 
+void
+RouteTimeAxisView::set_selected_regionviews (RegionSelection& regions)
+{
+       _view->set_selected_regionviews (regions);
+}
+
 void
 RouteTimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable*>& results)
 {
@@ -1053,3 +1161,399 @@ RouteTimeAxisView::select_me (GdkEventButton* ev)
        return false;
 }
 
+void
+RouteTimeAxisView::show_all_automation ()
+{
+       no_redraw = true;
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+                       if ((*ii)->view == 0) {
+                               add_redirect_automation_curve ((*i)->redirect, (*ii)->what);
+                       } 
+
+                       (*ii)->menu_item->set_active (true);
+               }
+       }
+
+       no_redraw = false;
+
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+void
+RouteTimeAxisView::show_existing_automation ()
+{
+       no_redraw = true;
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+                       if ((*ii)->view != 0) {
+                               (*ii)->menu_item->set_active (true);
+                       }
+               }
+       }
+
+       no_redraw = false;
+
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+void
+RouteTimeAxisView::hide_all_automation ()
+{
+       no_redraw = true;
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+                       (*ii)->menu_item->set_active (false);
+               }
+       }
+
+       no_redraw = false;
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+
+void
+RouteTimeAxisView::region_view_added (RegionView* rv)
+{
+       for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+               AutomationTimeAxisView* atv;
+
+               if ((atv = dynamic_cast<AutomationTimeAxisView*> (*i)) != 0) {
+                       rv->add_ghost (*atv);
+               }
+       }
+}
+
+void
+RouteTimeAxisView::add_ghost_to_redirect (RegionView* rv, AutomationTimeAxisView* atv)
+{
+       rv->add_ghost (*atv);
+}
+
+RouteTimeAxisView::RedirectAutomationInfo::~RedirectAutomationInfo ()
+{
+       for (vector<RedirectAutomationNode*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+               delete *i;
+       }
+}
+
+
+RouteTimeAxisView::RedirectAutomationNode::~RedirectAutomationNode ()
+{
+       parent.remove_ran (this);
+
+       if (view) {
+               delete view;
+       }
+}
+
+void
+RouteTimeAxisView::remove_ran (RedirectAutomationNode* ran)
+{
+       if (ran->view) {
+               remove_child (ran->view);
+       }
+}
+
+RouteTimeAxisView::RedirectAutomationNode*
+RouteTimeAxisView::find_redirect_automation_node (boost::shared_ptr<Redirect> redirect, uint32_t what)
+{
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+
+               if ((*i)->redirect == redirect) {
+
+                       for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+                               if ((*ii)->what == what) {
+                                       return *ii;
+                               }
+                       }
+               }
+       }
+
+       return 0;
+}
+
+// FIXME: duplicated in midi_time_axis.cc
+static string 
+legalize_for_xml_node (string str)
+{
+       string::size_type pos;
+       string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=:";
+       string legal;
+
+       legal = str;
+       pos = 0;
+
+       while ((pos = legal.find_first_not_of (legal_chars, pos)) != string::npos) {
+               legal.replace (pos, 1, "_");
+               pos += 1;
+       }
+
+       return legal;
+}
+
+
+void
+RouteTimeAxisView::add_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what)
+{
+       RedirectAutomationLine* ral;
+       string name;
+       RedirectAutomationNode* ran;
+
+       if ((ran = find_redirect_automation_node (redirect, what)) == 0) {
+               fatal << _("programming error: ")
+                     << string_compose (X_("redirect automation curve for %1:%2 not registered with audio track!"),
+                                 redirect->name(), what)
+                     << endmsg;
+               /*NOTREACHED*/
+               return;
+       }
+
+       if (ran->view) {
+               return;
+       }
+
+       name = redirect->describe_parameter (what);
+
+       /* create a string that is a legal XML node name that can be used to refer to this redirect+port combination */
+
+       char state_name[256];
+       snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (redirect->name()).c_str(), what);
+
+       ran->view = new RedirectAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *redirect, state_name);
+
+       ral = new RedirectAutomationLine (name, 
+                                         *redirect, what, _session, *ran->view,
+                                         *ran->view->canvas_display, redirect->automation_list (what));
+       
+       ral->set_line_color (color_map[cRedirectAutomationLine]);
+       ral->queue_reset ();
+
+       ran->view->add_line (*ral);
+
+       ran->view->Hiding.connect (bind (mem_fun(*this, &RouteTimeAxisView::redirect_automation_track_hidden), ran, redirect));
+
+       if (!ran->view->marked_for_display()) {
+               ran->view->hide ();
+       } else {
+               ran->menu_item->set_active (true);
+       }
+
+       add_child (ran->view);
+
+       _view->foreach_regionview (bind (mem_fun(*this, &RouteTimeAxisView::add_ghost_to_redirect), ran->view));
+
+       redirect->mark_automation_visible (what, true);
+}
+
+void
+RouteTimeAxisView::redirect_automation_track_hidden (RouteTimeAxisView::RedirectAutomationNode* ran, boost::shared_ptr<Redirect> r)
+{
+       if (!_hidden) {
+               ran->menu_item->set_active (false);
+       }
+
+       r->mark_automation_visible (ran->what, false);
+
+        _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+void
+RouteTimeAxisView::add_existing_redirect_automation_curves (boost::shared_ptr<Redirect> redirect)
+{
+       set<uint32_t> s;
+       RedirectAutomationLine *ral;
+
+       redirect->what_has_visible_automation (s);
+
+       for (set<uint32_t>::iterator i = s.begin(); i != s.end(); ++i) {
+               
+               if ((ral = find_redirect_automation_curve (redirect, *i)) != 0) {
+                       ral->queue_reset ();
+               } else {
+                       add_redirect_automation_curve (redirect, (*i));
+               }
+       }
+}
+
+void
+RouteTimeAxisView::add_redirect_to_subplugin_menu (boost::shared_ptr<Redirect> r)
+{
+       using namespace Menu_Helpers;
+       RedirectAutomationInfo *rai;
+       list<RedirectAutomationInfo*>::iterator x;
+       
+       const std::set<uint32_t>& automatable = r->what_can_be_automated ();
+       std::set<uint32_t> has_visible_automation;
+
+       r->what_has_visible_automation(has_visible_automation);
+
+       if (automatable.empty()) {
+               return;
+       }
+
+       for (x = redirect_automation.begin(); x != redirect_automation.end(); ++x) {
+               if ((*x)->redirect == r) {
+                       break;
+               }
+       }
+
+       if (x == redirect_automation.end()) {
+
+               rai = new RedirectAutomationInfo (r);
+               redirect_automation.push_back (rai);
+
+       } else {
+
+               rai = *x;
+
+       }
+
+       /* any older menu was deleted at the top of redirects_changed()
+          when we cleared the subplugin menu.
+       */
+
+       rai->menu = manage (new Menu);
+       MenuList& items = rai->menu->items();
+       rai->menu->set_name ("ArdourContextMenu");
+
+       items.clear ();
+
+       for (std::set<uint32_t>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) {
+
+               RedirectAutomationNode* ran;
+               CheckMenuItem* mitem;
+               
+               string name = r->describe_parameter (*i);
+               
+               items.push_back (CheckMenuElem (name));
+               mitem = dynamic_cast<CheckMenuItem*> (&items.back());
+
+               if (has_visible_automation.find((*i)) != has_visible_automation.end()) {
+                       mitem->set_active(true);
+               }
+
+               if ((ran = find_redirect_automation_node (r, *i)) == 0) {
+
+                       /* new item */
+                       
+                       ran = new RedirectAutomationNode (*i, mitem, *this);
+                       
+                       rai->lines.push_back (ran);
+
+               } else {
+
+                       ran->menu_item = mitem;
+
+               }
+
+               mitem->signal_toggled().connect (bind (mem_fun(*this, &RouteTimeAxisView::redirect_menu_item_toggled), rai, ran));
+       }
+
+       /* add the menu for this redirect, because the subplugin
+          menu is always cleared at the top of redirects_changed().
+          this is the result of some poor design in gtkmm and/or
+          GTK+.
+       */
+
+       subplugin_menu.items().push_back (MenuElem (r->name(), *rai->menu));
+       rai->valid = true;
+}
+
+void
+RouteTimeAxisView::redirect_menu_item_toggled (RouteTimeAxisView::RedirectAutomationInfo* rai,
+                                              RouteTimeAxisView::RedirectAutomationNode* ran)
+{
+       bool showit = ran->menu_item->get_active();
+       bool redraw = false;
+
+       if (ran->view == 0 && showit) {
+               add_redirect_automation_curve (rai->redirect, ran->what);
+               redraw = true;
+       }
+
+       if (showit != ran->view->marked_for_display()) {
+
+               if (showit) {
+                       ran->view->set_marked_for_display (true);
+                       ran->view->canvas_display->show();
+               } else {
+                       rai->redirect->mark_automation_visible (ran->what, true);
+                       ran->view->set_marked_for_display (false);
+                       ran->view->hide ();
+               }
+
+               redraw = true;
+
+       }
+
+       if (redraw && !no_redraw) {
+
+               /* now trigger a redisplay */
+               
+                _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+
+       }
+}
+
+void
+RouteTimeAxisView::redirects_changed (void *src)
+{
+       using namespace Menu_Helpers;
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+               (*i)->valid = false;
+       }
+
+       subplugin_menu.items().clear ();
+
+       _route->foreach_redirect (this, &RouteTimeAxisView::add_redirect_to_subplugin_menu);
+       _route->foreach_redirect (this, &RouteTimeAxisView::add_existing_redirect_automation_curves);
+
+       for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ) {
+
+               list<RedirectAutomationInfo*>::iterator tmp;
+
+               tmp = i;
+               ++tmp;
+
+               if (!(*i)->valid) {
+
+                       delete *i;
+                       redirect_automation.erase (i);
+
+               } 
+
+               i = tmp;
+       }
+
+       /* change in visibility was possible */
+
+       _route->gui_changed ("track_height", this);
+}
+
+RedirectAutomationLine *
+RouteTimeAxisView::find_redirect_automation_curve (boost::shared_ptr<Redirect> redirect, uint32_t what)
+{
+       RedirectAutomationNode* ran;
+
+       if ((ran = find_redirect_automation_node (redirect, what)) != 0) {
+               if (ran->view) {
+                       return dynamic_cast<RedirectAutomationLine*> (ran->view->lines.front());
+               } 
+       }
+
+       return 0;
+}
+
+void
+RouteTimeAxisView::reset_redirect_automation_curves ()
+{
+       for (vector<RedirectAutomationLine*>::iterator i = redirect_automation_curves.begin(); i != redirect_automation_curves.end(); ++i) {
+               (*i)->reset();
+       }
+}
+
index a75851b8a8419b23185184a11ea679e73cc66a4a..476a135c395201d52b95445e141fac52aeeea384 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2006 Paul Davis 
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -33,7 +33,6 @@
 #include <list>
 
 #include <ardour/types.h>
-#include <ardour/region.h>
 
 #include "ardour_dialog.h"
 #include "route_ui.h"
@@ -44,6 +43,7 @@
 
 namespace ARDOUR {
        class Session;
+       class Region;
        class Diskstream;
        class RouteGroup;
        class Redirect;
@@ -57,12 +57,14 @@ class RegionView;
 class StreamView;
 class Selection;
 class Selectable;
+class AutomationTimeAxisView;
 class AutomationLine;
+class RedirectAutomationLine;
 class TimeSelection;
 
 class RouteTimeAxisView : public RouteUI, public TimeAxisView
 {
-  public:
+public:
        RouteTimeAxisView (PublicEditor&, ARDOUR::Session&, boost::shared_ptr<ARDOUR::Route>, ArdourCanvas::Canvas& canvas);
        virtual ~RouteTimeAxisView ();
 
@@ -74,51 +76,57 @@ class RouteTimeAxisView : public RouteUI, public TimeAxisView
        void hide_timestretch ();
        void selection_click (GdkEventButton*);
        void set_selected_points (PointSelection&);
+       void set_selected_regionviews (RegionSelection&);
        void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable *>&);
        void get_inverted_selectables (Selection&, list<Selectable*>&);
                
        ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir);
 
-       string name() const;
-
-       ARDOUR::RouteGroup* edit_group() const;
-
-       void build_playlist_menu (Gtk::Menu *);
-       ARDOUR::Playlist* playlist() const;
-
-       StreamView* view() { return _view; }
-
-       /* editing operations */
-       
+       /* Editing operations */
        bool cut_copy_clear (Selection&, Editing::CutCopyOp);
        bool paste (jack_nframes_t, float times, Selection&, size_t nth);
 
        list<TimeAxisView*> get_child_list();
 
-       /* the editor calls these when mapping an operation across multiple tracks */
-
+       /* The editor calls these when mapping an operation across multiple tracks */
        void use_new_playlist (bool prompt);
        void use_copy_playlist (bool prompt);
        void clear_playlist ();
+       
+       void build_playlist_menu (Gtk::Menu *);
+       
+       string              name() const;
+       StreamView*         view() const { return _view; }
+       ARDOUR::RouteGroup* edit_group() const;
+       ARDOUR::Playlist*   playlist() const;
 
-  //private: (FIXME)
+protected:
        friend class StreamView;
        
-       StreamView *_view;
+       struct RedirectAutomationNode {
+           uint32_t                what;
+           Gtk::CheckMenuItem*     menu_item;
+           AutomationTimeAxisView* view;
+           RouteTimeAxisView&      parent;
 
-       ArdourCanvas::Canvas& parent_canvas;
+           RedirectAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, RouteTimeAxisView& p)
+                   : what (w), menu_item (mitem), view (0), parent (p) {}
 
-       bool         no_redraw;
-  
-       Gtk::HBox   other_button_hbox;
-       Gtk::Table  button_table;
-       Gtk::Button redirect_button;
-       Gtk::Button edit_group_button;
-       Gtk::Button playlist_button;
-       Gtk::Button size_button;
-       Gtk::Button automation_button;
-       Gtk::Button hide_button;
-       Gtk::Button visual_button;
+           ~RedirectAutomationNode ();
+       };
+
+       struct RedirectAutomationInfo {
+           boost::shared_ptr<ARDOUR::Redirect> redirect;
+           bool                                valid;
+           Gtk::Menu*                          menu;
+           vector<RedirectAutomationNode*>     lines;
+
+           RedirectAutomationInfo (boost::shared_ptr<ARDOUR::Redirect> r) 
+                   : redirect (r), valid (true), menu (0) {}
+
+           ~RedirectAutomationInfo ();
+       };
+       
 
        void diskstream_changed (void *src);
        void update_diskstream_display ();
@@ -133,11 +141,30 @@ class RouteTimeAxisView : public RouteUI, public TimeAxisView
        void redirect_relist ();
        void redirect_row_selected (gint row, gint col, GdkEvent *ev);
        void add_to_redirect_display (ARDOUR::Redirect *);
-       //void redirects_changed (void *);
+       void redirects_changed (void *);
+       
+       void add_redirect_to_subplugin_menu (boost::shared_ptr<ARDOUR::Redirect>);
+       void remove_ran (RedirectAutomationNode* ran);
 
-       sigc::connection modified_connection;
-       sigc::connection state_changed_connection;
+       void redirect_menu_item_toggled (RouteTimeAxisView::RedirectAutomationInfo*,
+                                        RouteTimeAxisView::RedirectAutomationNode*);
+       
+       void redirect_automation_track_hidden (RedirectAutomationNode*,
+                                              boost::shared_ptr<ARDOUR::Redirect>);
+
+       RedirectAutomationNode*
+       find_redirect_automation_node (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
+       
+       RedirectAutomationLine*
+       find_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
 
+       void add_redirect_automation_curve (boost::shared_ptr<ARDOUR::Redirect> r, uint32_t);
+       void add_existing_redirect_automation_curves (boost::shared_ptr<ARDOUR::Redirect>);
+       
+       void reset_redirect_automation_curves ();
+
+       void update_automation_view (ARDOUR::AutomationType);
+       
        void take_name_changed (void *);
        void route_name_changed (void *);
        void name_entry_changed ();
@@ -145,9 +172,7 @@ class RouteTimeAxisView : public RouteUI, public TimeAxisView
        void on_area_realize ();
 
        virtual void label_view ();
-
-       Gtk::Menu edit_group_menu;
-
+       
        void add_edit_group_menu_item (ARDOUR::RouteGroup *, Gtk::RadioMenuItem::Group*);
        void set_edit_group_from_menu (ARDOUR::RouteGroup *);
 
@@ -155,35 +180,27 @@ class RouteTimeAxisView : public RouteUI, public TimeAxisView
 
        void select_track_color();
        
-       virtual void build_display_menu () = 0;
-
-       Gtk::RadioMenuItem* align_existing_item;
-       Gtk::RadioMenuItem* align_capture_item;
+       virtual void build_automation_action_menu ();
+       virtual void append_extra_display_menu_items () {}
+       void         build_display_menu ();
        
        void align_style_changed ();
        void set_align_style (ARDOUR::AlignStyle);
-
-       Gtk::Menu     *playlist_menu;
-       Gtk::Menu     *playlist_action_menu;
-       Gtk::MenuItem *playlist_item;
        
-       /* playlist */
-
        virtual void set_playlist (ARDOUR::Playlist *);
-       void playlist_click ();
-       void show_playlist_selector ();
-
-       void playlist_changed ();
-       void playlist_state_changed (ARDOUR::Change);
-       void playlist_modified ();
+       void         playlist_click ();
+       void         show_playlist_selector ();
+       void         playlist_changed ();
+       void         playlist_state_changed (ARDOUR::Change);
+       void         playlist_modified ();
 
        void add_playlist_to_playlist_menu (ARDOUR::Playlist*);
        void rename_current_playlist ();
        
-       Gtk::Menu* automation_action_menu;
-       void automation_click ();
-
-       ArdourCanvas::SimpleRect *timestretch_rect;
+       void         automation_click ();
+       virtual void show_all_automation ();
+       virtual void show_existing_automation ();
+       virtual void hide_all_automation ();
 
        void timestretch (jack_nframes_t start, jack_nframes_t end);
 
@@ -198,7 +215,40 @@ class RouteTimeAxisView : public RouteUI, public TimeAxisView
        void color_handler (ColorID, uint32_t);
        bool select_me (GdkEventButton*);
        
-       virtual void region_view_added (RegionView*) = 0;
+       void region_view_added (RegionView*);
+       void add_ghost_to_redirect (RegionView*, AutomationTimeAxisView*);
+       
+       
+       StreamView*           _view;
+       ArdourCanvas::Canvas& parent_canvas;
+       bool                  no_redraw;
+  
+       Gtk::HBox   other_button_hbox;
+       Gtk::Table  button_table;
+       Gtk::Button redirect_button;
+       Gtk::Button edit_group_button;
+       Gtk::Button playlist_button;
+       Gtk::Button size_button;
+       Gtk::Button automation_button;
+       Gtk::Button hide_button;
+       Gtk::Button visual_button;
+       
+       Gtk::Menu           subplugin_menu;
+       Gtk::Menu*          automation_action_menu;
+       Gtk::Menu           edit_group_menu;
+       Gtk::RadioMenuItem* align_existing_item;
+       Gtk::RadioMenuItem* align_capture_item;
+       Gtk::Menu*          playlist_menu;
+       Gtk::Menu*          playlist_action_menu;
+       Gtk::MenuItem*      playlist_item;
+
+       ArdourCanvas::SimpleRect* timestretch_rect;
+       
+       list<RedirectAutomationInfo*>   redirect_automation;
+       vector<RedirectAutomationLine*> redirect_automation_curves;
+
+       sigc::connection modified_connection;
+       sigc::connection state_changed_connection;
 };
 
 #endif /* __ardour_route_time_axis_h__ */
index 93d25b6a973629ef1400ff56154611f36543f8dd..c94184272e3397cb4ba91766b369694aa137c60a 100644 (file)
@@ -60,7 +60,6 @@ StreamView::StreamView (RouteTimeAxisView& tv)
        canvas_rect->property_y1() = 0.0;
        canvas_rect->property_x2() = 1000000.0;
        canvas_rect->property_y2() = (double) tv.height;
-       canvas_rect->property_outline_color_rgba() = color_map[cAudioTrackOutline]; // FIXME
        canvas_rect->property_outline_what() = (guint32) (0x1|0x2|0x8);  // outline ends and bottom 
        canvas_rect->property_fill_color_rgba() = stream_base_color;
 
index f2906d40c4724e8177d78adf20c047f37041048b..baa779ba67431f075d42c605138de9838420c64b 100644 (file)
@@ -98,35 +98,37 @@ public:
 protected:
        StreamView (RouteTimeAxisView&);
        
-//private:
-       void update_rec_box ();
-       void transport_changed();
-       void rec_enable_changed(void*  src = 0);
-       void sess_rec_enable_changed();
+//private: (FIXME?)
+
+       void         transport_changed();
+       void         rec_enable_changed(void*  src = 0);
+       void         sess_rec_enable_changed();
        virtual void setup_rec_box () = 0;
-       void rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, ARDOUR::Source* src); 
+       void         update_rec_box ();
        virtual void update_rec_regions () = 0;
        
        virtual void add_region_view_internal (ARDOUR::Region*, bool wait_for_waves) = 0;
        virtual void remove_region_view (ARDOUR::Region* );
-       void remove_rec_region (ARDOUR::Region*);
+       void         remove_rec_region (ARDOUR::Region*);
 
-       void display_diskstream (ARDOUR::Diskstream* );
+       void         display_diskstream (ARDOUR::Diskstream* );
        virtual void undisplay_diskstream ();
        virtual void redisplay_diskstream () = 0;
-       void diskstream_changed (void* );
-       void playlist_state_changed (ARDOUR::Change);
+       void         diskstream_changed (void* );
+       
+       void         playlist_state_changed (ARDOUR::Change);
        virtual void playlist_changed (ARDOUR::Diskstream* );
        virtual void playlist_modified ();
+       
+       virtual void color_handler (ColorID, uint32_t) = 0;
 
 
-       RouteTimeAxisView& _trackview;
-
+       RouteTimeAxisView&        _trackview;
        ArdourCanvas::Group*      canvas_group;
        ArdourCanvas::SimpleRect* canvas_rect; /* frame around the whole thing */
 
        typedef list<RegionView* > RegionViewList;
-       RegionViewList region_views;
+       RegionViewList  region_views;
 
        double _samples_per_unit;
 
@@ -141,8 +143,6 @@ protected:
        Gdk::Color region_color;
        uint32_t   stream_base_color;
 
-       virtual void color_handler (ColorID, uint32_t) = 0;
-
        vector<sigc::connection> playlist_connections;
        sigc::connection         playlist_change_connection;
 };
index 76fd91337e5039f4f258f53f93a2b2713feec380..19e6ba3ad3462f8df118c1ddccb9d1aabba76760 100644 (file)
@@ -63,53 +63,9 @@ TapeAudioRegionView::TapeAudioRegionView (ArdourCanvas::Group *parent, RouteTime
 void
 TapeAudioRegionView::init (Gdk::Color& basic_color, bool wfw)
 {
-       XMLNode *node;
-
-       editor = 0;
-       valid = true;
-       in_destructor = false;
-       _amplitude_above_axis = 1.0;
-       zero_line = 0;
-       wait_for_waves = wfw;
-       _height = 0;
-
-       _flags = 0;
-
-       if ((node = _region.extra_xml ("GUI")) != 0) {
-               set_flags (node);
-       } else {
-               _flags = WaveformVisible;
-               store_flags ();
-       }
-
-       fade_in_handle = 0;
-       fade_out_handle = 0;
-       gain_line = 0;
-       sync_mark = 0;
-
-       compute_colors (basic_color);
-
-       create_waves ();
-
-       name_highlight->set_data ("regionview", this);
-
-       reset_width_dependent_items ((double) _region.length() / samples_per_unit);
-
-       set_height (trackview.height);
-
-       region_muted ();
-       region_resized (BoundsChanged);
-       set_waveview_data_src();
-       region_locked ();
-
-       /* no events, no state changes */
-
-       set_colors ();
-
-       // ColorChanged.connect (mem_fun (*this, &AudioRegionView::color_handler));
+       AudioRegionView::init(basic_color, wfw);
 
        /* every time the wave data changes and peaks are ready, redraw */
-
        
        for (uint32_t n = 0; n < audio_region().n_channels(); ++n) {
                audio_region().source(n).PeaksReady.connect (bind (mem_fun(*this, &TapeAudioRegionView::update), n));
index c4a942a5d7dbb8155ee71b1aa8ae0b544ecfe6e4..ec15cf1caff57067fbbe6ec915a7bf944d2c9467 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2000-2006 Paul Davis 
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -14,8 +14,6 @@
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-    $Id: diskstream.h 579 2006-06-12 19:56:37Z essej $
 */
 
 #ifndef __ardour_audio_diskstream_h__
@@ -62,18 +60,12 @@ class AudioDiskstream : public Diskstream
        AudioDiskstream (Session &, const string& name, Diskstream::Flag f = Recordable);
        AudioDiskstream (Session &, const XMLNode&);
 
-       void set_io (ARDOUR::IO& io);
-
+       // FIXME
        AudioDiskstream& ref() { _refcnt++; return *this; }
-       //void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
-       //uint32_t refcnt() const { return _refcnt; }
 
        float playback_buffer_load() const;
        float capture_buffer_load() const;
 
-       //void set_align_style (AlignStyle);
-       //void set_persistent_align_style (AlignStyle);
-
        string input_source (uint32_t n=0) const {
                if (n < channels.size()) {
                        return channels[n].source ? channels[n].source->name() : "";
@@ -87,7 +79,6 @@ class AudioDiskstream : public Diskstream
        }
 
        void set_record_enabled (bool yn, void *src);
-       //void set_speed (double);
 
        float peak_power(uint32_t n=0) { 
                float x = channels[n].peak_power;
@@ -98,16 +89,13 @@ class AudioDiskstream : public Diskstream
                        return minus_infinity();
                }
        }
+       
+       AudioPlaylist* audio_playlist () { return dynamic_cast<AudioPlaylist*>(_playlist); }
 
        int use_playlist (Playlist *);
        int use_new_playlist ();
        int use_copy_playlist ();
 
-       void start_scrub (jack_nframes_t where) {} // FIXME?
-       void end_scrub () {} // FIXME?
-
-       Playlist *playlist () { return _playlist; }
-
        Sample *playback_buffer (uint32_t n=0) {
                if (n < channels.size())
                        return channels[n].current_playback_buffer;
@@ -137,7 +125,6 @@ class AudioDiskstream : public Diskstream
 
        void monitor_input (bool);
 
-       // FIXME: these don't belong here
        static void swap_by_ptr (Sample *first, Sample *last) {
                while (first < last) {
                        Sample tmp = *first;
@@ -154,11 +141,6 @@ class AudioDiskstream : public Diskstream
                }
        }
 
-       //void handle_input_change (IOChange, void *src);
-       
-       //static sigc::signal<void> DiskOverrun;
-       //static sigc::signal<void> DiskUnderrun;
-       //static sigc::signal<void,AudioDiskstream*> AudioDiskstreamCreated;   // XXX use a ref with sigc2
        static sigc::signal<void,list<AudioFileSource*>*> DeleteSources;
 
        int set_loop (Location *loc);
@@ -168,8 +150,6 @@ class AudioDiskstream : public Diskstream
                return _last_capture_regions;
        }
 
-       void handle_input_change (IOChange, void *src);
-
        const PBD::ID& id() const { return _id; }
 
        XMLNode* deprecated_io_node;
@@ -184,7 +164,6 @@ class AudioDiskstream : public Diskstream
 
        void set_pending_overwrite(bool);
        int  overwrite_existing_buffers ();
-       void reverse_scrub_buffer (bool to_forward) {} // FIXME?
        void set_block_size (jack_nframes_t);
        int  internal_playback_seek (jack_nframes_t distance);
        int  can_internal_playback_seek (jack_nframes_t distance);
@@ -237,60 +216,30 @@ class AudioDiskstream : public Diskstream
                jack_nframes_t                     curr_capture_cnt;
        };
 
-       typedef vector<ChannelInfo> ChannelList;
-
-       /* the two central butler operations */
-
-       int do_flush (char * workbuf, bool force = false);
-       int do_refill (Sample *mixdown_buffer, float *gain_buffer, char *workbuf);
+       /* The two central butler operations */
+       int do_flush (Session::RunContext context, bool force = false);
+       int do_refill () { return _do_refill(_mixdown_buffer, _gain_buffer, _conversion_buffer); }
        
-       virtual int non_realtime_do_refill() { return do_refill(0, 0, 0); }
+       int do_refill_with_alloc();
 
-       int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf, jack_nframes_t& start, jack_nframes_t cnt, 
-                 ChannelInfo& channel_info, int channel, bool reversed);
-
-       /* XXX fix this redundancy ... */
-
-       //void playlist_changed (Change);
-       //void playlist_modified ();
-       void playlist_deleted (Playlist*);
-       void session_controls_changed (Session::ControlType) {} // FIXME?
+       int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf,
+               jack_nframes_t& start, jack_nframes_t cnt, 
+               ChannelInfo& channel_info, int channel, bool reversed);
 
        void finish_capture (bool rec_monitors_input);
-       void clean_up_capture (struct tm&, time_t, bool abort) {} // FIXME?
        void transport_stopped (struct tm&, time_t, bool abort);
 
-       struct CaptureInfo {
-           uint32_t start;
-           uint32_t frames;
-       };
-
-       vector<CaptureInfo*> capture_info;
-       Glib::Mutex  capture_info_lock;
-       
        void init (Diskstream::Flag);
 
        void init_channel (ChannelInfo &chan);
        void destroy_channel (ChannelInfo &chan);
        
        int use_new_write_source (uint32_t n=0);
-       int use_new_fade_source (uint32_t n=0) { return 0; } // FIXME?
 
        int find_and_use_playlist (const string&);
 
        void allocate_temporary_buffers ();
 
-       int  create_input_port () { return 0; } // FIXME?
-       int  connect_input_port () { return 0; } // FIXME?
-       int  seek_unlocked (jack_nframes_t which_sample) { return 0; } // FIXME?
-
-       int ports_created () { return 0; } // FIXME?
-
-       //bool realtime_set_speed (double, bool global_change);
-       void non_realtime_set_speed ();
-
-       std::list<Region*> _last_capture_regions;
-       std::vector<AudioFileSource*> capturing_sources;
        int use_pending_capture_data (XMLNode& node);
 
        void get_input_sources ();
@@ -299,10 +248,26 @@ class AudioDiskstream : public Diskstream
        void setup_destructive_playlist ();
        void use_destructive_playlist ();
 
-       ChannelList    channels;
-       AudioPlaylist* _playlist;
        void engage_record_enable (void* src);
        void disengage_record_enable (void* src);
+
+       // Working buffers for do_refill (butler thread)
+       static void allocate_working_buffers();
+       static void free_working_buffers();
+
+       static size_t  _working_buffers_size;
+       static Sample* _mixdown_buffer;
+       static gain_t* _gain_buffer;
+       static char*   _conversion_buffer;
+
+       // Uh, /really/ private?  (death to friend classes)
+       int _do_refill (Sample *mixdown_buffer, float *gain_buffer, char *workbuf);
+       
+       
+       std::vector<AudioFileSource*> capturing_sources;
+       
+       typedef vector<ChannelInfo> ChannelList;
+       ChannelList channels;
 };
 
 } // namespace ARDOUR
index b595879264f0023fad87fbda5e3421a9635619e9..ff25127ec973881cf095214c3c13c8aaa04e4492 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2000-2006 Paul Davis 
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -52,7 +52,6 @@ class AudioEngine;
 class Send;
 class Session;
 class Playlist;
-//class FileSource;
 class IO;
 
 /* FIXME: There are (obviously) far too many virtual functions in this ATM.
@@ -71,10 +70,10 @@ class Diskstream : public Stateful, public sigc::trackable
        virtual int set_name (string str, void* src);
 
        ARDOUR::IO* io() const { return _io; }
-       virtual void set_io (ARDOUR::IO& io) = 0;
+       void set_io (ARDOUR::IO& io);
 
        virtual Diskstream& ref() { _refcnt++; return *this; }
-       void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
+       void     unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
        uint32_t refcnt() const { return _refcnt; }
 
        virtual float playback_buffer_load() const = 0;
@@ -105,17 +104,15 @@ class Diskstream : public Stateful, public sigc::trackable
        virtual void punch_in()  {}
        virtual void punch_out() {}
 
-       virtual void set_speed (double);
-       virtual void non_realtime_set_speed () = 0;
+       void set_speed (double);
+       void non_realtime_set_speed ();
 
-       virtual Playlist *playlist () = 0;
+       Playlist* playlist () { return _playlist; }
+
+       virtual int use_playlist (Playlist *);
        virtual int use_new_playlist () = 0;
-       virtual int use_playlist (Playlist *) = 0;
        virtual int use_copy_playlist () = 0;
 
-       virtual void start_scrub (jack_nframes_t where) = 0;
-       virtual void end_scrub () = 0;
-
        jack_nframes_t current_capture_start() const { return capture_start_frame; }
        jack_nframes_t current_capture_end()   const { return capture_start_frame + capture_captured; }
        jack_nframes_t get_capture_start_frame (uint32_t n=0);
@@ -123,7 +120,7 @@ class Diskstream : public Stateful, public sigc::trackable
        
        uint32_t n_channels() { return _n_channels; }
 
-       static jack_nframes_t disk_io_frames() { return disk_io_chunk_frames; }
+       static jack_nframes_t disk_io_frames()            { return disk_io_chunk_frames; }
        static void set_disk_io_chunk_frames (uint32_t n) { disk_io_chunk_frames = n; }
 
        /* Stateful */
@@ -144,7 +141,7 @@ class Diskstream : public Stateful, public sigc::trackable
 
        std::list<Region*>& last_capture_regions () { return _last_capture_regions; }
 
-       virtual void handle_input_change (IOChange, void *src);
+       void handle_input_change (IOChange, void *src);
 
        sigc::signal<void,void*> RecordEnableChanged;
        sigc::signal<void>       SpeedChanged;
@@ -170,7 +167,6 @@ class Diskstream : public Stateful, public sigc::trackable
 
        virtual void set_pending_overwrite (bool) = 0;
        virtual int  overwrite_existing_buffers () = 0;
-       virtual void reverse_scrub_buffer (bool to_forward) = 0;
        virtual void set_block_size (jack_nframes_t) = 0;
        virtual int  internal_playback_seek (jack_nframes_t distance) = 0;
        virtual int  can_internal_playback_seek (jack_nframes_t distance) = 0;
@@ -209,25 +205,21 @@ class Diskstream : public Stateful, public sigc::trackable
                jack_nframes_t   capture_val;
        };
 
-       /* the two central butler operations */
-
-       virtual int do_flush (char * workbuf, bool force = false) = 0;
-       //int do_refill (Sample *mixdown_buffer, float *gain_buffer, char *workbuf);
+       /* The two central butler operations */
+       virtual int do_flush (Session::RunContext context, bool force = false) = 0;
+       virtual int do_refill () = 0;
        
-       virtual int non_realtime_do_refill() = 0;
+       /** For non-butler contexts (allocates temporary working buffers) */
+       virtual int do_refill_with_alloc() = 0;
 
-       //int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf, jack_nframes_t& start, jack_nframes_t cnt, 
-       //        ChannelInfo& channel_info, int channel, bool reversed);
        
        /* XXX fix this redundancy ... */
 
        virtual void playlist_changed (Change);
        virtual void playlist_modified ();
-       virtual void playlist_deleted (Playlist*) = 0;
-       virtual void session_controls_changed (Session::ControlType) = 0;
+       virtual void playlist_deleted (Playlist*);
 
        virtual void finish_capture (bool rec_monitors_input) = 0;
-       virtual void clean_up_capture (struct tm&, time_t, bool abort) = 0;
        virtual void transport_stopped (struct tm&, time_t, bool abort) = 0;
 
        struct CaptureInfo {
@@ -237,37 +229,23 @@ class Diskstream : public Stateful, public sigc::trackable
 
        virtual void init (Flag);
 
-       //void init_channel (ChannelInfo &chan);
-       //void destroy_channel (ChannelInfo &chan);
-
        virtual int use_new_write_source (uint32_t n=0) = 0;
-       virtual int use_new_fade_source (uint32_t n=0) = 0;
 
        virtual int find_and_use_playlist (const string&) = 0;
 
-       //void allocate_temporary_buffers ();
-
-       virtual int  create_input_port () = 0;
-       virtual int  connect_input_port () = 0;
-       virtual int  seek_unlocked (jack_nframes_t which_sample) = 0;
-
-       virtual int ports_created () = 0;
+       virtual void allocate_temporary_buffers () = 0;
 
        virtual bool realtime_set_speed (double, bool global_change);
-       //void non_realtime_set_speed ();
 
        std::list<Region*> _last_capture_regions;
-       //std::vector<FileSource*> capturing_sources;
        virtual int use_pending_capture_data (XMLNode& node) = 0;
 
        virtual void get_input_sources () = 0;
        virtual void check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record) = 0;
-       //void set_align_style_from_io();
+       virtual void set_align_style_from_io() {}
        virtual void setup_destructive_playlist () = 0;
-       //void use_destructive_playlist ();
+       virtual void use_destructive_playlist () = 0;
 
-       // Wouldn't hurt for this thing to do on a diet:
-       
        static jack_nframes_t disk_io_chunk_frames;
        vector<CaptureInfo*>  capture_info;
        Glib::Mutex           capture_info_lock;
@@ -279,6 +257,7 @@ class Diskstream : public Stateful, public sigc::trackable
        ARDOUR::IO*       _io;
        uint32_t          _n_channels;
        PBD::ID           _id;
+       Playlist*         _playlist;
 
        mutable gint             _record_enabled;
        double                   _visible_speed;
@@ -338,7 +317,6 @@ class Diskstream : public Stateful, public sigc::trackable
        sigc::connection plgone_connection;
        
        unsigned char _flags;
-
 };
 
 }; /* namespace ARDOUR */
index b6121d1176ac151f1103e52d8486df5a437c95d3..5998363d693b3b62436915dbebaeab1c91a94a7e 100644 (file)
@@ -80,9 +80,6 @@ class MidiDiskstream : public Diskstream
        int use_new_playlist ();
        int use_copy_playlist ();
 
-       void start_scrub (jack_nframes_t where) {} // FIXME?
-       void end_scrub () {} // FIXME?
-
        Playlist *playlist () { return _playlist; }
 
        static sigc::signal<void,list<SMFSource*>*> DeleteSources;
@@ -106,7 +103,6 @@ class MidiDiskstream : public Diskstream
 
        void set_pending_overwrite(bool);
        int  overwrite_existing_buffers ();
-       void reverse_scrub_buffer (bool to_forward) {} // FIXME?
        void set_block_size (jack_nframes_t);
        int  internal_playback_seek (jack_nframes_t distance);
        int  can_internal_playback_seek (jack_nframes_t distance);
@@ -134,12 +130,11 @@ class MidiDiskstream : public Diskstream
 
        MidiPlaylist* _playlist;
 
-       /* the two central butler operations */
-
-       int do_flush (char * workbuf, bool force = false);
-       int do_refill (RawMidi *mixdown_buffer, float *gain_buffer, char *workbuf);
+       /*Tthe two central butler operations */
+       int do_flush (Session::RunContext context, bool force = false) { return 0; }
+       int do_refill () { return 0; }
        
-       virtual int non_realtime_do_refill() { return do_refill(0, 0, 0); }
+       int do_refill_with_alloc() { return 0; }
 
        int read (RawMidi* buf, RawMidi* mixdown_buffer, char * workbuf, jack_nframes_t& start, jack_nframes_t cnt, bool reversed);
 
@@ -148,10 +143,8 @@ class MidiDiskstream : public Diskstream
        //void playlist_changed (Change);
        //void playlist_modified ();
        void playlist_deleted (Playlist*);
-       void session_controls_changed (Session::ControlType) {} // FIXME?
 
        void finish_capture (bool rec_monitors_input);
-       void clean_up_capture (struct tm&, time_t, bool abort) {} // FIXME?
        void transport_stopped (struct tm&, time_t, bool abort);
 
        struct CaptureInfo {
@@ -162,18 +155,11 @@ class MidiDiskstream : public Diskstream
        void init (Diskstream::Flag);
 
        int use_new_write_source (uint32_t n=0);
-       int use_new_fade_source (uint32_t n=0) { return 0; } // FIXME?
 
        int find_and_use_playlist (const string&);
 
        void allocate_temporary_buffers ();
 
-       int  create_input_port () { return 0; } // FIXME?
-       int  connect_input_port () { return 0; } // FIXME?
-       int  seek_unlocked (jack_nframes_t which_sample) { return 0; } // FIXME?
-
-       int ports_created () { return 0; } // FIXME?
-
        //bool realtime_set_speed (double, bool global_change);
        void non_realtime_set_speed ();
 
index ca760a5ad502a370e3410c071542be1667007baf..add253982f7aab324115806fb4bffc40e44b0bd8 100644 (file)
@@ -110,16 +110,15 @@ class Playlist : public Stateful, public StateManager {
        int set_state (const XMLNode&);
        XMLNode& get_template ();
 
-       sigc::signal<void,Region *> RegionAdded;
-       sigc::signal<void,Region *> RegionRemoved;
-
+       sigc::signal<void,Region *>       RegionAdded;
+       sigc::signal<void,Region *>       RegionRemoved;
        sigc::signal<void,Playlist*,bool> InUse;
-       sigc::signal<void>            Modified;
-       sigc::signal<void>            NameChanged;
-       sigc::signal<void>            LengthChanged;
-       sigc::signal<void>            LayeringChanged;
-       sigc::signal<void,Playlist *> GoingAway;
-       sigc::signal<void>            StatePushed;
+       sigc::signal<void>                Modified;
+       sigc::signal<void>                NameChanged;
+       sigc::signal<void>                LengthChanged;
+       sigc::signal<void>                LayeringChanged;
+       sigc::signal<void,Playlist *>     GoingAway;
+       sigc::signal<void>                StatePushed;
 
        static sigc::signal<void,Playlist*> PlaylistCreated;
 
index 68ac55df67a5fb804e1344d12035208d209952dd..a138f66042479143087b5e2ccdeb7d50275ec1a8 100644 (file)
@@ -145,6 +145,8 @@ class Region : public Stateful, public StateManager
        bool overlap_equivalent (const Region&) const;
        bool region_list_equivalent (const Region&) const;
        virtual bool source_equivalent (const Region&) const = 0;
+       
+       virtual bool speed_mismatch (float) const = 0;
 
        /*virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, 
                                        float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, 
index 7bd24b96cc6d54b5c2a428310c4ddb566f8027fc..dd8ec4806af0f9785fc91fccb1ec2615fdd69fb5 100644 (file)
@@ -938,7 +938,7 @@ class Session : public sigc::trackable, public Stateful
        /* buffers for gain and pan */
 
        gain_t* gain_automation_buffer () const { return _gain_automation_buffer; }
-       pan_t** pan_automation_buffer() const { return _pan_automation_buffer; }
+       pan_t** pan_automation_buffer () const  { return _pan_automation_buffer; }
 
        /* buffers for conversion */
        enum RunContext {
index a3345cf15a4674e91b8b3fce5a6a5246eb340b82..5f6ce0501625e729203ddb9584d54e95b993b79c 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000-2003 Paul Davis 
+    Copyright (C) 2000-2006 Paul Davis 
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -14,8 +14,6 @@
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-    $Id: diskstream.cc 567 2006-06-07 14:54:12Z trutkin $
 */
 
 #include <fstream>
@@ -23,6 +21,7 @@
 #include <unistd.h>
 #include <cmath>
 #include <cerrno>
+#include <cassert>
 #include <string>
 #include <climits>
 #include <fcntl.h>
@@ -57,10 +56,14 @@ using namespace PBD;
 
 sigc::signal<void,list<AudioFileSource*>*> AudioDiskstream::DeleteSources;
 
+size_t  AudioDiskstream::_working_buffers_size = 0;
+Sample* AudioDiskstream::_mixdown_buffer       = 0;
+gain_t* AudioDiskstream::_gain_buffer          = 0;
+char*   AudioDiskstream::_conversion_buffer    = 0;
+
 AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream::Flag flag)
        : Diskstream(sess, name, flag)
        , deprecated_io_node(NULL)
-       , _playlist(NULL)
 {
        /* prevent any write sources from being created */
 
@@ -77,7 +80,6 @@ AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream:
 AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
        : Diskstream(sess, node)
        , deprecated_io_node(NULL)
-       , _playlist(NULL)
 {
        in_set_state = true;
        init (Recordable);
@@ -178,25 +180,33 @@ AudioDiskstream::~AudioDiskstream ()
 {
        Glib::Mutex::Lock lm (state_lock);
 
-       if (_playlist)
-               _playlist->unref ();
-
-       for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+       for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan)
                destroy_channel((*chan));
-       }
        
        channels.clear();
 }
 
 void
-AudioDiskstream::handle_input_change (IOChange change, void *src)
+AudioDiskstream::allocate_working_buffers()
 {
-       Glib::Mutex::Lock lm (state_lock);
+       assert(disk_io_frames() > 0);
 
-       if (!(input_change_pending & change)) {
-               input_change_pending = IOChange (input_change_pending|change);
-               _session.request_input_change_handling ();
-       }
+       _working_buffers_size = disk_io_frames();
+       _mixdown_buffer       = new Sample[_working_buffers_size];
+       _gain_buffer          = new gain_t[_working_buffers_size];
+       _conversion_buffer    = new char[_working_buffers_size * 4];
+}
+
+void
+AudioDiskstream::free_working_buffers()
+{
+       delete _mixdown_buffer;
+       delete _gain_buffer;
+       delete _conversion_buffer;
+       _working_buffers_size = 0;
+       _mixdown_buffer       = 0;
+       _gain_buffer          = 0;
+       _conversion_buffer    = 0;
 }
 
 void
@@ -312,40 +322,7 @@ AudioDiskstream::use_playlist (Playlist* playlist)
 {
        assert(dynamic_cast<AudioPlaylist*>(playlist));
 
-       {
-               Glib::Mutex::Lock lm (state_lock);
-
-               if (playlist == _playlist) {
-                       return 0;
-               }
-
-               plstate_connection.disconnect();
-               plmod_connection.disconnect ();
-               plgone_connection.disconnect ();
-
-               if (_playlist) {
-                       _playlist->unref();
-               }
-                       
-               _playlist = dynamic_cast<AudioPlaylist*>(playlist);
-               _playlist->ref();
-
-               if (!in_set_state && recordable()) {
-                       reset_write_sources (false);
-               }
-               
-               plstate_connection = _playlist->StateChanged.connect (mem_fun (*this, &AudioDiskstream::playlist_changed));
-               plmod_connection = _playlist->Modified.connect (mem_fun (*this, &AudioDiskstream::playlist_modified));
-               plgone_connection = _playlist->GoingAway.connect (mem_fun (*this, &AudioDiskstream::playlist_deleted));
-       }
-
-       if (!overwrite_queued) {
-               _session.request_overwrite_buffer (this);
-               overwrite_queued = true;
-       }
-       
-       PlaylistChanged (); /* EMIT SIGNAL */
-       _session.set_dirty ();
+       Diskstream::use_playlist(playlist);
 
        return 0;
 }
@@ -377,6 +354,8 @@ AudioDiskstream::use_new_playlist ()
 int
 AudioDiskstream::use_copy_playlist ()
 {
+       assert(audio_playlist());
+
        if (destructive()) {
                return 0;
        }
@@ -391,7 +370,7 @@ AudioDiskstream::use_copy_playlist ()
 
        newname = Playlist::bump_name (_playlist->name(), _session);
        
-       if ((playlist  = new AudioPlaylist (*_playlist, newname)) != 0) {
+       if ((playlist  = new AudioPlaylist (*audio_playlist(), newname)) != 0) {
                playlist->set_orig_diskstream_id (id());
                return use_playlist (playlist);
        } else { 
@@ -399,19 +378,6 @@ AudioDiskstream::use_copy_playlist ()
        }
 }
 
-
-void
-AudioDiskstream::playlist_deleted (Playlist* pl)
-{
-       /* this catches an ordering issue with session destruction. playlists 
-          are destroyed before diskstreams. we have to invalidate any handles
-          we have to the playlist.
-       */
-
-       _playlist = 0;
-}
-
-
 void
 AudioDiskstream::setup_destructive_playlist ()
 {
@@ -460,36 +426,6 @@ AudioDiskstream::use_destructive_playlist ()
        /* the source list will never be reset for a destructive track */
 }
 
-void
-AudioDiskstream::set_io (IO& io)
-{
-       _io = &io;
-       set_align_style_from_io ();
-}
-
-void
-AudioDiskstream::non_realtime_set_speed ()
-{
-       if (_buffer_reallocation_required)
-       {
-               Glib::Mutex::Lock lm (state_lock);
-               allocate_temporary_buffers ();
-
-               _buffer_reallocation_required = false;
-       }
-
-       if (_seek_required) {
-               if (speed() != 1.0f || speed() != -1.0f) {
-                       seek ((jack_nframes_t) (_session.transport_frame() * (double) speed()), true);
-               }
-               else {
-                       seek (_session.transport_frame(), true);
-               }
-
-               _seek_required = false;
-       }
-}
-
 void
 AudioDiskstream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record)
 {
@@ -1054,9 +990,9 @@ AudioDiskstream::seek (jack_nframes_t frame, bool complete_refill)
        file_frame = frame;
 
        if (complete_refill) {
-               while ((ret = non_realtime_do_refill ()) > 0);
+               while ((ret = do_refill_with_alloc ()) > 0) ;
        } else {
-               ret = non_realtime_do_refill ();
+               ret = do_refill_with_alloc ();
        }
 
        return ret;
@@ -1148,7 +1084,7 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
 
                this_read = min(cnt,this_read);
 
-               if (_playlist->read (buf+offset, mixdown_buffer, gain_buffer, workbuf, start, this_read, channel) != this_read) {
+               if (audio_playlist()->read (buf+offset, mixdown_buffer, gain_buffer, workbuf, start, this_read, channel) != this_read) {
                        error << string_compose(_("AudioDiskstream %1: cannot read %2 from playlist at frame %3"), _id, this_read, 
                                         start) << endmsg;
                        return -1;
@@ -1182,14 +1118,27 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
 }
 
 int
-AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbuf)
+AudioDiskstream::do_refill_with_alloc()
+{
+       Sample* mix_buf  = new Sample[disk_io_chunk_frames];
+       float*  gain_buf = new float[disk_io_chunk_frames];
+       char*   work_buf = new char[disk_io_chunk_frames * 4];
+
+       int ret = _do_refill(mix_buf, gain_buf, work_buf);
+       
+       delete [] mix_buf;
+       delete [] gain_buf;
+       delete [] work_buf;
+
+       return ret;
+}
+
+int
+AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbuf)
 {
        int32_t ret = 0;
        jack_nframes_t to_read;
        RingBufferNPT<Sample>::rw_vector vector;
-       bool free_mixdown;
-       bool free_gain;
-       bool free_workbuf;
        bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f;
        jack_nframes_t total_space;
        jack_nframes_t zero_fill;
@@ -1197,6 +1146,10 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w
        ChannelList::iterator i;
        jack_nframes_t ts;
 
+       assert(mixdown_buffer);
+       assert(gain_buffer);
+       assert(workbuf);
+
        channels.front().playback_buf->get_write_vector (&vector);
        
        if ((total_space = vector.len[0] + vector.len[1]) == 0) {
@@ -1303,33 +1256,6 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w
                        zero_fill = 0;
                }
        }
-
-       /* Please note: the code to allocate buffers isn't run
-          during normal butler thread operation. Its there
-          for other times when we need to call do_refill()
-          from somewhere other than the butler thread.
-       */
-
-       if (mixdown_buffer == 0) {
-               mixdown_buffer = new Sample[disk_io_chunk_frames];
-               free_mixdown = true;
-       } else {
-               free_mixdown = false;
-       }
-
-       if (gain_buffer == 0) {
-               gain_buffer = new float[disk_io_chunk_frames];
-               free_gain = true;
-       } else {
-               free_gain = false;
-       }
-
-       if (workbuf == 0) {
-               workbuf = new char[disk_io_chunk_frames * 4];
-               free_workbuf = true;
-       } else {
-               free_workbuf = false;
-       }
        
        jack_nframes_t file_frame_tmp = 0;
 
@@ -1398,22 +1324,15 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w
        file_frame = file_frame_tmp;
 
   out:
-       if (free_mixdown) {
-               delete [] mixdown_buffer;
-       }
-       if (free_gain) {
-               delete [] gain_buffer;
-       }
-       if (free_workbuf) {
-               delete [] workbuf;
-       }
 
        return ret;
 }      
 
 int
-AudioDiskstream::do_flush (char * workbuf, bool force_flush)
+AudioDiskstream::do_flush (Session::RunContext context, bool force_flush)
 {
+       char* workbuf = _session.conversion_buffer(context);
+
        uint32_t to_write;
        int32_t ret = 0;
        RingBufferNPT<Sample>::rw_vector vector;
@@ -1570,7 +1489,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
        */
 
        while (more_work && !err) {
-               switch (do_flush ( _session.conversion_buffer(Session::TransportContext), true)) {
+               switch (do_flush (Session::TransportContext, true)) {
                case 0:
                        more_work = false;
                        break;
index 4e2bec9850ab444f3e1deb1d5e7a6072dc570c7c..9fc2ded0ce5893e645df0be5f8b245e096b0acc9 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000-2003 Paul Davis 
+    Copyright (C) 2000-2006 Paul Davis 
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -55,7 +55,7 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-jack_nframes_t Diskstream::disk_io_chunk_frames;
+jack_nframes_t Diskstream::disk_io_chunk_frames = 0;
 
 sigc::signal<void,Diskstream*>    Diskstream::DiskstreamCreated;
 //sigc::signal<void,list<AudioFileSource*>*> Diskstream::DeleteSources;
@@ -65,13 +65,14 @@ sigc::signal<void>                Diskstream::DiskUnderrun;
 Diskstream::Diskstream (Session &sess, const string &name, Flag flag)
        : _name (name)
        , _session (sess)
+       , _playlist(NULL)
 {
        init (flag);
 }
        
 Diskstream::Diskstream (Session& sess, const XMLNode& node)
        : _session (sess)
-       
+       , _playlist(NULL)
 {
        init (Recordable);
 }
@@ -113,37 +114,28 @@ Diskstream::init (Flag f)
        _read_data_count = 0;
        _write_data_count = 0;
 
-       /* there are no channels at this point, so these
-          two calls just get speed_buffer_size and wrap_buffer
-          size setup without duplicating their code.
-       */
-
-       //set_block_size (_session.get_block_size());
-       //allocate_temporary_buffers ();
-
        pending_overwrite = false;
        overwrite_frame = 0;
        overwrite_queued = false;
        input_change_pending = NoChange;
 
-       //add_channel ();
-       _n_channels = 0;//1;
+       _n_channels = 0;
 }
 
 Diskstream::~Diskstream ()
 {
-       // Taken by child.. assure lock?
+       // Taken by derived class destrctors.. assure lock?
        //Glib::Mutex::Lock lm (state_lock);
 
-       //if (_playlist) {
-       //      _playlist->unref ();
-       //}
+       if (_playlist)
+               _playlist->unref ();
+}
 
-       //for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
-       //      destroy_channel((*chan));
-       //}
-       
-       //channels.clear();
+void
+Diskstream::set_io (IO& io)
+{
+       _io = &io;
+       set_align_style_from_io ();
 }
 
 void
@@ -157,6 +149,29 @@ Diskstream::handle_input_change (IOChange change, void *src)
        }
 }
 
+void
+Diskstream::non_realtime_set_speed ()
+{
+       if (_buffer_reallocation_required)
+       {
+               Glib::Mutex::Lock lm (state_lock);
+               allocate_temporary_buffers ();
+
+               _buffer_reallocation_required = false;
+       }
+
+       if (_seek_required) {
+               if (speed() != 1.0f || speed() != -1.0f) {
+                       seek ((jack_nframes_t) (_session.transport_frame() * (double) speed()), true);
+               }
+               else {
+                       seek (_session.transport_frame(), true);
+               }
+
+               _seek_required = false;
+       }
+}
+
 bool
 Diskstream::realtime_set_speed (double sp, bool global)
 {
@@ -223,7 +238,6 @@ Diskstream::set_align_style (AlignStyle a)
                return;
        }
 
-
        if (a != _alignment_style) {
                _alignment_style = a;
                AlignmentStyleChanged ();
@@ -287,6 +301,47 @@ Diskstream::set_speed (double sp)
        playlist_modified();
 }
 
+int
+Diskstream::use_playlist (Playlist* playlist)
+{
+       {
+               Glib::Mutex::Lock lm (state_lock);
+
+               if (playlist == _playlist) {
+                       return 0;
+               }
+
+               plstate_connection.disconnect();
+               plmod_connection.disconnect ();
+               plgone_connection.disconnect ();
+
+               if (_playlist) {
+                       _playlist->unref();
+               }
+                       
+               _playlist = playlist;
+               _playlist->ref();
+
+               if (!in_set_state && recordable()) {
+                       reset_write_sources (false);
+               }
+               
+               plstate_connection = _playlist->StateChanged.connect (mem_fun (*this, &Diskstream::playlist_changed));
+               plmod_connection = _playlist->Modified.connect (mem_fun (*this, &Diskstream::playlist_modified));
+               plgone_connection = _playlist->GoingAway.connect (mem_fun (*this, &Diskstream::playlist_deleted));
+       }
+
+       if (!overwrite_queued) {
+               _session.request_overwrite_buffer (this);
+               overwrite_queued = true;
+       }
+       
+       PlaylistChanged (); /* EMIT SIGNAL */
+       _session.set_dirty ();
+
+       return 0;
+}
+
 void
 Diskstream::playlist_changed (Change ignored)
 {
@@ -302,6 +357,17 @@ Diskstream::playlist_modified ()
        } 
 }
 
+void
+Diskstream::playlist_deleted (Playlist* pl)
+{
+       /* this catches an ordering issue with session destruction. playlists 
+          are destroyed before diskstreams. we have to invalidate any handles
+          we have to the playlist.
+       */
+
+       _playlist = 0;
+}
+
 int
 Diskstream::set_name (string str, void *src)
 {
index a5853136ea216f810292cd0e41e9a1a75224e9a0..4602fc8f67b725fa8292ee5a99a8b12bc9d7f0c4 100644 (file)
@@ -388,7 +388,7 @@ MidiDiskstream::read (RawMidi* buf, RawMidi* mixdown_buffer, char * workbuf, jac
 {
        return 0;
 }
-
+/*
 int
 MidiDiskstream::do_refill (RawMidi* mixdown_buffer, float* gain_buffer, char * workbuf)
 {
@@ -400,7 +400,7 @@ MidiDiskstream::do_flush (char * workbuf, bool force_flush)
 {
        return 0;
 }
-
+*/
 void
 MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture)
 {
index fec674b6714e1add793cb9ca78e962dbb85b393f..011d1d62374ca2ccca3bf07036037df5f958de38 100644 (file)
@@ -403,6 +403,8 @@ Session::~Session ()
        for (map<RunContext,char*>::iterator i = _conversion_buffers.begin(); i != _conversion_buffers.end(); ++i) {
                delete [] (i->second);
        }
+
+       AudioDiskstream::free_working_buffers();
        
 #undef TRACK_DESTRUCTION
 #ifdef TRACK_DESTRUCTION
@@ -2105,7 +2107,7 @@ void
 Session::add_diskstream (Diskstream* dstream)
 {
        /* need to do this in case we're rolling at the time, to prevent false underruns */
-       dstream->non_realtime_do_refill();
+       dstream->do_refill_with_alloc();
        
        { 
                Glib::RWLock::WriterLock lm (diskstream_lock);
index f0a2af0a83d146cdf72c16b884805020c78036c0..6509a783bb8ad8481050480cea09241087001c81 100644 (file)
@@ -170,11 +170,6 @@ Session::butler_thread_work ()
        bool disk_work_outstanding = false;
        DiskstreamList::iterator i;
 
-       butler_mixdown_buffer = new Sample[AudioDiskstream::disk_io_frames()];
-       butler_gain_buffer = new gain_t[AudioDiskstream::disk_io_frames()];
-       // this buffer is used for temp conversion purposes in filesources
-       char * conv_buffer = conversion_buffer(ButlerContext);
-       
        while (true) {
                pfd[0].fd = butler_request_pipe[0];
                pfd[0].events = POLLIN|POLLERR|POLLHUP;
@@ -256,16 +251,15 @@ Session::butler_thread_work ()
                Glib::RWLock::ReaderLock dsm (diskstream_lock);
                
                for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) {
-                       // cerr << "rah fondr " << (*i)->io()->name () << endl;
-                       AudioDiskstream* ads = dynamic_cast<AudioDiskstream*>(*i);
-                       if (!ads) continue; // FIXME
 
-                       switch (ads->do_refill (butler_mixdown_buffer, butler_gain_buffer, conv_buffer)) {
+                       Diskstream* const ds = *i;
+
+                       switch (ds->do_refill ()) {
                        case 0:
-                               bytes += ads->read_data_count();
+                               bytes += ds->read_data_count();
                                break;
                        case 1:
-                               bytes += ads->read_data_count();
+                               bytes += ds->read_data_count();
                                disk_work_outstanding = true;
                                break;
                                
@@ -302,7 +296,7 @@ Session::butler_thread_work ()
                for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) {
                        // cerr << "write behind for " << (*i)->name () << endl;
                        
-                       switch ((*i)->do_flush (conv_buffer)) {
+                       switch ((*i)->do_flush (Session::ButlerContext)) {
                        case 0:
                                bytes += (*i)->write_data_count();
                                break;
index 73ba3918738cb540b698d9ce34e22c10b846bb6f..0809aae6eb8dbe0aa11e53a717536adde4f874aa 100644 (file)
@@ -196,7 +196,8 @@ Session::first_stage_init (string fullpath, string snapshot_name)
        /* allocate conversion buffers */
        _conversion_buffers[ButlerContext] = new char[AudioDiskstream::disk_io_frames() * 4];
        _conversion_buffers[TransportContext] = new char[AudioDiskstream::disk_io_frames() * 4];
-       
+       AudioDiskstream::allocate_working_buffers();
+
        /* default short fade = 15ms */
 
        Crossfade::set_short_xfade_length ((jack_nframes_t) floor ((15.0 * frame_rate()) / 1000.0));