many pervasive changes primarily related to waveform drawing, particular content-dragging, colors, and more

This commit is contained in:
Paul Davis 2013-04-24 15:42:14 -04:00
parent b36e085001
commit 6f664c1f67
22 changed files with 393 additions and 278 deletions

View file

@ -42,6 +42,7 @@
#include "canvas/poly_line.h" #include "canvas/poly_line.h"
#include "canvas/line.h" #include "canvas/line.h"
#include "canvas/text.h" #include "canvas/text.h"
#include "canvas/debug.h"
#include "streamview.h" #include "streamview.h"
#include "audio_region_view.h" #include "audio_region_view.h"
@ -158,21 +159,25 @@ AudioRegionView::init (Gdk::Color const & basic_color, bool wfd)
create_waves (); create_waves ();
fade_in_shape = new ArdourCanvas::Polygon (group); fade_in_shape = new ArdourCanvas::Polygon (group);
CANVAS_DEBUG_NAME (fade_in_shape, string_compose ("fade in shape for %1", region()->name()));
fade_in_shape->set_fill_color (fade_color); fade_in_shape->set_fill_color (fade_color);
fade_in_shape->set_data ("regionview", this); fade_in_shape->set_data ("regionview", this);
fade_out_shape = new ArdourCanvas::Polygon (group); fade_out_shape = new ArdourCanvas::Polygon (group);
CANVAS_DEBUG_NAME (fade_out_shape, string_compose ("fade out shape for %1", region()->name()));
fade_out_shape->set_fill_color (fade_color); fade_out_shape->set_fill_color (fade_color);
fade_out_shape->set_data ("regionview", this); fade_out_shape->set_data ("regionview", this);
if (!_recregion) { if (!_recregion) {
fade_in_handle = new ArdourCanvas::Rectangle (group); fade_in_handle = new ArdourCanvas::Rectangle (group);
CANVAS_DEBUG_NAME (fade_in_handle, string_compose ("fade in handle for %1", region()->name()));
fade_in_handle->set_fill_color (UINT_RGBA_CHANGE_A (fill_color, 0)); fade_in_handle->set_fill_color (UINT_RGBA_CHANGE_A (fill_color, 0));
fade_in_handle->set_outline_color (RGBA_TO_UINT (0, 0, 0, 0)); fade_in_handle->set_outline_color (RGBA_TO_UINT (0, 0, 0, 0));
fade_in_handle->set_data ("regionview", this); fade_in_handle->set_data ("regionview", this);
fade_out_handle = new ArdourCanvas::Rectangle (group); fade_out_handle = new ArdourCanvas::Rectangle (group);
CANVAS_DEBUG_NAME (fade_out_handle, string_compose ("fade out handle for %1", region()->name()));
fade_out_handle->set_fill_color (UINT_RGBA_CHANGE_A (fill_color, 0)); fade_out_handle->set_fill_color (UINT_RGBA_CHANGE_A (fill_color, 0));
fade_out_handle->set_outline_color (RGBA_TO_UINT (0, 0, 0, 0)); fade_out_handle->set_outline_color (RGBA_TO_UINT (0, 0, 0, 0));
@ -229,6 +234,9 @@ AudioRegionView::init (Gdk::Color const & basic_color, bool wfd)
setup_waveform_shape (); setup_waveform_shape ();
setup_waveform_scale (); setup_waveform_scale ();
frame_handle_start->raise_to_top ();
frame_handle_end->raise_to_top ();
/* XXX sync mark drag? */ /* XXX sync mark drag? */
} }
@ -363,7 +371,6 @@ AudioRegionView::region_resized (const PropertyChange& what_changed)
for (uint32_t n = 0; n < waves.size(); ++n) { for (uint32_t n = 0; n < waves.size(); ++n) {
waves[n]->region_resized (); waves[n]->region_resized ();
waves[n]->set_region_start (region()->start ());
} }
for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
@ -371,7 +378,6 @@ AudioRegionView::region_resized (const PropertyChange& what_changed)
for (vector<WaveView*>::iterator w = agr->waves.begin(); w != agr->waves.end(); ++w) { for (vector<WaveView*>::iterator w = agr->waves.begin(); w != agr->waves.end(); ++w) {
(*w)->region_resized (); (*w)->region_resized ();
(*w)->set_region_start (region()->start ());
} }
} }
} }
@ -432,14 +438,7 @@ void
AudioRegionView::region_muted () AudioRegionView::region_muted ()
{ {
RegionView::region_muted(); RegionView::region_muted();
set_waveform_colors ();
for (uint32_t n=0; n < waves.size(); ++n) {
if (_region->muted()) {
waves[n]->set_outline_color (UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->get_canvasvar_WaveForm(), MUTED_ALPHA));
} else {
waves[n]->set_outline_color (ARDOUR_UI::config()->get_canvasvar_WaveForm());
}
}
} }
void void
@ -750,12 +749,14 @@ AudioRegionView::redraw_start_xfade_to (boost::shared_ptr<AudioRegion> ar, frame
if (!start_xfade_in) { if (!start_xfade_in) {
start_xfade_in = new ArdourCanvas::PolyLine (group); start_xfade_in = new ArdourCanvas::PolyLine (group);
CANVAS_DEBUG_NAME (start_xfade_in, string_compose ("xfade start in line for %1", region()->name()));
start_xfade_in->set_outline_color (ARDOUR_UI::config()->get_canvasvar_CrossfadeLine()); start_xfade_in->set_outline_color (ARDOUR_UI::config()->get_canvasvar_CrossfadeLine());
start_xfade_in->set_outline_width (1.5); start_xfade_in->set_outline_width (1.5);
} }
if (!start_xfade_out) { if (!start_xfade_out) {
start_xfade_out = new ArdourCanvas::PolyLine (group); start_xfade_out = new ArdourCanvas::PolyLine (group);
CANVAS_DEBUG_NAME (start_xfade_out, string_compose ("xfade start out line for %1", region()->name()));
uint32_t col = UINT_RGBA_CHANGE_A (ARDOUR_UI::config()->get_canvasvar_CrossfadeLine(), 128); uint32_t col = UINT_RGBA_CHANGE_A (ARDOUR_UI::config()->get_canvasvar_CrossfadeLine(), 128);
start_xfade_out->set_outline_color (col); start_xfade_out->set_outline_color (col);
start_xfade_out->set_outline_width (2.0); start_xfade_out->set_outline_width (2.0);
@ -763,6 +764,7 @@ AudioRegionView::redraw_start_xfade_to (boost::shared_ptr<AudioRegion> ar, frame
if (!start_xfade_rect) { if (!start_xfade_rect) {
start_xfade_rect = new ArdourCanvas::Rectangle (group); start_xfade_rect = new ArdourCanvas::Rectangle (group);
CANVAS_DEBUG_NAME (start_xfade_rect, string_compose ("xfade start rect for %1", region()->name()));
start_xfade_rect->set_fill (true); start_xfade_rect->set_fill (true);
start_xfade_rect->set_fill_color (ARDOUR_UI::config()->get_canvasvar_ActiveCrossfade()); start_xfade_rect->set_fill_color (ARDOUR_UI::config()->get_canvasvar_ActiveCrossfade());
start_xfade_rect->set_outline (false); start_xfade_rect->set_outline (false);
@ -775,7 +777,6 @@ AudioRegionView::redraw_start_xfade_to (boost::shared_ptr<AudioRegion> ar, frame
start_xfade_in->set (points); start_xfade_in->set (points);
start_xfade_in->show (); start_xfade_in->show ();
start_xfade_in->raise_to_top ();
/* fade out line */ /* fade out line */
@ -807,9 +808,6 @@ AudioRegionView::redraw_start_xfade_to (boost::shared_ptr<AudioRegion> ar, frame
start_xfade_out->set (ipoints); start_xfade_out->set (ipoints);
start_xfade_out->show (); start_xfade_out->show ();
start_xfade_out->raise_to_top ();
start_xfade_rect->raise_to_top (); //this needs to be topmost so the lines don't steal mouse focus
show_start_xfade(); show_start_xfade();
} }
@ -837,6 +835,7 @@ AudioRegionView::redraw_end_xfade_to (boost::shared_ptr<AudioRegion> ar, framecn
if (!end_xfade_in) { if (!end_xfade_in) {
end_xfade_in = new ArdourCanvas::PolyLine (group); end_xfade_in = new ArdourCanvas::PolyLine (group);
CANVAS_DEBUG_NAME (end_xfade_in, string_compose ("xfade end in line for %1", region()->name()));
uint32_t col UINT_RGBA_CHANGE_A (ARDOUR_UI::config()->get_canvasvar_CrossfadeLine(), 128); uint32_t col UINT_RGBA_CHANGE_A (ARDOUR_UI::config()->get_canvasvar_CrossfadeLine(), 128);
end_xfade_in->set_outline_color (col); end_xfade_in->set_outline_color (col);
end_xfade_in->set_outline_width (1.5); end_xfade_in->set_outline_width (1.5);
@ -844,12 +843,14 @@ AudioRegionView::redraw_end_xfade_to (boost::shared_ptr<AudioRegion> ar, framecn
if (!end_xfade_out) { if (!end_xfade_out) {
end_xfade_out = new ArdourCanvas::PolyLine (group); end_xfade_out = new ArdourCanvas::PolyLine (group);
CANVAS_DEBUG_NAME (end_xfade_out, string_compose ("xfade end out line for %1", region()->name()));
end_xfade_out->set_outline_color (ARDOUR_UI::config()->get_canvasvar_CrossfadeLine()); end_xfade_out->set_outline_color (ARDOUR_UI::config()->get_canvasvar_CrossfadeLine());
end_xfade_out->set_outline_width (2.0); end_xfade_out->set_outline_width (2.0);
} }
if (!end_xfade_rect) { if (!end_xfade_rect) {
end_xfade_rect = new ArdourCanvas::Rectangle (group); end_xfade_rect = new ArdourCanvas::Rectangle (group);
CANVAS_DEBUG_NAME (end_xfade_rect, string_compose ("xfade end rect for %1", region()->name()));
end_xfade_rect->set_fill (true); end_xfade_rect->set_fill (true);
end_xfade_rect->set_fill_color (ARDOUR_UI::config()->get_canvasvar_ActiveCrossfade()); end_xfade_rect->set_fill_color (ARDOUR_UI::config()->get_canvasvar_ActiveCrossfade());
end_xfade_rect->set_outline (0); end_xfade_rect->set_outline (0);
@ -1025,16 +1026,7 @@ AudioRegionView::set_colors ()
ARDOUR_UI::config()->get_canvasvar_GainLineInactive()); ARDOUR_UI::config()->get_canvasvar_GainLineInactive());
} }
for (uint32_t n=0; n < waves.size(); ++n) { set_waveform_colors ();
if (_region->muted()) {
waves[n]->set_outline_color (UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->get_canvasvar_WaveForm(), MUTED_ALPHA));
} else {
waves[n]->set_outline_color (ARDOUR_UI::config()->get_canvasvar_WaveForm());
}
waves[n]->set_clip_color (ARDOUR_UI::config()->get_canvasvar_WaveFormClip());
waves[n]->set_zero_color (ARDOUR_UI::config()->get_canvasvar_ZeroLine());
}
if (start_xfade_in) { if (start_xfade_in) {
start_xfade_in->set_outline_color (ARDOUR_UI::config()->get_canvasvar_CrossfadeLine()); start_xfade_in->set_outline_color (ARDOUR_UI::config()->get_canvasvar_CrossfadeLine());
@ -1181,9 +1173,10 @@ AudioRegionView::create_one_wave (uint32_t which, bool /*direct*/)
gdouble yoff = which * ht; gdouble yoff = which * ht;
WaveView *wave = new WaveView (group, audio_region ()); WaveView *wave = new WaveView (group, audio_region ());
CANVAS_DEBUG_NAME (wave, string_compose ("wave view for chn %1 of %2", which, get_item_name()));
wave->lower_to_bottom ();
wave->set_channel (which); wave->set_channel (which);
wave->set_x_position (0);
wave->set_y_position (yoff); wave->set_y_position (yoff);
wave->set_height (ht); wave->set_height (ht);
wave->set_samples_per_pixel (samples_per_pixel); wave->set_samples_per_pixel (samples_per_pixel);
@ -1201,8 +1194,6 @@ AudioRegionView::create_one_wave (uint32_t which, bool /*direct*/)
// CAIROCANVAS // CAIROCANVAS
// wave->property_zero_line() = true; // wave->property_zero_line() = true;
wave->set_region_start (_region->start());
switch (Config->get_waveform_shape()) { switch (Config->get_waveform_shape()) {
case Rectified: case Rectified:
wave->set_shape (WaveView::Rectified); wave->set_shape (WaveView::Rectified);
@ -1362,12 +1353,11 @@ AudioRegionView::add_ghost (TimeAxisView& tv)
} }
WaveView *wave = new WaveView (ghost->group, audio_region()); WaveView *wave = new WaveView (ghost->group, audio_region());
CANVAS_DEBUG_NAME (wave, string_compose ("ghost wave for %1", get_item_name()));
wave->set_channel (n); wave->set_channel (n);
wave->set_x_position (0);
wave->set_samples_per_pixel (samples_per_pixel); wave->set_samples_per_pixel (samples_per_pixel);
wave->set_amplitude_above_axis (_amplitude_above_axis); wave->set_amplitude_above_axis (_amplitude_above_axis);
wave->set_region_start (_region->start());
ghost->waves.push_back(wave); ghost->waves.push_back(wave);
} }
@ -1441,6 +1431,47 @@ AudioRegionView::color_handler ()
} }
void
AudioRegionView::set_waveform_colors ()
{
ArdourCanvas::Color fill, outline, clip, zero;
if (_selected) {
if (_region->muted()) {
outline = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->get_canvasvar_SelectedWaveForm(), MUTED_ALPHA);
} else {
outline = ARDOUR_UI::config()->get_canvasvar_SelectedWaveForm();
}
fill = ARDOUR_UI::config()->get_canvasvar_SelectedWaveFormFill();
} else {
if (_recregion) {
if (_region->muted()) {
outline = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->get_canvasvar_RecWaveForm(), MUTED_ALPHA);
} else {
outline = ARDOUR_UI::config()->get_canvasvar_RecWaveForm();
}
fill = ARDOUR_UI::config()->get_canvasvar_RecWaveFormFill();
} else {
if (_region->muted()) {
outline = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->get_canvasvar_WaveForm(), MUTED_ALPHA);
} else {
outline = ARDOUR_UI::config()->get_canvasvar_WaveForm();
}
fill = ARDOUR_UI::config()->get_canvasvar_WaveFormFill();
}
}
clip = ARDOUR_UI::config()->get_canvasvar_WaveFormClip();
zero = ARDOUR_UI::config()->get_canvasvar_ZeroLine();
for (vector<ArdourCanvas::WaveView*>::iterator w = waves.begin(); w != waves.end(); ++w) {
(*w)->set_outline_color (outline);
(*w)->set_fill_color (fill);
(*w)->set_clip_color (clip);
(*w)->set_zero_color (zero);
}
}
void void
AudioRegionView::set_frame_color () AudioRegionView::set_frame_color ()
{ {
@ -1456,40 +1487,7 @@ AudioRegionView::set_frame_color ()
TimeAxisViewItem::set_frame_color (); TimeAxisViewItem::set_frame_color ();
uint32_t wc; set_waveform_colors ();
uint32_t fc;
if (_selected) {
if (_region->muted()) {
wc = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->get_canvasvar_SelectedWaveForm(), MUTED_ALPHA);
} else {
wc = ARDOUR_UI::config()->get_canvasvar_SelectedWaveForm();
}
fc = ARDOUR_UI::config()->get_canvasvar_SelectedWaveFormFill();
} else {
if (_recregion) {
if (_region->muted()) {
wc = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->get_canvasvar_RecWaveForm(), MUTED_ALPHA);
} else {
wc = ARDOUR_UI::config()->get_canvasvar_RecWaveForm();
}
fc = ARDOUR_UI::config()->get_canvasvar_RecWaveFormFill();
} else {
if (_region->muted()) {
wc = UINT_RGBA_CHANGE_A(ARDOUR_UI::config()->get_canvasvar_WaveForm(), MUTED_ALPHA);
} else {
wc = ARDOUR_UI::config()->get_canvasvar_WaveForm();
}
fc = ARDOUR_UI::config()->get_canvasvar_WaveFormFill();
}
}
for (vector<ArdourCanvas::WaveView*>::iterator w = waves.begin(); w != waves.end(); ++w) {
(*w)->set_outline_color (wc);
if (!_region->muted()) {
(*w)->set_fill_color (fc);
}
}
} }
void void
@ -1555,6 +1553,7 @@ AudioRegionView::transients_changed ()
while (feature_lines.size() < analysis_features.size()) { while (feature_lines.size() < analysis_features.size()) {
ArdourCanvas::Line* canvas_item = new ArdourCanvas::Line(group); ArdourCanvas::Line* canvas_item = new ArdourCanvas::Line(group);
CANVAS_DEBUG_NAME (canvas_item, string_compose ("transient group for %1", region()->name()));
canvas_item->set (ArdourCanvas::Duple (-1.0, 2.0), canvas_item->set (ArdourCanvas::Duple (-1.0, 2.0),
ArdourCanvas::Duple (1.0, _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1)); ArdourCanvas::Duple (1.0, _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1));

View file

@ -189,6 +189,7 @@ class AudioRegionView : public RegionView
void peaks_ready_handler (uint32_t); void peaks_ready_handler (uint32_t);
void set_colors (); void set_colors ();
void set_waveform_colors ();
void compute_colors (Gdk::Color const &); void compute_colors (Gdk::Color const &);
void reset_width_dependent_items (double pixel_width); void reset_width_dependent_items (double pixel_width);
void set_frame_color (); void set_frame_color ();

View file

@ -1172,9 +1172,7 @@ CrossfadeEditor::make_waves (boost::shared_ptr<AudioRegion> region, WhichFade wh
waveview->set_outline_color (color); waveview->set_outline_color (color);
waveview->set_fill_color (color); waveview->set_fill_color (color);
if (which == In) { if (which != In) {
waveview->set_region_start (region->start());
} else {
waveview->set_region_start (region->start() + region->length() - xfade->length()); waveview->set_region_start (region->start() + region->length() - xfade->length());
} }

View file

@ -1830,6 +1830,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
TimeAxisView* tvp = &_primary->get_time_axis_view (); TimeAxisView* tvp = &_primary->get_time_axis_view ();
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp); RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result; pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
frameoffset_t frame_delta = 0;
if (tv && tv->is_track()) { if (tv && tv->is_track()) {
speed = tv->track()->speed(); speed = tv->track()->speed();
@ -1926,27 +1927,11 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
case ContentsTrim: case ContentsTrim:
{ {
bool swap_direction = false;
if (event && Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
swap_direction = true;
}
framecnt_t frame_delta = 0;
bool left_direction = false;
if (last_pointer_frame() > adjusted_current_frame(event)) {
left_direction = true;
}
if (left_direction) {
frame_delta = (last_pointer_frame() - adjusted_current_frame(event));
} else {
frame_delta = (adjusted_current_frame(event) - last_pointer_frame()); frame_delta = (adjusted_current_frame(event) - last_pointer_frame());
} // frame_delta = (last_pointer_frame() - adjusted_current_frame(event));
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) { for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
i->view->trim_contents (frame_delta, left_direction, swap_direction); i->view->move_contents (frame_delta);
} }
} }
break; break;
@ -1960,7 +1945,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
show_verbose_cursor_time ((framepos_t) (rv->region()->last_frame() / speed)); show_verbose_cursor_time ((framepos_t) (rv->region()->last_frame() / speed));
break; break;
case ContentsTrim: case ContentsTrim:
show_verbose_cursor_time (adjusted_current_frame (event)); // show_verbose_cursor_time (frame_delta);
break; break;
} }
} }

View file

@ -162,8 +162,9 @@ Editor::compute_current_bbt_points (framepos_t leftmost, framepos_t rightmost,
void void
Editor::hide_measures () Editor::hide_measures ()
{ {
if (tempo_lines) if (tempo_lines) {
tempo_lines->hide(); tempo_lines->hide();
}
} }
void void

View file

@ -21,6 +21,8 @@
#include "canvas/group.h" #include "canvas/group.h"
#include "canvas/rectangle.h" #include "canvas/rectangle.h"
#include "canvas/wave_view.h" #include "canvas/wave_view.h"
#include "canvas/debug.h"
#include "ardour_ui.h" #include "ardour_ui.h"
#include "automation_time_axis.h" #include "automation_time_axis.h"
#include "ghostregion.h" #include "ghostregion.h"
@ -41,9 +43,11 @@ GhostRegion::GhostRegion (ArdourCanvas::Group* parent, TimeAxisView& tv, TimeAxi
, source_trackview (source_tv) , source_trackview (source_tv)
{ {
group = new ArdourCanvas::Group (parent); group = new ArdourCanvas::Group (parent);
CANVAS_DEBUG_NAME (group, "ghost region group");
group->set_position (ArdourCanvas::Duple (initial_pos, 0)); group->set_position (ArdourCanvas::Duple (initial_pos, 0));
base_rect = new ArdourCanvas::Rectangle (group); base_rect = new ArdourCanvas::Rectangle (group);
CANVAS_DEBUG_NAME (base_rect, "ghost region rect");
base_rect->set_x0 (0); base_rect->set_x0 (0);
base_rect->set_y0 (0); base_rect->set_y0 (0);
base_rect->set_y1 (trackview.current_height()); base_rect->set_y1 (trackview.current_height());
@ -191,6 +195,7 @@ MidiGhostRegion::GhostEvent::GhostEvent (NoteBase* e, ArdourCanvas::Group* g)
: event (e) : event (e)
{ {
rect = new ArdourCanvas::Rectangle (g, ArdourCanvas::Rect (e->x0(), e->y0(), e->x1(), e->y1())); rect = new ArdourCanvas::Rectangle (g, ArdourCanvas::Rect (e->x0(), e->y0(), e->x1(), e->y1()));
CANVAS_DEBUG_NAME (rect, "ghost note rect");
} }
MidiGhostRegion::GhostEvent::~GhostEvent () MidiGhostRegion::GhostEvent::~GhostEvent ()

View file

@ -632,9 +632,11 @@ RegionView::region_sync_changed ()
/* points set below */ /* points set below */
sync_mark = new ArdourCanvas::Polygon (group); sync_mark = new ArdourCanvas::Polygon (group);
CANVAS_DEBUG_NAME (sync_mark, string_compose ("sync mark for %1", get_item_name()));
sync_mark->set_fill_color (RGBA_TO_UINT(0,255,0,255)); // FIXME make a themeable colour sync_mark->set_fill_color (RGBA_TO_UINT(0,255,0,255)); // FIXME make a themeable colour
sync_line = new ArdourCanvas::Line (group); sync_line = new ArdourCanvas::Line (group);
CANVAS_DEBUG_NAME (sync_line, string_compose ("sync mark for %1", get_item_name()));
sync_line->set_outline_color (RGBA_TO_UINT(0,255,0,255)); // FIXME make a themeable colour sync_line->set_outline_color (RGBA_TO_UINT(0,255,0,255)); // FIXME make a themeable colour
} }
@ -930,32 +932,12 @@ RegionView::thaw_after_trim ()
void void
RegionView::trim_contents (framepos_t frame_delta, bool left_direction, bool swap_direction) RegionView::move_contents (frameoffset_t distance)
{ {
if (_region->locked()) { if (_region->locked()) {
return; return;
} }
_region->move_start (distance);
framepos_t new_bound;
RouteTimeAxisView& rtv = dynamic_cast<RouteTimeAxisView&> (trackview);
double const speed = rtv.track()->speed ();
if (left_direction) {
if (swap_direction) {
new_bound = (framepos_t) (_region->position() / speed) + frame_delta;
} else {
new_bound = (framepos_t) (_region->position() / speed) - frame_delta;
}
} else {
if (swap_direction) {
new_bound = (framepos_t) (_region->position() / speed) - frame_delta;
} else {
new_bound = (framepos_t) (_region->position() / speed) + frame_delta;
}
}
_region->trim_start ((framepos_t) (new_bound * speed));
region_changed (PropertyChange (ARDOUR::Properties::start)); region_changed (PropertyChange (ARDOUR::Properties::start));
} }

View file

@ -113,7 +113,7 @@ class RegionView : public TimeAxisViewItem
virtual void trim_front_ending () {} virtual void trim_front_ending () {}
bool trim_end (framepos_t, bool); bool trim_end (framepos_t, bool);
void trim_contents (framepos_t, bool, bool); void move_contents (ARDOUR::frameoffset_t);
virtual void thaw_after_trim (); virtual void thaw_after_trim ();
void set_silent_frames (const ARDOUR::AudioIntervalResult&, double threshold); void set_silent_frames (const ARDOUR::AudioIntervalResult&, double threshold);

View file

@ -71,8 +71,10 @@ StreamView::StreamView (RouteTimeAxisView& tv)
canvas_rect->set (ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, tv.current_height ())); canvas_rect->set (ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, tv.current_height ()));
canvas_rect->raise(1); // raise above tempo lines canvas_rect->raise(1); // raise above tempo lines
canvas_rect->set_outline_what (0x2 | 0x8); canvas_rect->set_outline_what (ArdourCanvas::Rectangle::What (ArdourCanvas::Rectangle::TOP | ArdourCanvas::Rectangle::BOTTOM));
canvas_rect->set_outline_color (RGBA_TO_UINT (0, 0, 0, 255)); canvas_rect->set_outline_color (RGBA_TO_UINT (0, 0, 0, 255));
canvas_rect->set_fill_color (RGBA_TO_UINT (1.0, 0, 0, 255));
canvas_rect->set_fill (true);
canvas_rect->Event.connect (sigc::bind ( canvas_rect->Event.connect (sigc::bind (
sigc::mem_fun (_trackview.editor(), &PublicEditor::canvas_stream_view_event), sigc::mem_fun (_trackview.editor(), &PublicEditor::canvas_stream_view_event),

View file

@ -47,17 +47,13 @@ TempoLines::tempo_map_changed()
void void
TempoLines::show () TempoLines::show ()
{ {
for (Lines::iterator i = _lines.begin(); i != _lines.end(); ++i) { _group->show ();
(*i)->show();
}
} }
void void
TempoLines::hide () TempoLines::hide ()
{ {
for (Lines::iterator i = _lines.begin(); i != _lines.end(); ++i) { _group->hide ();
(*i)->hide();
}
} }
void void
@ -111,6 +107,8 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
line->reparent (_group); line->reparent (_group);
} else { } else {
line = new ArdourCanvas::Line (_group); line = new ArdourCanvas::Line (_group);
CANVAS_DEBUG_NAME (line, "tempo measure line");
line->set_ignore_events (true);
} }
line->set_x0 (xpos); line->set_x0 (xpos);

View file

@ -32,6 +32,7 @@
#include <gtkmm2ext/selector.h> #include <gtkmm2ext/selector.h>
#include "canvas/rectangle.h" #include "canvas/rectangle.h"
#include "canvas/debug.h"
#include "ardour_ui.h" #include "ardour_ui.h"
#include "ardour_dialog.h" #include "ardour_dialog.h"
@ -940,13 +941,16 @@ TimeAxisView::get_selection_rect (uint32_t id)
rect = new SelectionRect; rect = new SelectionRect;
rect->rect = new ArdourCanvas::Rectangle (selection_group); rect->rect = new ArdourCanvas::Rectangle (selection_group);
CANVAS_DEBUG_NAME (rect->rect, "selection rect");
rect->rect->set_outline_what (0); rect->rect->set_outline_what (0);
rect->rect->set_fill_color (ARDOUR_UI::config()->get_canvasvar_SelectionRect()); rect->rect->set_fill_color (ARDOUR_UI::config()->get_canvasvar_SelectionRect());
rect->start_trim = new ArdourCanvas::Rectangle (selection_group); rect->start_trim = new ArdourCanvas::Rectangle (selection_group);
CANVAS_DEBUG_NAME (rect->rect, "selection rect start trim");
rect->start_trim->set_outline_what (0); rect->start_trim->set_outline_what (0);
rect->end_trim = new ArdourCanvas::Rectangle (selection_group); rect->end_trim = new ArdourCanvas::Rectangle (selection_group);
CANVAS_DEBUG_NAME (rect->rect, "selection rect end trim");
rect->end_trim->set_outline_what (0); rect->end_trim->set_outline_what (0);
free_selection_rects.push_front (rect); free_selection_rects.push_front (rect);

View file

@ -138,6 +138,7 @@ TimeAxisViewItem::TimeAxisViewItem (const TimeAxisViewItem& other)
ArdourCanvas::Group* parent = other.group->parent(); ArdourCanvas::Group* parent = other.group->parent();
group = new ArdourCanvas::Group (parent); group = new ArdourCanvas::Group (parent);
CANVAS_DEBUG_NAME (group, string_compose ("TAVI group for %1", get_item_name()));
_selected = other._selected; _selected = other._selected;
@ -171,6 +172,7 @@ TimeAxisViewItem::init (const string& it_name, double fpp, Gdk::Color const & ba
} }
vestigial_frame = new ArdourCanvas::Rectangle (group, ArdourCanvas::Rect (0.0, 1.0, 2.0, trackview.current_height())); vestigial_frame = new ArdourCanvas::Rectangle (group, ArdourCanvas::Rect (0.0, 1.0, 2.0, trackview.current_height()));
CANVAS_DEBUG_NAME (vestigial_frame, string_compose ("vestigial frame for %1", get_item_name()));
vestigial_frame->hide (); vestigial_frame->hide ();
vestigial_frame->set_outline_color (ARDOUR_UI::config()->get_canvasvar_VestigialFrame()); vestigial_frame->set_outline_color (ARDOUR_UI::config()->get_canvasvar_VestigialFrame());
vestigial_frame->set_fill_color (ARDOUR_UI::config()->get_canvasvar_VestigialFrame()); vestigial_frame->set_fill_color (ARDOUR_UI::config()->get_canvasvar_VestigialFrame());
@ -180,6 +182,7 @@ TimeAxisViewItem::init (const string& it_name, double fpp, Gdk::Color const & ba
ArdourCanvas::Rect (0.0, 1.0, ArdourCanvas::Rect (0.0, 1.0,
trackview.editor().sample_to_pixel(duration), trackview.editor().sample_to_pixel(duration),
trackview.current_height())); trackview.current_height()));
CANVAS_DEBUG_NAME (frame, string_compose ("frame for %1", get_item_name()));
if (_recregion) { if (_recregion) {
frame->set_outline_color (ARDOUR_UI::config()->get_canvasvar_RecordingRect()); frame->set_outline_color (ARDOUR_UI::config()->get_canvasvar_RecordingRect());
@ -199,11 +202,13 @@ TimeAxisViewItem::init (const string& it_name, double fpp, Gdk::Color const & ba
ArdourCanvas::Rect (0.0, trackview.editor().sample_to_pixel(item_duration), ArdourCanvas::Rect (0.0, trackview.editor().sample_to_pixel(item_duration),
trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE, trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE,
trackview.current_height())); trackview.current_height()));
CANVAS_DEBUG_NAME (name_highlight, string_compose ("name highlight for %1", get_item_name()));
} else { } else {
name_highlight = new ArdourCanvas::Rectangle (group, name_highlight = new ArdourCanvas::Rectangle (group,
ArdourCanvas::Rect (1.0, trackview.editor().sample_to_pixel(item_duration) - 1, ArdourCanvas::Rect (1.0, trackview.editor().sample_to_pixel(item_duration) - 1,
trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE, trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE,
trackview.current_height())); trackview.current_height()));
CANVAS_DEBUG_NAME (name_highlight, string_compose ("name highlight for %1", get_item_name()));
} }
name_highlight->set_data ("timeaxisviewitem", this); name_highlight->set_data ("timeaxisviewitem", this);
@ -217,6 +222,7 @@ TimeAxisViewItem::init (const string& it_name, double fpp, Gdk::Color const & ba
if (visibility & ShowNameText) { if (visibility & ShowNameText) {
name_text = new ArdourCanvas::Text (group); name_text = new ArdourCanvas::Text (group);
CANVAS_DEBUG_NAME (name_text, string_compose ("name text for %1", get_item_name()));
name_text->set_position (ArdourCanvas::Duple (NAME_X_OFFSET, trackview.current_height() - NAME_Y_OFFSET)); name_text->set_position (ArdourCanvas::Duple (NAME_X_OFFSET, trackview.current_height() - NAME_Y_OFFSET));
name_text->set_font_description (NAME_FONT); name_text->set_font_description (NAME_FONT);
@ -230,9 +236,16 @@ TimeAxisViewItem::init (const string& it_name, double fpp, Gdk::Color const & ba
double width = TimeAxisViewItem::GRAB_HANDLE_WIDTH; double width = TimeAxisViewItem::GRAB_HANDLE_WIDTH;
frame_handle_start = new ArdourCanvas::Rectangle (group, ArdourCanvas::Rect (0.0, top, width, trackview.current_height())); frame_handle_start = new ArdourCanvas::Rectangle (group, ArdourCanvas::Rect (0.0, top, width, trackview.current_height()));
frame_handle_start->set_outline_what (ArdourCanvas::Rectangle::What (0)); CANVAS_DEBUG_NAME (frame_handle_start, "TAVI frame handle start");
frame_handle_start->set_outline (false);
frame_handle_start->set_fill (false);
frame_handle_start->Event.connect (sigc::bind (sigc::mem_fun (*this, &TimeAxisViewItem::frame_handle_crossing), frame_handle_start));
frame_handle_end = new ArdourCanvas::Rectangle (group, ArdourCanvas::Rect (0.0, top, width, trackview.current_height())); frame_handle_end = new ArdourCanvas::Rectangle (group, ArdourCanvas::Rect (0.0, top, width, trackview.current_height()));
frame_handle_end->set_outline_what (ArdourCanvas::Rectangle::What (0)); CANVAS_DEBUG_NAME (frame_handle_end, "TAVI frame handle end");
frame_handle_end->set_outline (false);
frame_handle_end->set_fill (false);
frame_handle_end->Event.connect (sigc::bind (sigc::mem_fun (*this, &TimeAxisViewItem::frame_handle_crossing), frame_handle_end));
} else { } else {
frame_handle_start = frame_handle_end = 0; frame_handle_start = frame_handle_end = 0;
} }
@ -819,12 +832,28 @@ TimeAxisViewItem::set_trim_handle_colors()
frame_handle_start->set_fill_color (ARDOUR_UI::config()->get_canvasvar_TrimHandleLocked()); frame_handle_start->set_fill_color (ARDOUR_UI::config()->get_canvasvar_TrimHandleLocked());
frame_handle_end->set_fill_color (ARDOUR_UI::config()->get_canvasvar_TrimHandleLocked()); frame_handle_end->set_fill_color (ARDOUR_UI::config()->get_canvasvar_TrimHandleLocked());
} else { } else {
frame_handle_start->set_fill_color (RGBA_TO_UINT (1, 1, 1, 0)); //ARDOUR_UI::config()->get_canvasvar_TrimHandle(); frame_handle_start->set_fill_color (ARDOUR_UI::config()->get_canvasvar_TrimHandle());
frame_handle_end->set_fill_color (RGBA_TO_UINT (1, 1, 1, 0)); //ARDOUR_UI::config()->get_canvasvar_TrimHandle(); frame_handle_end->set_fill_color (ARDOUR_UI::config()->get_canvasvar_TrimHandle());
} }
} }
} }
bool
TimeAxisViewItem::frame_handle_crossing (GdkEvent* ev, ArdourCanvas::Rectangle* item)
{
switch (ev->type) {
case GDK_LEAVE_NOTIFY:
item->set_fill (false);
break;
case GDK_ENTER_NOTIFY:
item->set_fill (true);
break;
default:
break;
}
return false;
}
/** @return the frames per pixel */ /** @return the frames per pixel */
double double
TimeAxisViewItem::get_samples_per_pixel () const TimeAxisViewItem::get_samples_per_pixel () const
@ -901,6 +930,7 @@ TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
* the right-hand end of frame_handle_start and the left-hand * the right-hand end of frame_handle_start and the left-hand
* end of frame_handle_end, so disable the handles * end of frame_handle_end, so disable the handles
*/ */
frame_handle_start->hide(); frame_handle_start->hide();
frame_handle_end->hide(); frame_handle_end->hide();
} else { } else {

View file

@ -21,6 +21,7 @@
#define __gtk_ardour_time_axis_view_item_h__ #define __gtk_ardour_time_axis_view_item_h__
#include <string> #include <string>
#include <gdk/gdk.h>
#include <gdkmm/color.h> #include <gdkmm/color.h>
#include <pangomm/fontdescription.h> #include <pangomm/fontdescription.h>
#include "pbd/signals.h" #include "pbd/signals.h"
@ -244,6 +245,8 @@ class TimeAxisViewItem : public Selectable, public PBD::ScopedConnectionList
ArdourCanvas::Rectangle* frame_handle_start; ///< `frame' (fade) handle for the start of the item, or 0 ArdourCanvas::Rectangle* frame_handle_start; ///< `frame' (fade) handle for the start of the item, or 0
ArdourCanvas::Rectangle* frame_handle_end; ///< `frame' (fade) handle for the end of the item, or 0 ArdourCanvas::Rectangle* frame_handle_end; ///< `frame' (fade) handle for the end of the item, or 0
bool frame_handle_crossing (GdkEvent*, ArdourCanvas::Rectangle*);
double _height; double _height;
Visibility visibility; Visibility visibility;
bool _recregion; bool _recregion;

View file

@ -22,6 +22,8 @@
#include "pbd/stacktrace.h" #include "pbd/stacktrace.h"
#include "ardour/profile.h" #include "ardour/profile.h"
#include "canvas/debug.h"
#include "ardour_ui.h" #include "ardour_ui.h"
#include "audio_clock.h" #include "audio_clock.h"
#include "editor.h" #include "editor.h"
@ -42,10 +44,9 @@ VerboseCursor::VerboseCursor (Editor* editor)
, _yoffset (0) , _yoffset (0)
{ {
_canvas_item = new ArdourCanvas::Text (_editor->_track_canvas->root()); _canvas_item = new ArdourCanvas::Text (_editor->_track_canvas->root());
CANVAS_DEBUG_NAME (_canvas_item, "verbose canvas cursor");
_canvas_item->set_ignore_events (true); _canvas_item->set_ignore_events (true);
_canvas_item->set_font_description (get_font_for_style (N_("VerboseCanvasCursor"))); _canvas_item->set_font_description (get_font_for_style (N_("VerboseCanvasCursor")));
// CAIROCANVAS
// _canvas_item->property_anchor() = Gtk::ANCHOR_NW;
} }
ArdourCanvas::Item * ArdourCanvas::Item *

View file

@ -220,7 +220,7 @@ class Region
bool at_natural_position () const; bool at_natural_position () const;
void move_to_natural_position (); void move_to_natural_position ();
void trim_start (framepos_t new_position); void move_start (frameoffset_t distance);
void trim_front (framepos_t new_position); void trim_front (framepos_t new_position);
void trim_end (framepos_t new_position); void trim_end (framepos_t new_position);
void trim_to (framepos_t position, framecnt_t length); void trim_to (framepos_t position, framecnt_t length);

View file

@ -698,33 +698,32 @@ Region::set_start (framepos_t pos)
} }
void void
Region::trim_start (framepos_t new_position) Region::move_start (frameoffset_t distance)
{ {
if (locked() || position_locked() || video_locked()) { if (locked() || position_locked() || video_locked()) {
return; return;
} }
framepos_t new_start; framepos_t new_start;
frameoffset_t const start_shift = new_position - _position;
if (start_shift > 0) { if (distance > 0) {
if (_start > max_framepos - start_shift) { if (_start > max_framepos - distance) {
new_start = max_framepos; new_start = max_framepos; // makes no sense
} else { } else {
new_start = _start + start_shift; new_start = _start + distance;
} }
if (!verify_start (new_start)) { if (!verify_start (new_start)) {
return; return;
} }
} else if (start_shift < 0) { } else if (distance < 0) {
if (_start < -start_shift) { if (_start < -distance) {
new_start = 0; new_start = 0;
} else { } else {
new_start = _start + start_shift; new_start = _start + distance;
} }
} else { } else {
@ -736,6 +735,7 @@ Region::trim_start (framepos_t new_position)
} }
set_start_internal (new_start); set_start_internal (new_start);
_whole_file = false; _whole_file = false;
first_edit (); first_edit ();

View file

@ -61,9 +61,10 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
{ {
#ifdef CANVAS_DEBUG #ifdef CANVAS_DEBUG
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) { if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
cerr << "CANVAS @ " << this << endl; cerr << "RENDER: " << area << endl;
dump (cerr); //cerr << "CANVAS @ " << this << endl;
cerr << "-------------------------\n"; //dump (cerr);
//cerr << "-------------------------\n";
} }
#endif #endif
@ -78,9 +79,9 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
context->set_source_rgba (random()%255 / 255.0, context->set_source_rgba (random()%255 / 255.0,
random()%255 / 255.0, random()%255 / 255.0,
random()%255 / 255.0, random()%255 / 255.0,
255); 0.3);
context->rectangle (area.x0, area.y0, area.width(), area.height()); context->rectangle (area.x0, area.y0, area.width(), area.height());
context->stroke (); context->fill ();
} }
#endif #endif
@ -119,7 +120,7 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
context->set_source_rgba (random()%255 / 255.0, context->set_source_rgba (random()%255 / 255.0,
random()%255 / 255.0, random()%255 / 255.0,
random()%255 / 255.0, random()%255 / 255.0,
255); 0.4);
context->rectangle (area.x0, area.y0, area.width(), area.height()); context->rectangle (area.x0, area.y0, area.width(), area.height());
context->fill (); context->fill ();
} }
@ -328,6 +329,11 @@ GtkCanvas::enter_leave_items ()
int x; int x;
int y; int y;
/* this version of ::enter_leave_items() is called after an item is
* added or removed, so we have no coordinates to work from as is the
* case with a motion event. Find out where the mouse is and use that.
*/
Glib::RefPtr<const Gdk::Window> pointer_window = Gdk::Display::get_default()->get_window_at_pointer (x, y); Glib::RefPtr<const Gdk::Window> pointer_window = Gdk::Display::get_default()->get_window_at_pointer (x, y);
if (pointer_window != get_window()) { if (pointer_window != get_window()) {
@ -340,18 +346,44 @@ GtkCanvas::enter_leave_items ()
void void
GtkCanvas::enter_leave_items (Duple const & point) GtkCanvas::enter_leave_items (Duple const & point)
{ {
/* find the items at the new mouse position */ /* find the items at the given position */
vector<Item const *> items; vector<Item const *> items;
_root.add_items_at_point (point, items); _root.add_items_at_point (point, items);
Item const * new_item = items.empty() ? 0 : items.back (); if (items.empty()) {
if (_current_item) {
/* leave event */
GdkEventCrossing leave_event;
leave_event.type = GDK_LEAVE_NOTIFY;
leave_event.x = point.x;
leave_event.y = point.y;
cerr << "Leaving (without entering)" << _current_item->name << endl;
_current_item->Event (reinterpret_cast<GdkEvent*> (&leave_event));
_current_item = 0;
}
return;
}
/* items is sorted from bottom to top, so reverse through it from top
* to bottom to find the first event-sensitive item and notify that
* we have entered it
*/
for (vector<Item const*>::const_reverse_iterator i = items.rbegin(); i != items.rend(); ++i) {
Item const * new_item = *i;
if (new_item->ignore_events()) {
continue;
}
if (_current_item && _current_item != new_item) { if (_current_item && _current_item != new_item) {
/* leave event */ /* leave event */
GdkEventCrossing leave_event; GdkEventCrossing leave_event;
leave_event.type = GDK_LEAVE_NOTIFY; leave_event.type = GDK_LEAVE_NOTIFY;
leave_event.x = point.x; leave_event.x = point.x;
leave_event.y = point.y; leave_event.y = point.y;
cerr << "Leaving " << _current_item->name << endl;
_current_item->Event (reinterpret_cast<GdkEvent*> (&leave_event)); _current_item->Event (reinterpret_cast<GdkEvent*> (&leave_event));
} }
@ -361,10 +393,13 @@ GtkCanvas::enter_leave_items (Duple const & point)
enter_event.type = GDK_ENTER_NOTIFY; enter_event.type = GDK_ENTER_NOTIFY;
enter_event.x = point.x; enter_event.x = point.x;
enter_event.y = point.y; enter_event.y = point.y;
cerr << "Entering (" << new_item->name << ") " << new_item->whatami() << endl;
new_item->Event (reinterpret_cast<GdkEvent*> (&enter_event)); new_item->Event (reinterpret_cast<GdkEvent*> (&enter_event));
} }
_current_item = new_item; _current_item = new_item;
break;
}
} }
/** Deliver an event to the appropriate item; either the grabbed item, or /** Deliver an event to the appropriate item; either the grabbed item, or

View file

@ -105,17 +105,31 @@ private:
#endif #endif
/** A cached, pre-rendered image of some section of a waveform.
It spans a range given relative to the start of the source
of the waveform data, so a range from N..M corresponds
to the sample range N..M within the source.
Invalidated by a changes to:
samples_per_pixel
colors
height
*/
class CacheEntry class CacheEntry
{ {
public: public:
CacheEntry (WaveView const *, int, int); CacheEntry (WaveView const *, double, double, int);
~CacheEntry (); ~CacheEntry ();
int start () const { double start () const {
return _start; return _start;
} }
int end () const { double end () const {
return _end; return _end;
} }
@ -130,9 +144,11 @@ private:
Coord position (Coord) const; Coord position (Coord) const;
WaveView const * _wave_view; WaveView const * _wave_view;
int _start;
int _end; double _start;
double _end;
int _n_peaks; int _n_peaks;
boost::shared_array<ARDOUR::PeakData> _peaks; boost::shared_array<ARDOUR::PeakData> _peaks;
Cairo::RefPtr<Cairo::ImageSurface> _image; Cairo::RefPtr<Cairo::ImageSurface> _image;
}; };

View file

@ -88,7 +88,7 @@ Group::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
if (!(*i)->visible ()) { if (!(*i)->visible ()) {
#ifdef CANVAS_DEBUG #ifdef CANVAS_DEBUG
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) { if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
cerr << _canvas->render_indent() << "Item " << (*i)->whatami() << " [" << (*i)->name << "] invisible - skipped\n"; // cerr << _canvas->render_indent() << "Item " << (*i)->whatami() << " [" << (*i)->name << "] invisible - skipped\n";
} }
#endif #endif
continue; continue;
@ -99,7 +99,7 @@ Group::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
if (!item_bbox) { if (!item_bbox) {
#ifdef CANVAS_DEBUG #ifdef CANVAS_DEBUG
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) { if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
cerr << _canvas->render_indent() << "Item " << (*i)->whatami() << " [" << (*i)->name << "] empty - skipped\n"; // cerr << _canvas->render_indent() << "Item " << (*i)->whatami() << " [" << (*i)->name << "] empty - skipped\n";
} }
#endif #endif
continue; continue;
@ -127,8 +127,8 @@ Group::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
} else { } else {
#ifdef CANVAS_DEBUG #ifdef CANVAS_DEBUG
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) { if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
cerr << string_compose ("%1skip render of %2 %3, no intersection\n", _canvas->render_indent(), (*i)->whatami(), //cerr << string_compose ("%1skip render of %2 %3, no intersection\n", _canvas->render_indent(), (*i)->whatami(),
(*i)->name); // (*i)->name);
} }
#endif #endif
} }

View file

@ -41,35 +41,33 @@ Outline::Outline (Group* parent)
void void
Outline::set_outline_color (Color color) Outline::set_outline_color (Color color)
{ {
if (color != _outline_color) {
begin_visual_change (); begin_visual_change ();
_outline_color = color; _outline_color = color;
end_visual_change (); end_visual_change ();
}
} }
void void
Outline::set_outline_width (Distance width) Outline::set_outline_width (Distance width)
{ {
if (width != _outline_width) {
begin_change (); begin_change ();
_outline_width = width; _outline_width = width;
_bounding_box_dirty = true; _bounding_box_dirty = true;
end_change (); end_change ();
}
DEBUG_TRACE (PBD::DEBUG::CanvasItemsDirtied, "canvas item dirty: outline width change\n");
} }
void void
Outline::set_outline (bool outline) Outline::set_outline (bool outline)
{ {
if (outline != _outline) {
begin_change (); begin_change ();
_outline = outline; _outline = outline;
_bounding_box_dirty = true; _bounding_box_dirty = true;
end_change (); end_change ();
}
} }
void void

View file

@ -25,6 +25,7 @@
#include "pbd/compose.h" #include "pbd/compose.h"
#include "pbd/signals.h" #include "pbd/signals.h"
#include "pbd/stacktrace.h"
#include "ardour/types.h" #include "ardour/types.h"
#include "ardour/dB.h" #include "ardour/dB.h"
@ -65,7 +66,7 @@ WaveView::WaveView (Group* parent, boost::shared_ptr<ARDOUR::AudioRegion> region
, _logscaled_independent (false) , _logscaled_independent (false)
, _gradient_depth_independent (false) , _gradient_depth_independent (false)
, _amplitude_above_axis (1.0) , _amplitude_above_axis (1.0)
, _region_start (0) , _region_start (region->start())
{ {
VisualPropertiesChanged.connect_same_thread (invalidation_connection, boost::bind (&WaveView::handle_visual_property_change, this)); VisualPropertiesChanged.connect_same_thread (invalidation_connection, boost::bind (&WaveView::handle_visual_property_change, this));
} }
@ -98,28 +99,47 @@ WaveView::handle_visual_property_change ()
void void
WaveView::set_fill_color (Color c) WaveView::set_fill_color (Color c)
{ {
if (c != _fill_color) {
invalidate_image_cache (); invalidate_image_cache ();
Fill::set_fill_color (c); Fill::set_fill_color (c);
}
} }
void void
WaveView::set_outline_color (Color c) WaveView::set_outline_color (Color c)
{ {
if (c != _outline_color) {
invalidate_image_cache (); invalidate_image_cache ();
Outline::set_outline_color (c); Outline::set_outline_color (c);
}
} }
void void
WaveView::set_samples_per_pixel (double samples_per_pixel) WaveView::set_samples_per_pixel (double samples_per_pixel)
{ {
if (samples_per_pixel != _samples_per_pixel) {
begin_change (); begin_change ();
_samples_per_pixel = samples_per_pixel; _samples_per_pixel = samples_per_pixel;
_bounding_box_dirty = true; _bounding_box_dirty = true;
end_change (); end_change ();
invalidate_whole_cache (); invalidate_whole_cache ();
}
}
static inline double
to_src_sample_offset (frameoffset_t src_sample_start, double pixel_offset, double spp)
{
return src_sample_start + (pixel_offset * spp);
}
static inline double
to_pixel_offset (frameoffset_t src_sample_start, double sample_offset, double spp)
{
return (sample_offset - src_sample_start) / spp;
} }
void void
@ -131,53 +151,91 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
return; return;
} }
/* p, start and end are offsets from the start of the source. /* These are all pixel (integer) coordinates from the left hand edge of
area is relative to the position of the region. * the waveview.
*/ */
int const start = rint (area.x0 + _region_start / _samples_per_pixel); double start = area.x0;
int const end = rint (area.x1 + _region_start / _samples_per_pixel); double const end = area.x1;
double const rend = _region->length() / _samples_per_pixel;
int p = start;
list<CacheEntry*>::iterator cache = _cache.begin (); list<CacheEntry*>::iterator cache = _cache.begin ();
while (p < end) { while ((end - start) > 1.0) {
/* Step through cache entries that end at or before our current position, p */ frameoffset_t start_sample_offset = to_src_sample_offset (_region_start, start, _samples_per_pixel);
while (cache != _cache.end() && (*cache)->end() <= p) {
/* Step through cache entries that end at or before our current position */
while (cache != _cache.end() && (*cache)->end() <= start_sample_offset) {
++cache; ++cache;
} }
/* Now either: /* Now either:
1. we have run out of cache entries 1. we have run out of cache entries
2. the one we are looking at finishes after p but also starts after p. 2. the one we are looking at finishes after start(_sample_offset) but also starts after start(_sample_offset).
3. the one we are looking at finishes after p and starts before p. 3. the one we are looking at finishes after start(_sample_offset) and starts before start(_sample_offset).
Set up a pointer to the cache entry that we will use on this iteration. Set up a pointer to the cache entry that we will use on this iteration.
*/ */
CacheEntry* render = 0; CacheEntry* image = 0;
if (cache == _cache.end ()) { if (cache == _cache.end ()) {
/* Case 1: we have run out of cache entries, so make a new one for /* Case 1: we have run out of cache entries, so make a new one for
the whole required area and put it in the list. the whole required area and put it in the list.
We would like to avoid lots of little images in the
cache, so when we create a new one, make it as wide
as possible, within a sensible limit (here, the
visible width of the canvas we're on).
However, we don't want to try to make it larger than
the region actually is, so clamp with that too.
*/ */
CacheEntry* c = new CacheEntry (this, p, end); double const endpoint = min (rend, max (end, start + _canvas->visible_area().width()));
CacheEntry* c = new CacheEntry (this,
start_sample_offset,
to_src_sample_offset (_region_start, endpoint, _samples_per_pixel),
endpoint - start);
_cache.push_back (c); _cache.push_back (c);
render = c; image = c;
} else if ((*cache)->start() > p) { } else if ((*cache)->start() > start_sample_offset) {
/* Case 2: we have a cache entry, but it starts after p, so we /* Case 2: we have a cache entry, but it starts after
need another one for the missing bit. * start(_sample_offset), so we need another one for
* the missing bit.
*
* Create a new cached image that extends as far as the
* next cached image's start, or the end of the region,
* or the end of the render area, whichever comes first.
*/ */
CacheEntry* c = new CacheEntry (this, p, min (end, (*cache)->start())); double end_pixel = min (rend, end);
double end_sample_offset = to_src_sample_offset (_region_start, end_pixel, _samples_per_pixel);
int npeaks;
if (end_sample_offset < (*cache)->start()) {
npeaks = end_pixel - start;
assert (npeaks > 0);
} else {
end_sample_offset = (*cache)->start();
end_pixel = to_pixel_offset (_region_start, end_sample_offset, _samples_per_pixel);
npeaks = end_pixel - npeaks;
assert (npeaks > 0);
}
CacheEntry* c = new CacheEntry (this,
start_sample_offset,
end_sample_offset,
npeaks);
cache = _cache.insert (cache, c); cache = _cache.insert (cache, c);
++cache; ++cache;
render = c; image = c;
} else { } else {
@ -185,29 +243,19 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
we have left, so render it. we have left, so render it.
*/ */
render = *cache; image = *cache;
++cache; ++cache;
} }
int const this_end = min (end, render->end ()); double this_end = min (end, to_pixel_offset (_region_start, image->end (), _samples_per_pixel));
double const image_origin = to_pixel_offset (_region_start, image->start(), _samples_per_pixel);
Coord const left = p - _region_start / _samples_per_pixel; context->rectangle (start, area.y0, this_end - start, area.height());
Coord const right = this_end - _region_start / _samples_per_pixel; context->set_source (image->image(), image_origin, 0);
context->fill ();
context->save (); start = this_end;
context->rectangle (left, area.y0, right, area.height());
context->clip ();
context->translate (left, 0);
context->set_source (render->image(), render->start() - p, 0);
context->paint ();
context->restore ();
p = min (end, render->end ());
} }
} }
@ -215,7 +263,7 @@ void
WaveView::compute_bounding_box () const WaveView::compute_bounding_box () const
{ {
if (_region) { if (_region) {
_bounding_box = Rect (0, 0, _region->length() / _samples_per_pixel, _height); _bounding_box = Rect (0.0, 0.0, _region->length() / _samples_per_pixel, _height);
} else { } else {
_bounding_box = boost::optional<Rect> (); _bounding_box = boost::optional<Rect> ();
} }
@ -226,6 +274,7 @@ WaveView::compute_bounding_box () const
void void
WaveView::set_height (Distance height) WaveView::set_height (Distance height)
{ {
if (height != _height) {
begin_change (); begin_change ();
_height = height; _height = height;
@ -234,11 +283,13 @@ WaveView::set_height (Distance height)
end_change (); end_change ();
invalidate_image_cache (); invalidate_image_cache ();
}
} }
void void
WaveView::set_channel (int channel) WaveView::set_channel (int channel)
{ {
if (channel != _channel) {
begin_change (); begin_change ();
_channel = channel; _channel = channel;
@ -247,12 +298,14 @@ WaveView::set_channel (int channel)
end_change (); end_change ();
invalidate_whole_cache (); invalidate_whole_cache ();
}
} }
void void
WaveView::invalidate_whole_cache () WaveView::invalidate_whole_cache ()
{ {
begin_visual_change (); begin_visual_change ();
for (list<CacheEntry*>::iterator i = _cache.begin(); i != _cache.end(); ++i) { for (list<CacheEntry*>::iterator i = _cache.begin(); i != _cache.end(); ++i) {
delete *i; delete *i;
} }
@ -274,12 +327,6 @@ WaveView::invalidate_image_cache ()
end_visual_change (); end_visual_change ();
} }
void
WaveView::region_resized ()
{
_bounding_box_dirty = true;
}
void void
WaveView::set_logscaled (bool yn) WaveView::set_logscaled (bool yn)
{ {
@ -360,31 +407,41 @@ WaveView::set_global_logscaled (bool yn)
} }
void void
WaveView::set_region_start (frameoffset_t start) WaveView::region_resized ()
{ {
_region_start = start; if (!_region) {
return;
}
/* special: do not use _region->length() here to compute
bounding box because it will already have changed.
if we have a bounding box, use it.
*/
_pre_change_bounding_box = _bounding_box;
_region_start = _region->start();
invalidate_whole_cache ();
_bounding_box_dirty = true; _bounding_box_dirty = true;
compute_bounding_box ();
end_change ();
} }
/** Construct a new CacheEntry with peak data between two offsets WaveView::CacheEntry::CacheEntry (WaveView const * wave_view, double start, double end, int npeaks)
* in the source.
*/
WaveView::CacheEntry::CacheEntry (WaveView const * wave_view, int start, int end)
: _wave_view (wave_view) : _wave_view (wave_view)
, _start (start) , _start (start)
, _end (end) , _end (end)
, _n_peaks (npeaks)
{ {
_n_peaks = _end - _start;
_peaks.reset (new PeakData[_n_peaks]); _peaks.reset (new PeakData[_n_peaks]);
_wave_view->_region->read_peaks ( _wave_view->_region->read_peaks (_peaks.get(), _n_peaks,
_peaks.get(), (framecnt_t) floor (_start),
_n_peaks, (framecnt_t) ceil (_end),
_start * _wave_view->_samples_per_pixel, _wave_view->_channel, _wave_view->_samples_per_pixel);
(_end - _start) * _wave_view->_samples_per_pixel,
_wave_view->_channel,
_wave_view->_samples_per_pixel
);
} }
WaveView::CacheEntry::~CacheEntry () WaveView::CacheEntry::~CacheEntry ()