mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
many pervasive changes primarily related to waveform drawing, particular content-dragging, colors, and more
This commit is contained in:
parent
b36e085001
commit
6f664c1f67
22 changed files with 393 additions and 278 deletions
|
|
@ -42,6 +42,7 @@
|
|||
#include "canvas/poly_line.h"
|
||||
#include "canvas/line.h"
|
||||
#include "canvas/text.h"
|
||||
#include "canvas/debug.h"
|
||||
|
||||
#include "streamview.h"
|
||||
#include "audio_region_view.h"
|
||||
|
|
@ -158,21 +159,25 @@ AudioRegionView::init (Gdk::Color const & basic_color, bool wfd)
|
|||
create_waves ();
|
||||
|
||||
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_data ("regionview", this);
|
||||
|
||||
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_data ("regionview", this);
|
||||
|
||||
if (!_recregion) {
|
||||
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_outline_color (RGBA_TO_UINT (0, 0, 0, 0));
|
||||
|
||||
fade_in_handle->set_data ("regionview", this);
|
||||
|
||||
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_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_scale ();
|
||||
|
||||
frame_handle_start->raise_to_top ();
|
||||
frame_handle_end->raise_to_top ();
|
||||
|
||||
/* XXX sync mark drag? */
|
||||
}
|
||||
|
||||
|
|
@ -360,10 +368,9 @@ AudioRegionView::region_resized (const PropertyChange& what_changed)
|
|||
interesting_stuff.add (ARDOUR::Properties::length);
|
||||
|
||||
if (what_changed.contains (interesting_stuff)) {
|
||||
|
||||
|
||||
for (uint32_t n = 0; n < waves.size(); ++n) {
|
||||
waves[n]->region_resized ();
|
||||
waves[n]->set_region_start (region()->start ());
|
||||
}
|
||||
|
||||
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) {
|
||||
(*w)->region_resized ();
|
||||
(*w)->set_region_start (region()->start ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -432,14 +438,7 @@ void
|
|||
AudioRegionView::region_muted ()
|
||||
{
|
||||
RegionView::region_muted();
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
set_waveform_colors ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -750,12 +749,14 @@ AudioRegionView::redraw_start_xfade_to (boost::shared_ptr<AudioRegion> ar, frame
|
|||
|
||||
if (!start_xfade_in) {
|
||||
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_width (1.5);
|
||||
}
|
||||
|
||||
if (!start_xfade_out) {
|
||||
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);
|
||||
start_xfade_out->set_outline_color (col);
|
||||
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) {
|
||||
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_color (ARDOUR_UI::config()->get_canvasvar_ActiveCrossfade());
|
||||
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->show ();
|
||||
start_xfade_in->raise_to_top ();
|
||||
|
||||
/* 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->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();
|
||||
}
|
||||
|
|
@ -837,6 +835,7 @@ AudioRegionView::redraw_end_xfade_to (boost::shared_ptr<AudioRegion> ar, framecn
|
|||
|
||||
if (!end_xfade_in) {
|
||||
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);
|
||||
end_xfade_in->set_outline_color (col);
|
||||
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) {
|
||||
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_width (2.0);
|
||||
}
|
||||
|
||||
if (!end_xfade_rect) {
|
||||
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_color (ARDOUR_UI::config()->get_canvasvar_ActiveCrossfade());
|
||||
end_xfade_rect->set_outline (0);
|
||||
|
|
@ -1025,16 +1026,7 @@ AudioRegionView::set_colors ()
|
|||
ARDOUR_UI::config()->get_canvasvar_GainLineInactive());
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
waves[n]->set_clip_color (ARDOUR_UI::config()->get_canvasvar_WaveFormClip());
|
||||
waves[n]->set_zero_color (ARDOUR_UI::config()->get_canvasvar_ZeroLine());
|
||||
}
|
||||
set_waveform_colors ();
|
||||
|
||||
if (start_xfade_in) {
|
||||
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;
|
||||
|
||||
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_x_position (0);
|
||||
wave->set_y_position (yoff);
|
||||
wave->set_height (ht);
|
||||
wave->set_samples_per_pixel (samples_per_pixel);
|
||||
|
|
@ -1201,8 +1194,6 @@ AudioRegionView::create_one_wave (uint32_t which, bool /*direct*/)
|
|||
// CAIROCANVAS
|
||||
// wave->property_zero_line() = true;
|
||||
|
||||
wave->set_region_start (_region->start());
|
||||
|
||||
switch (Config->get_waveform_shape()) {
|
||||
case Rectified:
|
||||
wave->set_shape (WaveView::Rectified);
|
||||
|
|
@ -1362,12 +1353,11 @@ AudioRegionView::add_ghost (TimeAxisView& tv)
|
|||
}
|
||||
|
||||
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_x_position (0);
|
||||
wave->set_samples_per_pixel (samples_per_pixel);
|
||||
wave->set_amplitude_above_axis (_amplitude_above_axis);
|
||||
wave->set_region_start (_region->start());
|
||||
|
||||
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
|
||||
AudioRegionView::set_frame_color ()
|
||||
{
|
||||
|
|
@ -1456,40 +1487,7 @@ AudioRegionView::set_frame_color ()
|
|||
|
||||
TimeAxisViewItem::set_frame_color ();
|
||||
|
||||
uint32_t wc;
|
||||
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);
|
||||
}
|
||||
}
|
||||
set_waveform_colors ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1555,6 +1553,7 @@ AudioRegionView::transients_changed ()
|
|||
while (feature_lines.size() < analysis_features.size()) {
|
||||
|
||||
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),
|
||||
ArdourCanvas::Duple (1.0, _height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE - 1));
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ class AudioRegionView : public RegionView
|
|||
void peaks_ready_handler (uint32_t);
|
||||
|
||||
void set_colors ();
|
||||
void set_waveform_colors ();
|
||||
void compute_colors (Gdk::Color const &);
|
||||
void reset_width_dependent_items (double pixel_width);
|
||||
void set_frame_color ();
|
||||
|
|
|
|||
|
|
@ -1172,9 +1172,7 @@ CrossfadeEditor::make_waves (boost::shared_ptr<AudioRegion> region, WhichFade wh
|
|||
waveview->set_outline_color (color);
|
||||
waveview->set_fill_color (color);
|
||||
|
||||
if (which == In) {
|
||||
waveview->set_region_start (region->start());
|
||||
} else {
|
||||
if (which != In) {
|
||||
waveview->set_region_start (region->start() + region->length() - xfade->length());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3731,7 +3731,7 @@ Editor::set_show_measures (bool yn)
|
|||
|
||||
compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
|
||||
draw_measures (begin, end);
|
||||
}
|
||||
}
|
||||
|
||||
instant_save ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1830,6 +1830,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
|
|||
TimeAxisView* tvp = &_primary->get_time_axis_view ();
|
||||
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*>(tvp);
|
||||
pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
|
||||
frameoffset_t frame_delta = 0;
|
||||
|
||||
if (tv && tv->is_track()) {
|
||||
speed = tv->track()->speed();
|
||||
|
|
@ -1926,27 +1927,11 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
|
|||
|
||||
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) {
|
||||
i->view->trim_contents (frame_delta, left_direction, swap_direction);
|
||||
i->view->move_contents (frame_delta);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -1960,7 +1945,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
|
|||
show_verbose_cursor_time ((framepos_t) (rv->region()->last_frame() / speed));
|
||||
break;
|
||||
case ContentsTrim:
|
||||
show_verbose_cursor_time (adjusted_current_frame (event));
|
||||
// show_verbose_cursor_time (frame_delta);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,8 +162,9 @@ Editor::compute_current_bbt_points (framepos_t leftmost, framepos_t rightmost,
|
|||
void
|
||||
Editor::hide_measures ()
|
||||
{
|
||||
if (tempo_lines)
|
||||
if (tempo_lines) {
|
||||
tempo_lines->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include "canvas/group.h"
|
||||
#include "canvas/rectangle.h"
|
||||
#include "canvas/wave_view.h"
|
||||
#include "canvas/debug.h"
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "automation_time_axis.h"
|
||||
#include "ghostregion.h"
|
||||
|
|
@ -41,9 +43,11 @@ GhostRegion::GhostRegion (ArdourCanvas::Group* parent, TimeAxisView& tv, TimeAxi
|
|||
, source_trackview (source_tv)
|
||||
{
|
||||
group = new ArdourCanvas::Group (parent);
|
||||
CANVAS_DEBUG_NAME (group, "ghost region group");
|
||||
group->set_position (ArdourCanvas::Duple (initial_pos, 0));
|
||||
|
||||
base_rect = new ArdourCanvas::Rectangle (group);
|
||||
CANVAS_DEBUG_NAME (base_rect, "ghost region rect");
|
||||
base_rect->set_x0 (0);
|
||||
base_rect->set_y0 (0);
|
||||
base_rect->set_y1 (trackview.current_height());
|
||||
|
|
@ -191,6 +195,7 @@ MidiGhostRegion::GhostEvent::GhostEvent (NoteBase* e, ArdourCanvas::Group* g)
|
|||
: event (e)
|
||||
{
|
||||
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 ()
|
||||
|
|
|
|||
|
|
@ -632,9 +632,11 @@ RegionView::region_sync_changed ()
|
|||
/* points set below */
|
||||
|
||||
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_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
|
||||
}
|
||||
|
||||
|
|
@ -930,32 +932,12 @@ RegionView::thaw_after_trim ()
|
|||
|
||||
|
||||
void
|
||||
RegionView::trim_contents (framepos_t frame_delta, bool left_direction, bool swap_direction)
|
||||
RegionView::move_contents (frameoffset_t distance)
|
||||
{
|
||||
if (_region->locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
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->move_start (distance);
|
||||
region_changed (PropertyChange (ARDOUR::Properties::start));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ class RegionView : public TimeAxisViewItem
|
|||
virtual void trim_front_ending () {}
|
||||
|
||||
bool trim_end (framepos_t, bool);
|
||||
void trim_contents (framepos_t, bool, bool);
|
||||
void move_contents (ARDOUR::frameoffset_t);
|
||||
virtual void thaw_after_trim ();
|
||||
|
||||
void set_silent_frames (const ARDOUR::AudioIntervalResult&, double threshold);
|
||||
|
|
|
|||
|
|
@ -71,8 +71,10 @@ StreamView::StreamView (RouteTimeAxisView& tv)
|
|||
canvas_rect->set (ArdourCanvas::Rect (0, 0, ArdourCanvas::COORD_MAX, tv.current_height ()));
|
||||
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_fill_color (RGBA_TO_UINT (1.0, 0, 0, 255));
|
||||
canvas_rect->set_fill (true);
|
||||
|
||||
canvas_rect->Event.connect (sigc::bind (
|
||||
sigc::mem_fun (_trackview.editor(), &PublicEditor::canvas_stream_view_event),
|
||||
|
|
|
|||
|
|
@ -47,17 +47,13 @@ TempoLines::tempo_map_changed()
|
|||
void
|
||||
TempoLines::show ()
|
||||
{
|
||||
for (Lines::iterator i = _lines.begin(); i != _lines.end(); ++i) {
|
||||
(*i)->show();
|
||||
}
|
||||
_group->show ();
|
||||
}
|
||||
|
||||
void
|
||||
TempoLines::hide ()
|
||||
{
|
||||
for (Lines::iterator i = _lines.begin(); i != _lines.end(); ++i) {
|
||||
(*i)->hide();
|
||||
}
|
||||
_group->hide ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -111,6 +107,8 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
|
|||
line->reparent (_group);
|
||||
} else {
|
||||
line = new ArdourCanvas::Line (_group);
|
||||
CANVAS_DEBUG_NAME (line, "tempo measure line");
|
||||
line->set_ignore_events (true);
|
||||
}
|
||||
|
||||
line->set_x0 (xpos);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <gtkmm2ext/selector.h>
|
||||
|
||||
#include "canvas/rectangle.h"
|
||||
#include "canvas/debug.h"
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "ardour_dialog.h"
|
||||
|
|
@ -940,13 +941,16 @@ TimeAxisView::get_selection_rect (uint32_t id)
|
|||
rect = new SelectionRect;
|
||||
|
||||
rect->rect = new ArdourCanvas::Rectangle (selection_group);
|
||||
CANVAS_DEBUG_NAME (rect->rect, "selection rect");
|
||||
rect->rect->set_outline_what (0);
|
||||
rect->rect->set_fill_color (ARDOUR_UI::config()->get_canvasvar_SelectionRect());
|
||||
|
||||
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->end_trim = new ArdourCanvas::Rectangle (selection_group);
|
||||
CANVAS_DEBUG_NAME (rect->rect, "selection rect end trim");
|
||||
rect->end_trim->set_outline_what (0);
|
||||
|
||||
free_selection_rects.push_front (rect);
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ TimeAxisViewItem::TimeAxisViewItem (const TimeAxisViewItem& other)
|
|||
ArdourCanvas::Group* parent = other.group->parent();
|
||||
|
||||
group = new ArdourCanvas::Group (parent);
|
||||
CANVAS_DEBUG_NAME (group, string_compose ("TAVI group for %1", get_item_name()));
|
||||
|
||||
_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()));
|
||||
CANVAS_DEBUG_NAME (vestigial_frame, string_compose ("vestigial frame for %1", get_item_name()));
|
||||
vestigial_frame->hide ();
|
||||
vestigial_frame->set_outline_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,
|
||||
trackview.editor().sample_to_pixel(duration),
|
||||
trackview.current_height()));
|
||||
CANVAS_DEBUG_NAME (frame, string_compose ("frame for %1", get_item_name()));
|
||||
|
||||
if (_recregion) {
|
||||
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),
|
||||
trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE,
|
||||
trackview.current_height()));
|
||||
CANVAS_DEBUG_NAME (name_highlight, string_compose ("name highlight for %1", get_item_name()));
|
||||
} else {
|
||||
name_highlight = new ArdourCanvas::Rectangle (group,
|
||||
ArdourCanvas::Rect (1.0, trackview.editor().sample_to_pixel(item_duration) - 1,
|
||||
trackview.current_height() - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE,
|
||||
trackview.current_height()));
|
||||
CANVAS_DEBUG_NAME (name_highlight, string_compose ("name highlight for %1", get_item_name()));
|
||||
}
|
||||
|
||||
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) {
|
||||
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_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;
|
||||
|
||||
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->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 {
|
||||
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_end->set_fill_color (ARDOUR_UI::config()->get_canvasvar_TrimHandleLocked());
|
||||
} else {
|
||||
frame_handle_start->set_fill_color (RGBA_TO_UINT (1, 1, 1, 0)); //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_start->set_fill_color (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 */
|
||||
double
|
||||
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
|
||||
* end of frame_handle_end, so disable the handles
|
||||
*/
|
||||
|
||||
frame_handle_start->hide();
|
||||
frame_handle_end->hide();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#define __gtk_ardour_time_axis_view_item_h__
|
||||
|
||||
#include <string>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdkmm/color.h>
|
||||
#include <pangomm/fontdescription.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_end; ///< `frame' (fade) handle for the end of the item, or 0
|
||||
|
||||
bool frame_handle_crossing (GdkEvent*, ArdourCanvas::Rectangle*);
|
||||
|
||||
double _height;
|
||||
Visibility visibility;
|
||||
bool _recregion;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
#include "pbd/stacktrace.h"
|
||||
#include "ardour/profile.h"
|
||||
|
||||
#include "canvas/debug.h"
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "audio_clock.h"
|
||||
#include "editor.h"
|
||||
|
|
@ -42,10 +44,9 @@ VerboseCursor::VerboseCursor (Editor* editor)
|
|||
, _yoffset (0)
|
||||
{
|
||||
_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_font_description (get_font_for_style (N_("VerboseCanvasCursor")));
|
||||
// CAIROCANVAS
|
||||
// _canvas_item->property_anchor() = Gtk::ANCHOR_NW;
|
||||
}
|
||||
|
||||
ArdourCanvas::Item *
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ class Region
|
|||
bool at_natural_position () const;
|
||||
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_end (framepos_t new_position);
|
||||
void trim_to (framepos_t position, framecnt_t length);
|
||||
|
|
|
|||
|
|
@ -698,33 +698,32 @@ Region::set_start (framepos_t pos)
|
|||
}
|
||||
|
||||
void
|
||||
Region::trim_start (framepos_t new_position)
|
||||
Region::move_start (frameoffset_t distance)
|
||||
{
|
||||
if (locked() || position_locked() || video_locked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
new_start = max_framepos;
|
||||
if (_start > max_framepos - distance) {
|
||||
new_start = max_framepos; // makes no sense
|
||||
} else {
|
||||
new_start = _start + start_shift;
|
||||
new_start = _start + distance;
|
||||
}
|
||||
|
||||
if (!verify_start (new_start)) {
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (start_shift < 0) {
|
||||
} else if (distance < 0) {
|
||||
|
||||
if (_start < -start_shift) {
|
||||
if (_start < -distance) {
|
||||
new_start = 0;
|
||||
} else {
|
||||
new_start = _start + start_shift;
|
||||
new_start = _start + distance;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -736,6 +735,7 @@ Region::trim_start (framepos_t new_position)
|
|||
}
|
||||
|
||||
set_start_internal (new_start);
|
||||
|
||||
_whole_file = false;
|
||||
first_edit ();
|
||||
|
||||
|
|
|
|||
|
|
@ -61,9 +61,10 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
|
|||
{
|
||||
#ifdef CANVAS_DEBUG
|
||||
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
|
||||
cerr << "CANVAS @ " << this << endl;
|
||||
dump (cerr);
|
||||
cerr << "-------------------------\n";
|
||||
cerr << "RENDER: " << area << endl;
|
||||
//cerr << "CANVAS @ " << this << endl;
|
||||
//dump (cerr);
|
||||
//cerr << "-------------------------\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -78,9 +79,9 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
|
|||
context->set_source_rgba (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->stroke ();
|
||||
context->fill ();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -119,7 +120,7 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
|
|||
context->set_source_rgba (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->fill ();
|
||||
}
|
||||
|
|
@ -327,6 +328,11 @@ GtkCanvas::enter_leave_items ()
|
|||
{
|
||||
int x;
|
||||
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);
|
||||
|
||||
|
|
@ -340,31 +346,60 @@ GtkCanvas::enter_leave_items ()
|
|||
void
|
||||
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;
|
||||
_root.add_items_at_point (point, items);
|
||||
|
||||
Item const * new_item = items.empty() ? 0 : items.back ();
|
||||
|
||||
if (_current_item && _current_item != new_item) {
|
||||
/* leave event */
|
||||
GdkEventCrossing leave_event;
|
||||
leave_event.type = GDK_LEAVE_NOTIFY;
|
||||
leave_event.x = point.x;
|
||||
leave_event.y = point.y;
|
||||
_current_item->Event (reinterpret_cast<GdkEvent*> (&leave_event));
|
||||
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;
|
||||
}
|
||||
|
||||
if (new_item && _current_item != new_item) {
|
||||
/* enter event */
|
||||
GdkEventCrossing enter_event;
|
||||
enter_event.type = GDK_ENTER_NOTIFY;
|
||||
enter_event.x = point.x;
|
||||
enter_event.y = point.y;
|
||||
new_item->Event (reinterpret_cast<GdkEvent*> (&enter_event));
|
||||
}
|
||||
/* 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
|
||||
*/
|
||||
|
||||
_current_item = new_item;
|
||||
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) {
|
||||
/* leave event */
|
||||
GdkEventCrossing leave_event;
|
||||
leave_event.type = GDK_LEAVE_NOTIFY;
|
||||
leave_event.x = point.x;
|
||||
leave_event.y = point.y;
|
||||
cerr << "Leaving " << _current_item->name << endl;
|
||||
_current_item->Event (reinterpret_cast<GdkEvent*> (&leave_event));
|
||||
}
|
||||
|
||||
if (new_item && _current_item != new_item) {
|
||||
/* enter event */
|
||||
GdkEventCrossing enter_event;
|
||||
enter_event.type = GDK_ENTER_NOTIFY;
|
||||
enter_event.x = point.x;
|
||||
enter_event.y = point.y;
|
||||
cerr << "Entering (" << new_item->name << ") " << new_item->whatami() << endl;
|
||||
new_item->Event (reinterpret_cast<GdkEvent*> (&enter_event));
|
||||
}
|
||||
|
||||
_current_item = new_item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Deliver an event to the appropriate item; either the grabbed item, or
|
||||
|
|
|
|||
|
|
@ -105,17 +105,31 @@ private:
|
|||
|
||||
#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
|
||||
{
|
||||
public:
|
||||
CacheEntry (WaveView const *, int, int);
|
||||
public:
|
||||
CacheEntry (WaveView const *, double, double, int);
|
||||
~CacheEntry ();
|
||||
|
||||
int start () const {
|
||||
double start () const {
|
||||
return _start;
|
||||
}
|
||||
|
||||
int end () const {
|
||||
double end () const {
|
||||
return _end;
|
||||
}
|
||||
|
||||
|
|
@ -130,9 +144,11 @@ private:
|
|||
Coord position (Coord) const;
|
||||
|
||||
WaveView const * _wave_view;
|
||||
int _start;
|
||||
int _end;
|
||||
int _n_peaks;
|
||||
|
||||
double _start;
|
||||
double _end;
|
||||
int _n_peaks;
|
||||
|
||||
boost::shared_array<ARDOUR::PeakData> _peaks;
|
||||
Cairo::RefPtr<Cairo::ImageSurface> _image;
|
||||
};
|
||||
|
|
@ -163,7 +179,7 @@ private:
|
|||
* value as the crossfade editor needs to alter it.
|
||||
*/
|
||||
ARDOUR::frameoffset_t _region_start;
|
||||
|
||||
|
||||
mutable std::list<CacheEntry*> _cache;
|
||||
|
||||
PBD::ScopedConnection invalidation_connection;
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ Group::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
|||
if (!(*i)->visible ()) {
|
||||
#ifdef CANVAS_DEBUG
|
||||
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
|
||||
continue;
|
||||
|
|
@ -99,7 +99,7 @@ Group::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
|||
if (!item_bbox) {
|
||||
#ifdef CANVAS_DEBUG
|
||||
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
|
||||
continue;
|
||||
|
|
@ -127,8 +127,8 @@ Group::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
|||
} else {
|
||||
#ifdef CANVAS_DEBUG
|
||||
if (DEBUG_ENABLED(PBD::DEBUG::CanvasRender)) {
|
||||
cerr << string_compose ("%1skip render of %2 %3, no intersection\n", _canvas->render_indent(), (*i)->whatami(),
|
||||
(*i)->name);
|
||||
//cerr << string_compose ("%1skip render of %2 %3, no intersection\n", _canvas->render_indent(), (*i)->whatami(),
|
||||
// (*i)->name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,35 +41,33 @@ Outline::Outline (Group* parent)
|
|||
void
|
||||
Outline::set_outline_color (Color color)
|
||||
{
|
||||
begin_visual_change ();
|
||||
|
||||
_outline_color = color;
|
||||
|
||||
end_visual_change ();
|
||||
if (color != _outline_color) {
|
||||
begin_visual_change ();
|
||||
_outline_color = color;
|
||||
end_visual_change ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Outline::set_outline_width (Distance width)
|
||||
{
|
||||
begin_change ();
|
||||
|
||||
_outline_width = width;
|
||||
|
||||
_bounding_box_dirty = true;
|
||||
end_change ();
|
||||
|
||||
DEBUG_TRACE (PBD::DEBUG::CanvasItemsDirtied, "canvas item dirty: outline width change\n");
|
||||
if (width != _outline_width) {
|
||||
begin_change ();
|
||||
_outline_width = width;
|
||||
_bounding_box_dirty = true;
|
||||
end_change ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Outline::set_outline (bool outline)
|
||||
{
|
||||
begin_change ();
|
||||
|
||||
_outline = outline;
|
||||
|
||||
_bounding_box_dirty = true;
|
||||
end_change ();
|
||||
if (outline != _outline) {
|
||||
begin_change ();
|
||||
_outline = outline;
|
||||
_bounding_box_dirty = true;
|
||||
end_change ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "pbd/compose.h"
|
||||
#include "pbd/signals.h"
|
||||
#include "pbd/stacktrace.h"
|
||||
|
||||
#include "ardour/types.h"
|
||||
#include "ardour/dB.h"
|
||||
|
|
@ -65,7 +66,7 @@ WaveView::WaveView (Group* parent, boost::shared_ptr<ARDOUR::AudioRegion> region
|
|||
, _logscaled_independent (false)
|
||||
, _gradient_depth_independent (false)
|
||||
, _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));
|
||||
}
|
||||
|
|
@ -98,28 +99,47 @@ WaveView::handle_visual_property_change ()
|
|||
void
|
||||
WaveView::set_fill_color (Color c)
|
||||
{
|
||||
invalidate_image_cache ();
|
||||
Fill::set_fill_color (c);
|
||||
if (c != _fill_color) {
|
||||
invalidate_image_cache ();
|
||||
Fill::set_fill_color (c);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WaveView::set_outline_color (Color c)
|
||||
{
|
||||
invalidate_image_cache ();
|
||||
Outline::set_outline_color (c);
|
||||
if (c != _outline_color) {
|
||||
invalidate_image_cache ();
|
||||
Outline::set_outline_color (c);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WaveView::set_samples_per_pixel (double samples_per_pixel)
|
||||
{
|
||||
begin_change ();
|
||||
if (samples_per_pixel != _samples_per_pixel) {
|
||||
begin_change ();
|
||||
|
||||
_samples_per_pixel = samples_per_pixel;
|
||||
_samples_per_pixel = samples_per_pixel;
|
||||
|
||||
_bounding_box_dirty = true;
|
||||
|
||||
end_change ();
|
||||
|
||||
invalidate_whole_cache ();
|
||||
}
|
||||
}
|
||||
|
||||
_bounding_box_dirty = true;
|
||||
end_change ();
|
||||
static inline double
|
||||
to_src_sample_offset (frameoffset_t src_sample_start, double pixel_offset, double spp)
|
||||
{
|
||||
return src_sample_start + (pixel_offset * spp);
|
||||
}
|
||||
|
||||
invalidate_whole_cache ();
|
||||
static inline double
|
||||
to_pixel_offset (frameoffset_t src_sample_start, double sample_offset, double spp)
|
||||
{
|
||||
return (sample_offset - src_sample_start) / spp;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -131,53 +151,91 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
|||
return;
|
||||
}
|
||||
|
||||
/* p, start and end are offsets from the start of the source.
|
||||
area is relative to the position of the region.
|
||||
/* These are all pixel (integer) coordinates from the left hand edge of
|
||||
* the waveview.
|
||||
*/
|
||||
|
||||
int const start = rint (area.x0 + _region_start / _samples_per_pixel);
|
||||
int const end = rint (area.x1 + _region_start / _samples_per_pixel);
|
||||
double start = area.x0;
|
||||
double const end = area.x1;
|
||||
double const rend = _region->length() / _samples_per_pixel;
|
||||
|
||||
int p = start;
|
||||
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 */
|
||||
while (cache != _cache.end() && (*cache)->end() <= p) {
|
||||
frameoffset_t start_sample_offset = to_src_sample_offset (_region_start, start, _samples_per_pixel);
|
||||
|
||||
/* Step through cache entries that end at or before our current position */
|
||||
|
||||
while (cache != _cache.end() && (*cache)->end() <= start_sample_offset) {
|
||||
++cache;
|
||||
}
|
||||
|
||||
/* Now either:
|
||||
1. we have run out of cache entries
|
||||
2. the one we are looking at finishes after p but also starts after p.
|
||||
3. the one we are looking at finishes after p and starts before 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 start(_sample_offset) and starts before start(_sample_offset).
|
||||
|
||||
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 ()) {
|
||||
|
||||
/* 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.
|
||||
|
||||
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);
|
||||
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
|
||||
need another one for the missing bit.
|
||||
*/
|
||||
/* Case 2: we have a cache entry, but it starts after
|
||||
* 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.
|
||||
*/
|
||||
|
||||
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);
|
||||
|
||||
CacheEntry* c = new CacheEntry (this, p, min (end, (*cache)->start()));
|
||||
cache = _cache.insert (cache, c);
|
||||
++cache;
|
||||
render = c;
|
||||
image = c;
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -185,29 +243,19 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
|||
we have left, so render it.
|
||||
*/
|
||||
|
||||
render = *cache;
|
||||
image = *cache;
|
||||
++cache;
|
||||
|
||||
}
|
||||
|
||||
int const this_end = min (end, render->end ());
|
||||
|
||||
Coord const left = p - _region_start / _samples_per_pixel;
|
||||
Coord const right = this_end - _region_start / _samples_per_pixel;
|
||||
|
||||
context->save ();
|
||||
|
||||
context->rectangle (left, area.y0, right, area.height());
|
||||
context->clip ();
|
||||
|
||||
context->translate (left, 0);
|
||||
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);
|
||||
|
||||
context->set_source (render->image(), render->start() - p, 0);
|
||||
context->paint ();
|
||||
context->rectangle (start, area.y0, this_end - start, area.height());
|
||||
context->set_source (image->image(), image_origin, 0);
|
||||
context->fill ();
|
||||
|
||||
context->restore ();
|
||||
|
||||
p = min (end, render->end ());
|
||||
start = this_end;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -215,7 +263,7 @@ void
|
|||
WaveView::compute_bounding_box () const
|
||||
{
|
||||
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 {
|
||||
_bounding_box = boost::optional<Rect> ();
|
||||
}
|
||||
|
|
@ -226,33 +274,38 @@ WaveView::compute_bounding_box () const
|
|||
void
|
||||
WaveView::set_height (Distance height)
|
||||
{
|
||||
begin_change ();
|
||||
|
||||
_height = height;
|
||||
|
||||
_bounding_box_dirty = true;
|
||||
end_change ();
|
||||
|
||||
invalidate_image_cache ();
|
||||
if (height != _height) {
|
||||
begin_change ();
|
||||
|
||||
_height = height;
|
||||
|
||||
_bounding_box_dirty = true;
|
||||
end_change ();
|
||||
|
||||
invalidate_image_cache ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WaveView::set_channel (int channel)
|
||||
{
|
||||
begin_change ();
|
||||
|
||||
_channel = channel;
|
||||
|
||||
_bounding_box_dirty = true;
|
||||
end_change ();
|
||||
|
||||
invalidate_whole_cache ();
|
||||
if (channel != _channel) {
|
||||
begin_change ();
|
||||
|
||||
_channel = channel;
|
||||
|
||||
_bounding_box_dirty = true;
|
||||
end_change ();
|
||||
|
||||
invalidate_whole_cache ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WaveView::invalidate_whole_cache ()
|
||||
{
|
||||
begin_visual_change ();
|
||||
|
||||
for (list<CacheEntry*>::iterator i = _cache.begin(); i != _cache.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
|
|
@ -266,7 +319,7 @@ void
|
|||
WaveView::invalidate_image_cache ()
|
||||
{
|
||||
begin_visual_change ();
|
||||
|
||||
|
||||
for (list<CacheEntry*>::iterator i = _cache.begin(); i != _cache.end(); ++i) {
|
||||
(*i)->clear_image ();
|
||||
}
|
||||
|
|
@ -274,12 +327,6 @@ WaveView::invalidate_image_cache ()
|
|||
end_visual_change ();
|
||||
}
|
||||
|
||||
void
|
||||
WaveView::region_resized ()
|
||||
{
|
||||
_bounding_box_dirty = true;
|
||||
}
|
||||
|
||||
void
|
||||
WaveView::set_logscaled (bool yn)
|
||||
{
|
||||
|
|
@ -360,31 +407,41 @@ WaveView::set_global_logscaled (bool yn)
|
|||
}
|
||||
|
||||
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;
|
||||
compute_bounding_box ();
|
||||
|
||||
end_change ();
|
||||
}
|
||||
|
||||
/** Construct a new CacheEntry with peak data between two offsets
|
||||
* in the source.
|
||||
*/
|
||||
WaveView::CacheEntry::CacheEntry (WaveView const * wave_view, int start, int end)
|
||||
WaveView::CacheEntry::CacheEntry (WaveView const * wave_view, double start, double end, int npeaks)
|
||||
: _wave_view (wave_view)
|
||||
, _start (start)
|
||||
, _end (end)
|
||||
, _n_peaks (npeaks)
|
||||
{
|
||||
_n_peaks = _end - _start;
|
||||
_peaks.reset (new PeakData[_n_peaks]);
|
||||
|
||||
_wave_view->_region->read_peaks (
|
||||
_peaks.get(),
|
||||
_n_peaks,
|
||||
_start * _wave_view->_samples_per_pixel,
|
||||
(_end - _start) * _wave_view->_samples_per_pixel,
|
||||
_wave_view->_channel,
|
||||
_wave_view->_samples_per_pixel
|
||||
);
|
||||
_wave_view->_region->read_peaks (_peaks.get(), _n_peaks,
|
||||
(framecnt_t) floor (_start),
|
||||
(framecnt_t) ceil (_end),
|
||||
_wave_view->_channel, _wave_view->_samples_per_pixel);
|
||||
}
|
||||
|
||||
WaveView::CacheEntry::~CacheEntry ()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue