* bugfix from http://tracker.ardour.org/view.php?id=2155 thanks to kristian: fix...
[ardour.git] / gtk2_ardour / region_view.cc
index 4c63c891529911305549ca4131fbca69c52e58a1..4251df344c13fed53c85b5ee8bd587e26846018d 100644 (file)
@@ -15,7 +15,6 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id: regionview.cc 691 2006-07-23 12:03:19Z drobilla $
 */
 
 #include <cmath>
 #include <gtkmm.h>
 
 #include <gtkmm2ext/gtk_ui.h>
+#include <pbd/stacktrace.h>
 
 #include <ardour/playlist.h>
 #include <ardour/audioregion.h>
 #include <ardour/audiosource.h>
 #include <ardour/audio_diskstream.h>
 
+#include "ardour_ui.h"
 #include "streamview.h"
 #include "region_view.h"
+#include "automation_region_view.h"
 #include "route_time_axis.h"
 #include "simplerect.h"
 #include "simpleline.h"
@@ -57,28 +59,41 @@ static const int32_t sync_mark_width = 9;
 
 sigc::signal<void,RegionView*> RegionView::RegionViewGoingAway;
 
-RegionView::RegionView (ArdourCanvas::Group* parent, 
-                        TimeAxisView&        tv,
+RegionView::RegionView (ArdourCanvas::Group*              parent, 
+                        TimeAxisView&                     tv,
                         boost::shared_ptr<ARDOUR::Region> r,
-                        double               spu,
-                        Gdk::Color&          basic_color)
+                        double                            spu,
+                        Gdk::Color&                       basic_color)
        : TimeAxisViewItem (r->name(), *parent, tv, spu, basic_color, r->position(), r->length(),
                            TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText|
                                                          TimeAxisViewItem::ShowNameHighlight|
                                                          TimeAxisViewItem::ShowFrame))
          , _region (r)
          , sync_mark(0)
-         , no_wave_msg(0)
+         , sync_line(0)
          , editor(0)
          , current_visible_sync_position(0.0)
          , valid(false)
+         , _enable_display(false)
          , _pixel_width(1.0)
-         , _height(1.0)
          , in_destructor(false)
          , wait_for_data(false)
 {
 }
 
+RegionView::RegionView (const RegionView& other)
+       : TimeAxisViewItem (other)
+{
+       /* derived concrete type will call init () */
+
+       _region = other._region;
+       editor = 0;
+       current_visible_sync_position = other.current_visible_sync_position;
+       valid = false;
+       _enable_display = false;
+       _pixel_width = other._pixel_width;
+}
+
 RegionView::RegionView (ArdourCanvas::Group*         parent, 
                         TimeAxisView&                tv,
                         boost::shared_ptr<ARDOUR::Region> r,
@@ -88,12 +103,12 @@ RegionView::RegionView (ArdourCanvas::Group*         parent,
        : TimeAxisViewItem (r->name(), *parent, tv, spu, basic_color, r->position(), r->length(), visibility)
        , _region (r)
        , sync_mark(0)
-       , no_wave_msg(0)
+       , sync_line(0)
        , editor(0)
        , current_visible_sync_position(0.0)
        , valid(false)
+       , _enable_display(false)
        , _pixel_width(1.0)
-       , _height(1.0)
        , in_destructor(false)
        , wait_for_data(false)
 {
@@ -102,11 +117,14 @@ RegionView::RegionView (ArdourCanvas::Group*         parent,
 void
 RegionView::init (Gdk::Color& basic_color, bool wfd)
 {
-       editor        = 0;
-       valid         = true;
-       in_destructor = false;
-       _height       = 0;
-       wait_for_data = wfd;
+       valid           = true;
+       _enable_display = false;
+       in_destructor   = false;
+       wait_for_data   = wfd;
+       sync_mark     = 0;
+       sync_line     = 0;
+       sync_mark     = 0;
+       sync_line     = 0;
 
        compute_colors (basic_color);
 
@@ -116,27 +134,10 @@ RegionView::init (Gdk::Color& basic_color, bool wfd)
                name_text->set_data ("regionview", this);
        }
 
-       /* 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));
-       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();
+       if (wfd)
+               _enable_display = true;
 
-       reset_width_dependent_items ((double) _region->length() / samples_per_unit);
-
-       set_height (trackview.height);
-
-       region_muted ();
-       region_sync_changed ();
-       region_resized (BoundsChanged);
-       region_locked ();
+       set_y_position_and_height (0, trackview.height - 2);
 
        _region->StateChanged.connect (mem_fun(*this, &RegionView::region_changed));
 
@@ -145,8 +146,8 @@ RegionView::init (Gdk::Color& basic_color, bool wfd)
 
        set_colors ();
 
-       ColorChanged.connect (mem_fun (*this, &RegionView::color_handler));
-
+       ColorsChanged.connect (mem_fun (*this, &RegionView::color_handler));
+       // set_pango_fontsize();
        /* XXX sync mark drag? */
 }
 
@@ -154,8 +155,6 @@ RegionView::~RegionView ()
 {
        in_destructor = true;
 
-       RegionViewGoingAway (this); /* EMIT_SIGNAL */
-
        for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
                delete *g;
        }
@@ -206,9 +205,14 @@ RegionView::region_changed (Change what_changed)
        if (what_changed & Region::SyncOffsetChanged) {
                region_sync_changed ();
        }
+       /* 
+          this should not be needed now that only playlist can change layering
+       */
+       /*
        if (what_changed & Region::LayerChanged) {
                region_layered ();
        }
+       */
        if (what_changed & Region::LockChanged) {
                region_locked ();
        }
@@ -236,8 +240,6 @@ RegionView::region_resized (Change what_changed)
 
                unit_length = _region->length() / samples_per_unit;
                
-               reset_width_dependent_items (unit_length);
-               
                for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
 
                        (*i)->set_duration (unit_length);
@@ -251,6 +253,11 @@ RegionView::reset_width_dependent_items (double pixel_width)
 {
        TimeAxisViewItem::reset_width_dependent_items (pixel_width);
        _pixel_width = pixel_width;
+
+       /*for (AutomationChildren::iterator i = _automation_children.begin();
+                       i != _automation_children.end(); ++i) {
+               i->second->reset_width_dependent_items(pixel_width);
+       }*/
 }
 
 void
@@ -274,24 +281,12 @@ RegionView::region_opacity ()
        set_frame_color ();
 }
 
-void
-RegionView::raise ()
-{
-       _region->raise ();
-}
-
 void
 RegionView::raise_to_top ()
 {
        _region->raise_to_top ();
 }
 
-void
-RegionView::lower ()
-{
-       _region->lower ();
-}
-
 void
 RegionView::lower_to_bottom ()
 {
@@ -299,7 +294,7 @@ RegionView::lower_to_bottom ()
 }
 
 bool
-RegionView::set_position (jack_nframes_t pos, void* src, double* ignored)
+RegionView::set_position (nframes_t pos, void* src, double* ignored)
 {
        double delta;
        bool ret;
@@ -316,6 +311,11 @@ RegionView::set_position (jack_nframes_t pos, void* src, double* ignored)
                for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
                        (*i)->group->move (delta, 0.0);
                }
+       
+               for (AutomationChildren::iterator i = _automation_children.begin();
+                               i != _automation_children.end(); ++i) {
+                       i->second->get_canvas_group()->move(delta, 0.0);
+               }
        }
 
        return ret;
@@ -335,7 +335,7 @@ RegionView::set_samples_per_unit (gdouble spu)
 }
 
 bool
-RegionView::set_duration (jack_nframes_t frames, void *src)
+RegionView::set_duration (nframes_t frames, void *src)
 {
        if (!TimeAxisViewItem::set_duration (frames, src)) {
                return false;
@@ -361,6 +361,7 @@ RegionView::set_colors ()
        
        if (sync_mark) {
                sync_mark->property_fill_color_rgba() = fill_color;
+               sync_line->property_fill_color_rgba() = fill_color;
        }
 }
 
@@ -368,14 +369,26 @@ void
 RegionView::set_frame_color ()
 {
        if (_region->opaque()) {
-               fill_opacity = 180;
+               fill_opacity = 130;
        } else {
-               fill_opacity = 100;
+               fill_opacity = 60;
        }
 
        TimeAxisViewItem::set_frame_color ();
 }
 
+void
+RegionView::fake_set_opaque (bool yn)
+{
+       if (yn) {
+               fill_opacity = 130;
+       } else {
+               fill_opacity = 60;
+       }
+       
+       set_frame_color ();
+}
+
 void
 RegionView::hide_region_editor()
 {
@@ -384,42 +397,70 @@ RegionView::hide_region_editor()
        }
 }
 
-void
-RegionView::region_renamed ()
+Glib::ustring
+RegionView::make_name () const
 {
-       string str;
+       Glib::ustring str;
+
+       // XXX nice to have some good icons for this
 
        if (_region->locked()) {
                str += '>';
                str += _region->name();
                str += '<';
+       } else if (_region->position_locked()) {
+               str += '{';
+               str += _region->name();
+               str += '}';
        } else {
                str = _region->name();
        }
 
-       if (_region->speed_mismatch (trackview.session().frame_rate())) {
-               str = string ("*") + str;
-       }
-
        if (_region->muted()) {
                str = string ("!") + str;
        }
 
+       return str;
+}
+
+void
+RegionView::region_renamed ()
+{
+       Glib::ustring str = make_name ();
+
        set_item_name (str, this);
        set_name_text (str);
+       reset_width_dependent_items (_pixel_width);
 }
 
 void
 RegionView::region_sync_changed ()
 {
-       if (sync_mark == 0) {
+       int sync_dir;
+       nframes_t sync_offset;
+
+       sync_offset = _region->sync_offset (sync_dir);
+
+       if (sync_offset == 0) {
+               /* no need for a sync mark */
+               if (sync_mark) {
+                       sync_mark->hide();
+                       sync_line->hide ();
+               }
                return;
        }
 
-       int sync_dir;
-       jack_nframes_t sync_offset;
+       if (!sync_mark) {
 
-       sync_offset = _region->sync_offset (sync_dir);
+               /* points set below */
+               
+               sync_mark =  new ArdourCanvas::Polygon (*group);
+               sync_mark->property_fill_color_rgba() = fill_color;
+
+               sync_line = new ArdourCanvas::Line (*group);
+               sync_line->property_fill_color_rgba() = fill_color;
+               sync_line->property_width_pixels() = 1;
+       }
 
        /* 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->
@@ -428,8 +469,9 @@ RegionView::region_sync_changed ()
        if (sync_offset == 0) {
 
                /* no sync mark - its the start of the region */
-
+               
                sync_mark->hide();
+               sync_line->hide ();
 
        } else {
 
@@ -438,6 +480,7 @@ RegionView::region_sync_changed ()
                        /* no sync mark - its out of the bounds of the region */
 
                        sync_mark->hide();
+                       sync_line->hide ();
 
                } else {
 
@@ -453,8 +496,14 @@ RegionView::region_sync_changed ()
                        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();
+                       sync_mark->show ();
+
+                       points.clear ();
+                       points.push_back (Gnome::Art::Point (offset, 0));
+                       points.push_back (Gnome::Art::Point (offset, trackview.height - NAME_HIGHLIGHT_SIZE));
 
+                       sync_line->property_points().set_value (points);
+                       sync_line->show ();
                }
        }
 }
@@ -462,7 +511,7 @@ RegionView::region_sync_changed ()
 void
 RegionView::move (double x_delta, double y_delta)
 {
-       if (_region->locked() || (x_delta == 0 && y_delta == 0)) {
+       if (!_region->can_move() || (x_delta == 0 && y_delta == 0)) {
                return;
        }
 
@@ -473,6 +522,22 @@ RegionView::move (double x_delta, double y_delta)
        for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
                (*i)->group->move (x_delta, 0.0);
        }
+               
+       for (AutomationChildren::iterator i = _automation_children.begin();
+                       i != _automation_children.end(); ++i) {
+               i->second->get_canvas_group()->move(x_delta, 0.0);
+       }
+}
+
+void
+RegionView::remove_ghost_in (TimeAxisView& tv)
+{
+       for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+               if (&(*i)->trackview == &tv) {
+                       delete *i;
+                       break;
+               }
+       }
 }
 
 void
@@ -496,3 +561,18 @@ RegionView::get_fill_color ()
        return fill_color;
 }
 
+void
+RegionView::set_height (double h)
+{
+       if (sync_line) {
+               Points points;
+               int sync_dir;
+               nframes_t sync_offset;
+               sync_offset = _region->sync_offset (sync_dir);
+               double offset = sync_offset / samples_per_unit;
+
+               points.push_back (Gnome::Art::Point (offset, 0));
+               points.push_back (Gnome::Art::Point (offset, h - NAME_HIGHLIGHT_SIZE));
+               sync_line->property_points().set_value (points);
+       }
+}