Add browse button to recent session dialogue. Fixes #3357.
[ardour.git] / gtk2_ardour / audio_region_view.cc
index 5a28a2f4847baace870812babb8db41158179a38..138601bf07044a29a8a35c1d1e2c12e30e9922ce 100644 (file)
@@ -27,7 +27,6 @@
 #include "ardour/playlist.h"
 #include "ardour/audioregion.h"
 #include "ardour/audiosource.h"
-#include "ardour/audio_diskstream.h"
 #include "ardour/profile.h"
 #include "ardour/session.h"
 
@@ -111,7 +110,6 @@ AudioRegionView::AudioRegionView (const AudioRegionView& other)
        , _amplitude_above_axis(1.0)
        , _flags(0)
        , fade_color(0)
-
 {
        Gdk::Color c;
        int r,g,b,a;
@@ -133,7 +131,6 @@ AudioRegionView::AudioRegionView (const AudioRegionView& other, boost::shared_pt
        , _amplitude_above_axis(1.0)
        , _flags(0)
        , fade_color(0)
-
 {
        Gdk::Color c;
        int r,g,b,a;
@@ -165,7 +162,8 @@ AudioRegionView::init (Gdk::Color const & basic_color, bool wfd)
                store_flags ();
        }
 
-       if (trackview.editor().new_regionviews_display_gain()) {
+       /* make envelope visible if it has anything interesting in it */
+       if (audio_region()->envelope()->size() > 2) {
                _flags |= EnvelopeVisible;
        }
 
@@ -181,7 +179,7 @@ AudioRegionView::init (Gdk::Color const & basic_color, bool wfd)
        fade_out_shape->property_fill_color_rgba() = fade_color;
        fade_out_shape->set_data ("regionview", this);
 
-       {
+       if (!_recregion) {
                uint32_t r,g,b,a;
                UINT_TO_RGBA(fill_color,&r,&g,&b,&a);
 
@@ -233,9 +231,15 @@ AudioRegionView::init (Gdk::Color const & basic_color, bool wfd)
        reset_width_dependent_items (_pixel_width);
 
        fade_in_shape->signal_event().connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_event), fade_in_shape, this));
-       fade_in_handle->signal_event().connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_handle_event), fade_in_handle, this));
+       if (fade_in_handle) {
+               fade_in_handle->signal_event().connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_in_handle_event), fade_in_handle, this));
+       }
+
        fade_out_shape->signal_event().connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_event), fade_out_shape, this));
-       fade_out_handle->signal_event().connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_handle_event), fade_out_handle, this));
+
+       if (fade_out_handle) {
+               fade_out_handle->signal_event().connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_fade_out_handle_event), fade_out_handle, this));
+       }
 
        set_colors ();
 
@@ -252,6 +256,14 @@ AudioRegionView::~AudioRegionView ()
                gnome_canvas_waveview_cache_destroy (*cache);
        }
 
+       for (vector<ScopedConnection*>::iterator i = _data_ready_connections.begin(); i != _data_ready_connections.end(); ++i) {
+               delete *i;
+       }
+
+       for (list<std::pair<nframes64_t, ArdourCanvas::SimpleLine*> >::iterator i = feature_lines.begin(); i != feature_lines.end(); ++i) {
+               delete ((*i).second);
+       }
+       
        /* all waveviews etc will be destroyed when the group is destroyed */
 
        delete gain_line;
@@ -290,6 +302,9 @@ AudioRegionView::region_changed (const PropertyChange& what_changed)
        if (what_changed.contains (ARDOUR::Properties::envelope_active)) {
                envelope_active_changed ();
        }
+       if (what_changed.contains (ARDOUR::Properties::valid_transients)) {
+               transients_changed ();
+       }
 }
 
 void
@@ -306,40 +321,36 @@ AudioRegionView::fade_out_changed ()
 void
 AudioRegionView::fade_in_active_changed ()
 {
-       uint32_t r,g,b,a;
-       uint32_t col;
-       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+//     uint32_t r,g,b,a;
+//     uint32_t col;
+//     UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
 
        if (audio_region()->fade_in_active()) {
-               col = RGBA_TO_UINT(r,g,b,120);
-               fade_in_shape->property_fill_color_rgba() = col;
-               fade_in_shape->property_width_pixels() = 0;
-               fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,0);
+               fade_in_shape->property_fill_color_rgba() = RGBA_TO_UINT(45,45,45,90);                          // FIXME make a themeable colour
+               fade_in_shape->property_width_pixels() = 1;
+               fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(180,180,180,190);                   // FIXME make a themeable colour
        } else {
-               col = RGBA_TO_UINT(r,g,b,0);
-               fade_in_shape->property_fill_color_rgba() = col;
+               fade_in_shape->property_fill_color_rgba() = RGBA_TO_UINT(45,45,45,20);                          // FIXME make a themeable colour
                fade_in_shape->property_width_pixels() = 1;
-               fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,255);
+               fade_in_shape->property_outline_color_rgba() = RGBA_TO_UINT(45,45,45,150);                      // FIXME make a themeable colour
        }
 }
 
 void
 AudioRegionView::fade_out_active_changed ()
 {
-       uint32_t r,g,b,a;
-       uint32_t col;
-       UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+//     uint32_t r,g,b,a;
+//     uint32_t col;
+//     UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
 
        if (audio_region()->fade_out_active()) {
-               col = RGBA_TO_UINT(r,g,b,120);
-               fade_out_shape->property_fill_color_rgba() = col;
-               fade_out_shape->property_width_pixels() = 0;
-               fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,0);
+               fade_out_shape->property_fill_color_rgba() = RGBA_TO_UINT(45,45,45,90);                         // FIXME make a themeable colour
+               fade_out_shape->property_width_pixels() = 1;
+               fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(180,180,180,200);                  // FIXME make a themeable colour
        } else {
-               col = RGBA_TO_UINT(r,g,b,0);
-               fade_out_shape->property_fill_color_rgba() = col;
+               fade_out_shape->property_fill_color_rgba() = RGBA_TO_UINT(45,45,45,20);                         // FIXME make a themeable colour
                fade_out_shape->property_width_pixels() = 1;
-               fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(r,g,b,255);
+               fade_out_shape->property_outline_color_rgba() = RGBA_TO_UINT(45,45,45,200);                     // FIXME make a themeable colour
        }
 }
 
@@ -390,13 +401,26 @@ AudioRegionView::region_resized (const PropertyChange& what_changed)
                }
 
                for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
-                       if((agr = dynamic_cast<AudioGhostRegion*>(*i)) != 0) {
+                       if ((agr = dynamic_cast<AudioGhostRegion*>(*i)) != 0) {
 
                                for (vector<WaveView*>::iterator w = agr->waves.begin(); w != agr->waves.end(); ++w) {
                                        (*w)->property_region_start() = _region->start();
                                }
                        }
                }
+               
+               /* hide transient lines that extend beyond the region end */
+               
+               list<std::pair<nframes64_t, ArdourCanvas::SimpleLine*> >::iterator l;
+               
+               for (l = feature_lines.begin(); l != feature_lines.end(); ++l) {
+                       if ((*l).first > _region->length()- 1){
+                         (*l).second->hide();
+                       }
+                       else {
+                         (*l).second->show();
+                       }
+               }
        }
 }
 
@@ -427,6 +451,15 @@ AudioRegionView::reset_width_dependent_items (double pixel_width)
                }
        }
 
+       AnalysisFeatureList analysis_features = _region->transients();
+       AnalysisFeatureList::const_iterator i;
+       list<std::pair<nframes64_t, ArdourCanvas::SimpleLine*> >::iterator l;
+
+       for (i = analysis_features.begin(), l = feature_lines.begin(); i != analysis_features.end() && l != feature_lines.end(); ++i, ++l) {
+               (*l).second->property_x1() = trackview.editor().frame_to_pixel (*i);
+               (*l).second->property_x2() = trackview.editor().frame_to_pixel (*i);
+       }
+       
        reset_fade_shapes ();
 }
 
@@ -470,13 +503,10 @@ AudioRegionView::set_height (gdouble height)
 
        uint32_t wcnt = waves.size();
 
-       // FIXME: ick
-       height -= 2;
-
        for (uint32_t n = 0; n < wcnt; ++n) {
                gdouble ht;
 
-               if ((height) < NAME_HIGHLIGHT_THRESH) {
+               if (height < NAME_HIGHLIGHT_THRESH) {
                        ht = ((height - 2 * wcnt) / (double) wcnt);
                } else {
                        ht = (((height - 2 * wcnt) - NAME_HIGHLIGHT_SIZE) / (double) wcnt);
@@ -498,11 +528,18 @@ AudioRegionView::set_height (gdouble height)
                        }
                }
 
-               gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE));
+               gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE) - 2);
        }
 
        manage_zero_line ();
        reset_fade_shapes ();
+       
+       /* Update hights for any active feature lines */
+       list<std::pair<nframes64_t, ArdourCanvas::SimpleLine*> >::iterator l;
+
+       for (l = feature_lines.begin(); l != feature_lines.end(); ++l) {
+               (*l).second->property_y2() = _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1;
+       }       
 
        if (name_pixbuf) {
                name_pixbuf->raise_to_top();
@@ -585,7 +622,7 @@ AudioRegionView::reset_fade_in_shape_width (nframes_t width)
        float curve[npoints];
        audio_region()->fade_in()->curve().get_vector (0, audio_region()->fade_in()->back()->when, curve, npoints);
 
-       points = get_canvas_points ("fade in shape", npoints+3);
+       points = get_canvas_points ("fade in shape", npoints + 3);
 
        if (_height >= NAME_HIGHLIGHT_THRESH) {
                h = _height - NAME_HIGHLIGHT_SIZE;
@@ -619,7 +656,9 @@ AudioRegionView::reset_fade_in_shape_width (nframes_t width)
        delete points;
 
        /* ensure trim handle stays on top */
-       frame_handle_start->raise_to_top();
+       if (frame_handle_start) {
+               frame_handle_start->raise_to_top();
+       }
 }
 
 void
@@ -684,7 +723,7 @@ AudioRegionView::reset_fade_out_shape_width (nframes_t width)
 
        /* points *MUST* be in anti-clockwise order */
 
-       points = get_canvas_points ("fade out shape", npoints+3);
+       points = get_canvas_points ("fade out shape", npoints + 3);
 
        uint32_t pi, pc;
        double xdelta = pwidth/npoints;
@@ -710,7 +749,9 @@ AudioRegionView::reset_fade_out_shape_width (nframes_t width)
        delete points;
 
        /* ensure trim handle stays on top */
-       frame_handle_end->raise_to_top();
+       if (frame_handle_end) {
+               frame_handle_end->raise_to_top();
+       }
 }
 
 void
@@ -773,20 +814,6 @@ AudioRegionView::set_colors ()
        }
 }
 
-void
-AudioRegionView::show_region_editor ()
-{
-       if (editor == 0) {
-               editor = new AudioRegionEditor (trackview.session(), audio_region(), *this);
-               // GTK2FIX : how to ensure float without realizing
-               // editor->realize ();
-               // trackview.editor.ensure_float (*editor);
-       }
-
-       editor->present ();
-       editor->show_all();
-}
-
 void
 AudioRegionView::set_waveform_visible (bool yn)
 {
@@ -847,11 +874,11 @@ AudioRegionView::create_waves ()
        // cerr << "AudioRegionView::create_waves() called on " << this << endl;//DEBUG
        RouteTimeAxisView& atv (*(dynamic_cast<RouteTimeAxisView*>(&trackview))); // ick
 
-       if (!atv.get_diskstream()) {
+       if (!atv.track()) {
                return;
        }
 
-       ChanCount nchans = atv.get_diskstream()->n_channels();
+       ChanCount nchans = atv.track()->n_channels();
 
        // cerr << "creating waves for " << _region->name() << " with wfd = " << wait_for_data
        //              << " and channels = " << nchans.n_audio() << endl;
@@ -861,6 +888,16 @@ AudioRegionView::create_waves ()
                tmp_waves.push_back (0);
        }
 
+       for (vector<ScopedConnection*>::iterator i = _data_ready_connections.begin(); i != _data_ready_connections.end(); ++i) {
+               delete *i;
+       }
+
+       _data_ready_connections.clear ();
+
+       for (uint32_t i = 0; i < nchans.n_audio(); ++i) {
+               _data_ready_connections.push_back (0);
+       }
+
        for (uint32_t n = 0; n < nchans.n_audio(); ++n) {
 
                if (n >= audio_region()->n_channels()) {
@@ -872,7 +909,7 @@ AudioRegionView::create_waves ()
                // cerr << "\tchannel " << n << endl;
 
                if (wait_for_data) {
-                       if (audio_region()->audio_source(n)->peaks_ready (boost::bind (&AudioRegionView::peaks_ready_handler, this, n), data_ready_connection, gui_context())) {
+                       if (audio_region()->audio_source(n)->peaks_ready (boost::bind (&AudioRegionView::peaks_ready_handler, this, n), &_data_ready_connections[n], gui_context())) {
                                // cerr << "\tData is ready\n";
                                create_one_wave (n, true);
                        } else {
@@ -894,7 +931,7 @@ AudioRegionView::create_one_wave (uint32_t which, bool /*direct*/)
 {
        //cerr << "AudioRegionView::create_one_wave() called which: " << which << " this: " << this << endl;//DEBUG
        RouteTimeAxisView& atv (*(dynamic_cast<RouteTimeAxisView*>(&trackview))); // ick
-       uint32_t nchans = atv.get_diskstream()->n_channels().n_audio();
+       uint32_t nchans = atv.track()->n_channels().n_audio();
        uint32_t n;
        uint32_t nwaves = std::min (nchans, audio_region()->n_channels());
        gdouble ht;
@@ -968,7 +1005,8 @@ AudioRegionView::create_one_wave (uint32_t which, bool /*direct*/)
                tmp_waves.clear ();
 
                /* all waves created, don't hook into peaks ready anymore */
-               data_ready_connection.disconnect ();
+               delete _data_ready_connections[which];
+               _data_ready_connections[which] = 0;
 
 #if 0
                if (!zero_line) {
@@ -1163,7 +1201,7 @@ AudioRegionView::add_ghost (TimeAxisView& tv)
        AudioGhostRegion* ghost = new AudioGhostRegion (tv, trackview, unit_position);
        uint32_t nchans;
 
-       nchans = rtv->get_diskstream()->n_channels().n_audio();
+       nchans = rtv->track()->n_channels().n_audio();
 
        for (uint32_t n = 0; n < nchans; ++n) {
 
@@ -1198,7 +1236,7 @@ AudioRegionView::add_ghost (TimeAxisView& tv)
 }
 
 void
-AudioRegionView::entered ()
+AudioRegionView::entered (bool internal_editing)
 {
        if (gain_line && _flags & EnvelopeVisible) {
                gain_line->show_all_control_points ();
@@ -1208,7 +1246,7 @@ AudioRegionView::entered ()
        UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
        a=255;
 
-       if (fade_in_handle) {
+       if (fade_in_handle && !internal_editing) {
                fade_in_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
                fade_out_handle->property_fill_color_rgba() = RGBA_TO_UINT(r,g,b,a);
        }
@@ -1371,6 +1409,88 @@ AudioRegionView::update_coverage_frames (LayerDisplay d)
 {
        RegionView::update_coverage_frames (d);
 
-       fade_in_handle->raise_to_top ();
-       fade_out_handle->raise_to_top ();
+       if (fade_in_handle) {
+               fade_in_handle->raise_to_top ();
+               fade_out_handle->raise_to_top ();
+       }
+}
+
+void
+AudioRegionView::show_region_editor ()
+{
+       if (editor == 0) {
+               editor = new AudioRegionEditor (trackview.session(), audio_region());
+       }
+
+       editor->present ();
+       editor->show_all();
+}
+
+void
+AudioRegionView::transients_changed ()
+{
+       AnalysisFeatureList analysis_features = _region->transients();
+
+       while (feature_lines.size() < analysis_features.size()) {
+               ArdourCanvas::SimpleLine* l = new ArdourCanvas::SimpleLine (*group);
+               l->property_color_rgba() = (guint) ARDOUR_UI::config()->canvasvar_ZeroLine.get();
+               feature_lines.push_back (make_pair(0, l));
+       }
+
+       while (feature_lines.size() > analysis_features.size()) {
+               ArdourCanvas::SimpleLine *line = feature_lines.back().second;
+               feature_lines.pop_back ();
+               delete line;
+       }
+
+       AnalysisFeatureList::const_iterator i;
+       list<std::pair<nframes64_t, ArdourCanvas::SimpleLine*> >::iterator l;
+
+       for (i = analysis_features.begin(), l = feature_lines.begin(); i != analysis_features.end() && l != feature_lines.end(); ++i, ++l) {
+               (*l).first = *i;
+               (*l).second->property_x1() = trackview.editor().frame_to_pixel (*i);
+               (*l).second->property_x2() = trackview.editor().frame_to_pixel (*i);            
+               (*l).second->property_y1() = 2;
+               (*l).second->property_y2() = _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1;
+               (*l).second->set_data("regionview", this);
+               (*l).second->show ();
+               (*l).second->raise_to_top ();
+               
+               (*l).second->signal_event().connect (sigc::bind (sigc::mem_fun (PublicEditor::instance(), &PublicEditor::canvas_feature_line_event), (*l).second, this));
+       }
+}
+
+void
+AudioRegionView::update_transient(float old_pos, float new_pos)
+{
+       /* Find frame at old pos, calulate new frame then update region transients*/
+       list<std::pair<nframes64_t, ArdourCanvas::SimpleLine*> >::iterator l;
+
+       for (l = feature_lines.begin(); l != feature_lines.end(); ++l) {
+               /* Simple line x1 has been updated in drag so we compare to new_pos */
+               if (rint(new_pos) == rint((*l).second->property_x1())) {
+                   
+                   nframes64_t old_frame = (*l).first;
+                   nframes64_t new_frame = trackview.editor().pixel_to_frame (new_pos);
+
+                   _region->update_transient (old_frame, new_frame);
+                   
+                   break;
+               }
+       }
+}
+
+void
+AudioRegionView::remove_transient(float pos)
+{
+       /* Find frame at old pos, calulate new frame then update region transients*/
+       list<std::pair<nframes64_t, ArdourCanvas::SimpleLine*> >::iterator l;
+
+       for (l = feature_lines.begin(); l != feature_lines.end(); ++l) {
+               /* Simple line x1 has been updated in drag so we compare to new_pos */
+               if (rint(pos) == rint((*l).second->property_x1())) {
+                   _region->remove_transient ((*l).first);                 
+                   break;
+               }
+       }
 }